gistfile1.txt
· 6.1 KiB · Text
Surowy
Adding Logo command parsing from a buffer in 6502 assembly requires handling string manipulation and tokenization. Below is an extended version of the previous code that includes a simple parser to read commands from a buffer and execute them.
### Assumptions
1. The input buffer contains a sequence of Logo commands separated by spaces or newlines.
2. Commands are in uppercase (e.g., `FORWARD 10`, `RIGHT 90`, `PENUP`).
3. The buffer is null-terminated.
### Updated 6502 Assembly Code
```assembly
; Constants
TURTLE_X = $0200 ; Turtle X position
TURTLE_Y = $0201 ; Turtle Y position
TURTLE_DIR = $0202 ; Turtle direction (0=right, 1=down, 2=left, 3=up)
PEN_STATE = $0203 ; Pen state (0=up, 1=down)
INPUT_BUFFER = $0300 ; Input buffer for commands
BUFFER_PTR = $0204 ; Pointer to current position in input buffer
; Initialize turtle and buffer pointer
LDA #$00
STA TURTLE_X ; Start at X=0
STA TURTLE_Y ; Start at Y=0
STA TURTLE_DIR ; Start facing right
STA PEN_STATE ; Start with pen down
LDA #<INPUT_BUFFER
STA BUFFER_PTR ; Initialize buffer pointer to start of input buffer
LDA #>INPUT_BUFFER
STA BUFFER_PTR+1
; Main loop
MainLoop:
JSR ReadCommand ; Read a command
JSR ExecuteCommand ; Execute the command
JMP MainLoop ; Repeat
; ReadCommand: Read a command from the input buffer
ReadCommand:
LDY #$00 ; Reset Y for buffer indexing
JSR SkipWhitespace ; Skip leading whitespace
JSR ReadToken ; Read the command token
RTS
; SkipWhitespace: Skip spaces and newlines in the buffer
SkipWhitespace:
LDA (BUFFER_PTR), Y
CMP #' ' ; Space
BEQ .NextChar
CMP #$0A ; Newline
BEQ .NextChar
RTS
.NextChar:
INY
JMP SkipWhitespace
; ReadToken: Read a token from the buffer
ReadToken:
LDX #$00 ; X will index into the token buffer
.ReadChar:
LDA (BUFFER_PTR), Y
BEQ .EndOfBuffer ; End of buffer
CMP #' ' ; Space
BEQ .EndOfToken
CMP #$0A ; Newline
BEQ .EndOfToken
STA TOKEN_BUFFER, X
INX
INY
JMP .ReadChar
.EndOfToken:
LDA #$00 ; Null-terminate the token
STA TOKEN_BUFFER, X
INY ; Move past the space/newline
RTS
.EndOfBuffer:
LDA #$00 ; Null-terminate the token
STA TOKEN_BUFFER, X
RTS
; ExecuteCommand: Execute the command in TOKEN_BUFFER
ExecuteCommand:
LDX #$00
.CompareCommand:
LDA TOKEN_BUFFER, X
CMP COMMAND_FORWARD, X
BNE .NotForward
INX
CPX #7 ; Length of "FORWARD"
BNE .CompareCommand
JSR ParseNumber ; Parse the number argument
JSR MoveForward ; Execute FORWARD command
RTS
.NotForward:
; Repeat for other commands (RIGHT, LEFT, PENUP, PENDOWN)
; Example for RIGHT:
LDX #$00
.CompareRight:
LDA TOKEN_BUFFER, X
CMP COMMAND_RIGHT, X
BNE .NotRight
INX
CPX #5 ; Length of "RIGHT"
BNE .CompareRight
JSR ParseNumber ; Parse the number argument
JSR TurnRight ; Execute RIGHT command
RTS
.NotRight:
; Add similar blocks for LEFT, PENUP, PENDOWN
RTS
; ParseNumber: Parse a number from the buffer
ParseNumber:
LDY #$00
LDA #$00
STA NUMBER ; Reset number
.ParseDigit:
LDA (BUFFER_PTR), Y
CMP #'0'
BCC .EndParse ; Not a digit
CMP #'9'+1
BCS .EndParse ; Not a digit
SEC
SBC #'0' ; Convert ASCII to number
PHA ; Save digit
LDA NUMBER
ASL A ; Multiply by 10
STA TEMP
ASL A
ASL A
CLC
ADC TEMP
ADC #$00 ; Add new digit
STA NUMBER
PLA ; Restore digit
INY
JMP .ParseDigit
.EndParse:
RTS
; MoveForward: Move the turtle forward by n steps
MoveForward:
LDX TURTLE_DIR
LDA TURTLE_X
CLC
ADC ForwardDeltaX, X
STA TURTLE_X
LDA TURTLE_Y
CLC
ADC ForwardDeltaY, X
STA TURTLE_Y
RTS
ForwardDeltaX:
.byte 1, 0, -1, 0 ; Delta X for each direction
ForwardDeltaY:
.byte 0, 1, 0, -1 ; Delta Y for each direction
; TurnRight: Turn the turtle right by d degrees
TurnRight:
LDA TURTLE_DIR
CLC
ADC #1
AND #$03 ; Wrap around after 3
STA TURTLE_DIR
RTS
; TurnLeft: Turn the turtle left by d degrees
TurnLeft:
LDA TURTLE_DIR
SEC
SBC #1
AND #$03 ; Wrap around after 3
STA TURTLE_DIR
RTS
; PenUp: Lift the pen
PenUp:
LDA #$00
STA PEN_STATE
RTS
; PenDown: Lower the pen
PenDown:
LDA #$01
STA PEN_STATE
RTS
; Data
COMMAND_FORWARD:
.byte "FORWARD", 0
COMMAND_RIGHT:
.byte "RIGHT", 0
COMMAND_LEFT:
.byte "LEFT", 0
COMMAND_PENUP:
.byte "PENUP", 0
COMMAND_PENDOWN:
.byte "PENDOWN", 0
TOKEN_BUFFER:
.res 16 ; Reserve 16 bytes for token buffer
NUMBER:
.byte 0 ; Storage for parsed number
TEMP:
.byte 0 ; Temporary storage
```
### Explanation of Changes
1. **Input Buffer**: The `INPUT_BUFFER` holds the Logo commands. The `BUFFER_PTR` keeps track of the current position in the buffer.
2. **Tokenization**: The `ReadToken` routine reads a command or argument from the buffer into `TOKEN_BUFFER`.
3. **Command Parsing**: The `ExecuteCommand` routine compares the token with known commands (`FORWARD`, `RIGHT`, etc.) and calls the appropriate subroutine.
4. **Number Parsing**: The `ParseNumber` routine converts ASCII digits in the buffer to a binary number.
5. **Command Execution**: The `MoveForward`, `TurnRight`, `TurnLeft`, `PenUp`, and `PenDown` routines implement the Logo commands.
### Example Input Buffer
If the input buffer contains:
```
FORWARD 10 RIGHT 90 FORWARD 20 PENUP
```
The program will parse and execute these commands sequentially.
### Limitations
- This implementation assumes fixed-format input (e.g., no lowercase commands).
- Error handling is minimal; invalid commands or numbers will cause undefined behavior.
- The buffer size and token buffer size are fixed and may need adjustment for larger inputs.
This code provides a basic framework for parsing and executing Logo commands in 6502 assembly. You can expand it further to handle more commands, error checking, and graphics output.
| 1 | Adding Logo command parsing from a buffer in 6502 assembly requires handling string manipulation and tokenization. Below is an extended version of the previous code that includes a simple parser to read commands from a buffer and execute them. |
| 2 | |
| 3 | ### Assumptions |
| 4 | 1. The input buffer contains a sequence of Logo commands separated by spaces or newlines. |
| 5 | 2. Commands are in uppercase (e.g., `FORWARD 10`, `RIGHT 90`, `PENUP`). |
| 6 | 3. The buffer is null-terminated. |
| 7 | |
| 8 | ### Updated 6502 Assembly Code |
| 9 | |
| 10 | ```assembly |
| 11 | ; Constants |
| 12 | TURTLE_X = $0200 ; Turtle X position |
| 13 | TURTLE_Y = $0201 ; Turtle Y position |
| 14 | TURTLE_DIR = $0202 ; Turtle direction (0=right, 1=down, 2=left, 3=up) |
| 15 | PEN_STATE = $0203 ; Pen state (0=up, 1=down) |
| 16 | INPUT_BUFFER = $0300 ; Input buffer for commands |
| 17 | BUFFER_PTR = $0204 ; Pointer to current position in input buffer |
| 18 | |
| 19 | ; Initialize turtle and buffer pointer |
| 20 | LDA #$00 |
| 21 | STA TURTLE_X ; Start at X=0 |
| 22 | STA TURTLE_Y ; Start at Y=0 |
| 23 | STA TURTLE_DIR ; Start facing right |
| 24 | STA PEN_STATE ; Start with pen down |
| 25 | LDA #<INPUT_BUFFER |
| 26 | STA BUFFER_PTR ; Initialize buffer pointer to start of input buffer |
| 27 | LDA #>INPUT_BUFFER |
| 28 | STA BUFFER_PTR+1 |
| 29 | |
| 30 | ; Main loop |
| 31 | MainLoop: |
| 32 | JSR ReadCommand ; Read a command |
| 33 | JSR ExecuteCommand ; Execute the command |
| 34 | JMP MainLoop ; Repeat |
| 35 | |
| 36 | ; ReadCommand: Read a command from the input buffer |
| 37 | ReadCommand: |
| 38 | LDY #$00 ; Reset Y for buffer indexing |
| 39 | JSR SkipWhitespace ; Skip leading whitespace |
| 40 | JSR ReadToken ; Read the command token |
| 41 | RTS |
| 42 | |
| 43 | ; SkipWhitespace: Skip spaces and newlines in the buffer |
| 44 | SkipWhitespace: |
| 45 | LDA (BUFFER_PTR), Y |
| 46 | CMP #' ' ; Space |
| 47 | BEQ .NextChar |
| 48 | CMP #$0A ; Newline |
| 49 | BEQ .NextChar |
| 50 | RTS |
| 51 | .NextChar: |
| 52 | INY |
| 53 | JMP SkipWhitespace |
| 54 | |
| 55 | ; ReadToken: Read a token from the buffer |
| 56 | ReadToken: |
| 57 | LDX #$00 ; X will index into the token buffer |
| 58 | .ReadChar: |
| 59 | LDA (BUFFER_PTR), Y |
| 60 | BEQ .EndOfBuffer ; End of buffer |
| 61 | CMP #' ' ; Space |
| 62 | BEQ .EndOfToken |
| 63 | CMP #$0A ; Newline |
| 64 | BEQ .EndOfToken |
| 65 | STA TOKEN_BUFFER, X |
| 66 | INX |
| 67 | INY |
| 68 | JMP .ReadChar |
| 69 | .EndOfToken: |
| 70 | LDA #$00 ; Null-terminate the token |
| 71 | STA TOKEN_BUFFER, X |
| 72 | INY ; Move past the space/newline |
| 73 | RTS |
| 74 | .EndOfBuffer: |
| 75 | LDA #$00 ; Null-terminate the token |
| 76 | STA TOKEN_BUFFER, X |
| 77 | RTS |
| 78 | |
| 79 | ; ExecuteCommand: Execute the command in TOKEN_BUFFER |
| 80 | ExecuteCommand: |
| 81 | LDX #$00 |
| 82 | .CompareCommand: |
| 83 | LDA TOKEN_BUFFER, X |
| 84 | CMP COMMAND_FORWARD, X |
| 85 | BNE .NotForward |
| 86 | INX |
| 87 | CPX #7 ; Length of "FORWARD" |
| 88 | BNE .CompareCommand |
| 89 | JSR ParseNumber ; Parse the number argument |
| 90 | JSR MoveForward ; Execute FORWARD command |
| 91 | RTS |
| 92 | .NotForward: |
| 93 | ; Repeat for other commands (RIGHT, LEFT, PENUP, PENDOWN) |
| 94 | ; Example for RIGHT: |
| 95 | LDX #$00 |
| 96 | .CompareRight: |
| 97 | LDA TOKEN_BUFFER, X |
| 98 | CMP COMMAND_RIGHT, X |
| 99 | BNE .NotRight |
| 100 | INX |
| 101 | CPX #5 ; Length of "RIGHT" |
| 102 | BNE .CompareRight |
| 103 | JSR ParseNumber ; Parse the number argument |
| 104 | JSR TurnRight ; Execute RIGHT command |
| 105 | RTS |
| 106 | .NotRight: |
| 107 | ; Add similar blocks for LEFT, PENUP, PENDOWN |
| 108 | RTS |
| 109 | |
| 110 | ; ParseNumber: Parse a number from the buffer |
| 111 | ParseNumber: |
| 112 | LDY #$00 |
| 113 | LDA #$00 |
| 114 | STA NUMBER ; Reset number |
| 115 | .ParseDigit: |
| 116 | LDA (BUFFER_PTR), Y |
| 117 | CMP #'0' |
| 118 | BCC .EndParse ; Not a digit |
| 119 | CMP #'9'+1 |
| 120 | BCS .EndParse ; Not a digit |
| 121 | SEC |
| 122 | SBC #'0' ; Convert ASCII to number |
| 123 | PHA ; Save digit |
| 124 | LDA NUMBER |
| 125 | ASL A ; Multiply by 10 |
| 126 | STA TEMP |
| 127 | ASL A |
| 128 | ASL A |
| 129 | CLC |
| 130 | ADC TEMP |
| 131 | ADC #$00 ; Add new digit |
| 132 | STA NUMBER |
| 133 | PLA ; Restore digit |
| 134 | INY |
| 135 | JMP .ParseDigit |
| 136 | .EndParse: |
| 137 | RTS |
| 138 | |
| 139 | ; MoveForward: Move the turtle forward by n steps |
| 140 | MoveForward: |
| 141 | LDX TURTLE_DIR |
| 142 | LDA TURTLE_X |
| 143 | CLC |
| 144 | ADC ForwardDeltaX, X |
| 145 | STA TURTLE_X |
| 146 | LDA TURTLE_Y |
| 147 | CLC |
| 148 | ADC ForwardDeltaY, X |
| 149 | STA TURTLE_Y |
| 150 | RTS |
| 151 | |
| 152 | ForwardDeltaX: |
| 153 | .byte 1, 0, -1, 0 ; Delta X for each direction |
| 154 | ForwardDeltaY: |
| 155 | .byte 0, 1, 0, -1 ; Delta Y for each direction |
| 156 | |
| 157 | ; TurnRight: Turn the turtle right by d degrees |
| 158 | TurnRight: |
| 159 | LDA TURTLE_DIR |
| 160 | CLC |
| 161 | ADC #1 |
| 162 | AND #$03 ; Wrap around after 3 |
| 163 | STA TURTLE_DIR |
| 164 | RTS |
| 165 | |
| 166 | ; TurnLeft: Turn the turtle left by d degrees |
| 167 | TurnLeft: |
| 168 | LDA TURTLE_DIR |
| 169 | SEC |
| 170 | SBC #1 |
| 171 | AND #$03 ; Wrap around after 3 |
| 172 | STA TURTLE_DIR |
| 173 | RTS |
| 174 | |
| 175 | ; PenUp: Lift the pen |
| 176 | PenUp: |
| 177 | LDA #$00 |
| 178 | STA PEN_STATE |
| 179 | RTS |
| 180 | |
| 181 | ; PenDown: Lower the pen |
| 182 | PenDown: |
| 183 | LDA #$01 |
| 184 | STA PEN_STATE |
| 185 | RTS |
| 186 | |
| 187 | ; Data |
| 188 | COMMAND_FORWARD: |
| 189 | .byte "FORWARD", 0 |
| 190 | COMMAND_RIGHT: |
| 191 | .byte "RIGHT", 0 |
| 192 | COMMAND_LEFT: |
| 193 | .byte "LEFT", 0 |
| 194 | COMMAND_PENUP: |
| 195 | .byte "PENUP", 0 |
| 196 | COMMAND_PENDOWN: |
| 197 | .byte "PENDOWN", 0 |
| 198 | |
| 199 | TOKEN_BUFFER: |
| 200 | .res 16 ; Reserve 16 bytes for token buffer |
| 201 | NUMBER: |
| 202 | .byte 0 ; Storage for parsed number |
| 203 | TEMP: |
| 204 | .byte 0 ; Temporary storage |
| 205 | ``` |
| 206 | |
| 207 | ### Explanation of Changes |
| 208 | |
| 209 | 1. **Input Buffer**: The `INPUT_BUFFER` holds the Logo commands. The `BUFFER_PTR` keeps track of the current position in the buffer. |
| 210 | 2. **Tokenization**: The `ReadToken` routine reads a command or argument from the buffer into `TOKEN_BUFFER`. |
| 211 | 3. **Command Parsing**: The `ExecuteCommand` routine compares the token with known commands (`FORWARD`, `RIGHT`, etc.) and calls the appropriate subroutine. |
| 212 | 4. **Number Parsing**: The `ParseNumber` routine converts ASCII digits in the buffer to a binary number. |
| 213 | 5. **Command Execution**: The `MoveForward`, `TurnRight`, `TurnLeft`, `PenUp`, and `PenDown` routines implement the Logo commands. |
| 214 | |
| 215 | ### Example Input Buffer |
| 216 | If the input buffer contains: |
| 217 | ``` |
| 218 | FORWARD 10 RIGHT 90 FORWARD 20 PENUP |
| 219 | ``` |
| 220 | The program will parse and execute these commands sequentially. |
| 221 | |
| 222 | ### Limitations |
| 223 | - This implementation assumes fixed-format input (e.g., no lowercase commands). |
| 224 | - Error handling is minimal; invalid commands or numbers will cause undefined behavior. |
| 225 | - The buffer size and token buffer size are fixed and may need adjustment for larger inputs. |
| 226 | |
| 227 | This code provides a basic framework for parsing and executing Logo commands in 6502 assembly. You can expand it further to handle more commands, error checking, and graphics output. |