-
Notifications
You must be signed in to change notification settings - Fork 0
/
BF6502A2.VER3B.S
232 lines (212 loc) · 8.42 KB
/
BF6502A2.VER3B.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
; Title: BrainFuck 6502 Interpreter for the Apple ][ //e
; File: BF6502A2.VER3B.S
;
: CPU: 6502
; Platform: Apple ][ //e
; By: Michael Pohoreski
; Date: Dec, 2008
; Last updated: Jul, 2015
; Description: 187 Byte Interpreter of BrainFuck
; Version 3b
; - No new functionality
; - Cleaned up source code for readability
; - Switched to Merlin directives
; License: BSD "Sharing is Caring!"
; https://github.com/Michaelangel007/brainfuck6502
;
; Discussion:
; https://groups.google.com/d/msg/comp.emulators.apple2/Om3JKqDZoEA/cwa5U1Hr3TAJ
;
; Definition:
; http://en.wikipedia.org/wiki/Brainfuck
;
; > ++pData;
; < --pData;
; + ++(*pData);
; - --(*pData);
; . putchar(*pData);
; , *pData=getchar();
; [ while (*pData) { // if( *pData == 0 ), pCode = find_same_depth ( ']' );
; ] } // if( *pData != 0 ), pCode = find_same_depth ( '[' );
;
; Reference Tests:
; http://esoteric.sange.fi/brainfuck/bf-source/prog/tests.b
;
; Examples:
; http://esoteric.sange.fi/brainfuck/bf-source/prog/
; http://esolangs.org/wiki/Brainfuck#Implementations
; http://www.muppetlabs.com/~breadbox/bf/standards.html
; http://software.xfx.net/utilities/vbbfck/index.php
; http://nesdev.parodius.com/6502.txt
; ===================================================================
; Source
; This was hand-assembled so don't blame me if this doesn't assemble.
; Well, technically you can, but I'm to lazy to fix it.
; Send me a patch and I'll try to update it.
; Merlin has a 64 char limit of OPERAND+COMMENT
; So you'll probably run into that issue
; One day you'll be able to assemble this directly inside AppleWin
OPCODE EQU $F0 ; Applesoft SPEED @ $F1, Flash mask $F3
OPFUNCPTR EQU $F8 ; Applesoft ROT @ $F9
; Applesoft Free soace $EB .. $EF
CUR_DEPTH EQU $EE ; // current nested depth
NUM_BRACKET EQU $EF ; // depth to find[]
BFPC EQU $3C ; BFPC/pCode same as A1L/H
DATA EQU $40 ; DATA/pData same as A3L/H
HGR EQU $F3D8
HGR2 EQU $F3E2
COUT EQU $FDED
RDKEY EQU $FD0C
NXTA1 EQU $FCBA
NXTA1_8 EQU $FCC2 ; standard entry point is NXTA1 = $FCBA
STOR EQU $FE0B
STOR_6 EQU $FE11 ; standard entry point is STOR = $FE0B
CLRTEXT EQU $C050
SETTEXT EQU $C051
HGR EQU $F3E2
HGR2 EQU $F3D8
RDKEY EQU $FD0C
COUT EQU $FDED ; trashes A, Y
; Used to read start address of $0806 = first Applesoft token
; If you use Applesoft as a helper text entry such as
; 0 "...brainfuck code..."
; You must manually move the BF code to $6000 via:
; CALL -151
; 6000<806.900M
; 300G
ORG $300
; STA CLRTEXT ; 8D 50 C0 ; Optional: C051 or C050
JSR HGR ; 20 D8 F3 ; Clear top 8K of data
JSR HGR2 ; 20 E2 F3 ; Clear bot 8K of data
LDY #$00 ; A0 00 ;
STY BFPC ; 84 3C ;
STY DATA ; 84 40 ;
STY CUR_DEPTH ; 84 EE ;
; Code needs to end with a zero byte
; DEFAULT: $60/$20 for big code ($6000..$BFFF = 24K) / medium data ($2000..$5FFF = 16K)
; Optional: $08/$10 for small code ($0800..$0FFF = 2K) / large data ($1000..$BFFF = 44K)
; Note: You will also need to zero memory if you use large data
LDA #$60 ; A9 60 ; Start CODE buffer
STA BFPC+1 ; 85 3D ;
LDA #$20 ; A9 20 ; Start DATA buffer
STA DATA+1 ; 85 41 ;
FETCH
LDA (BFPC),Y ; B1 3C ;
BEQ EXIT ; F0 1F ;
JSR INTERPRET ; 20 24 03 ;
JSR NXTA1_8 ; 20 C2 FC ;
LDY #$00 ; A0 00 ; because COUT trashes Y
BEQ FETCH ; F0 F2 ; branch always
INTERPRET
LDX #$07 ; A2 07 ; 8 Instructions
FIND_OP
CMP OPCODE,X ; D5 F0 ; table of opcodes (char)
BEQ EXEC ; F0 03 ;
DEX ; CA ;
BPL FIND_OP ; 10 F9 ;
RTS ; 60 ; ignore non-tokens, allows for comments
EXEC
LDA #$03 ; A9 03 ; high byte of this code address
PHA ; 48 ;
LDA OPFUNCPTR,X ; B5 F8 ; function pointer table (address)
PHA ; 48 ;
CLC ; 18 ; optimization: common code
LDA (DATA),Y ; B1 40 ; optimization: common code
EXIT
RTS ; 60 ; 1) exit to caller,
; 2) relative jsr to our bf_*(), or
; 3) exit our bf_*()
BF_NEXT
JMP STOR+6 ; 4C 11 FE ; optimization: INC A3L, BNE +2, INC A3H, RTS
BF_PREV
LDA DATA ; A5 40 ;
BNE .1 ; D0 02 ;
DEC DATA+1 ; C6 41 ;
.1
DEC DATA ; C6 40 ;
EXIT_2
RTS ; 60 ;
BF_INC
ADC #$02 ; 69 02 ; optimization: n+2-1 = n+1
CLC ; 18 ; optimization: fall-through into BF_INCDEC
BF_DEC
SBC #$00 ; E9 00 ;
STORE_DATA
LDY #$00 ; A0 00 ;
STA (DATA),Y ; 91 40 ;
RTS ; 60 ;
BF_IN
JSR RDKEY ; 20 0C FD ; trashes Y
AND #$7F ; 29 7F ; convert 8-bit Apple Text to 7-bit ASCII
BPL STORE_DATA ; 10 F4 ; always
; BrainFuck spec is ambigous -- is Return/Enter stored as 0x0D or 0x0A ?
; CMP #$0D ; C9 0D ;
; BNE STORE_DATA ; D0 F5 ;
; LDA #$0A ; A9 0A ;
; BPL STORE_DATA ; 10 F2 ; optmization: BPL BF_INCDEC (10 F4)
BF_OUT
ORA #$80 ; 09 80 ; output Hi-Bit Apple Text !
; CMP #$8A ; C9 8A ; BrainFuck spec is again ambigous
; BNE .1 ; D0 02 ; what ASCII char is newline? 0x0D 0x0A?
; LDA #8D ; A9 8D ; map newline 0A to 8D
.1
JMP COUT ; 4C ED FD ; trashes A, Y
BF_IF ; ; if( *pData == 0 ) pc = ']'
INC CUR_DEPTH ; E6 EE ; *** depth++
LDA (DATA),Y ; B1 40 ; optimization: common code
BNE EXIT_2 ; D0 E3 ; optimization: BEQ .1, therefore BNE RTS
LDA CUR_DEPTH ; A5 EE ; match_depth = depth
STA NUM_BRACKET ; 85 EF ;
.2 ; Sub-Total Bytes #101
JSR NXTA1+8 ; 20 C2 FC ; optimization: INC A1L, BNE +2, INC A1H, RTS
LDA (BFPC), Y ; B1 3C ;
CMP '[' ; C9 5B ; ***
BNE .4 ; D0 04 ;
INC NUM_BRACKET ; E6 EF ; *** inc stack
BNE .2 ; D0 F3 ;
.4
CMP ']' ; C9 5D ; ***
BNE .2 ; D0 EF ;
LDA CUR_DEPTH ; A5 EE ;
CMP NUM_BRACKET ; C5 EF ;
BEQ EXIT_2 ; F0 C8 ;
DEC NUM_BRACKET ; C6 EF ; *** dec stack
CLC ; 18 ;
BCC .2 ; 90 E4 ;
BF_FI ; ; if( *pData != 0 ) pc = '['
DEC CUR_DEPTH ; C6 EE ; depth--
LDA (DATA),Y ; B1 40 ;
BEQ EXIT_2 ; F0 BD ; optimization: BNE .1, therefore BEQ RTS
LDA CUR_DEPTH ; A5 EE ; match_depth = depth
STA NUM_BRACKET ; 85 EF ;
.2
LDA BFPC ; A5 3C ;
BNE .3 ; D0 02 ;
DEC BFPC+1 ; C6 3D ;
.3
DEC BFPC ; C6 3C ;
LDA (BFPC),Y ; B1 3C ;
CMP ']' ; C9 5D ;
BNE .4 ; D0 04 ;
DEC NUM_BRACKET ; C6 EF ; dec stack
BNE .2 ; D0 EE ;
.4
CMP '[' ; C9 5B ;
BNE .2 ; D0 EA ;
LDA CUR_DEPTH ; A5 EE ;
CMP NUM_BRACKET ; C5 EF ;
BEQ EXIT_2 ; F0 9D ;
INC NUM_BRACKET ; E6 EF ; dec stack
CLC ; 18 ;
BCC .2 ; 90 DF ;
ORG $F0
OPCODE ASC ',.[<]>-+' ; ; sorted: 2B 2C 2D 2E 3C 3E 5B 5D
OPFUNCPTR ; ; by usage: least commonly called to most
DFB BF_IN -1 ; 4D ; ,
DFB BF_OUT -1 ; 54 ; .
DFB BF_IF -1 ; 59 ; [
DFB BF_PREV-1 ; 3A ; <
DFB BF_FI -1 ; 7F ; ]
DFB BF_NEXT-1 ; 37 ; >
DFB BF_DEC -1 ; 46 ; -
DFB BF_INC -1 ; 43 ; +