├── README.md ├── basic.asm ├── basic.bin ├── config.asm ├── kernal.asm ├── smon.asm ├── smon.bin ├── uart_6522.asm ├── uart_6551.asm └── uart_6850.asm /README.md: -------------------------------------------------------------------------------- 1 | # SMON 2 | 3 | SMON is a machine language monitor and direct assembler for the Commodore 64, 4 | published in 1984 in "64'er" magazine (for more info see the [credit section](https://github.com/dhansel/smon6502#credits) below). 5 | 6 | In a nutshell, SMON provides the following functionality: 7 | - View and edit data in memory 8 | - Disassemble machine code 9 | - Write assembly code directly into memory (direkt assembler with support for labels) 10 | - Powerful search features 11 | - Moving memory, optionally with translation of absolute addresses 12 | - Trace (single-step) through code 13 | - Set breakpoint or run to a specific address and continue in single-step mode 14 | 15 | The best description of SMON's commands and capabilities is the article in the 16 | 64'er magazine (in German) [available here](https://archive.org/details/64er_sonderheft_1985_08/page/n121/mode/2up). 17 | For English speakers, C64Wiki has a brief [overview of SMON commands](https://www.c64-wiki.com/wiki/SMON). 18 | 19 | ## SMON for 6502 20 | 21 | The version published here is an adaptation of SMON for a simple MOS6502-based 22 | computer, such as the one built by [Ben Eater](https://eater.net/6502) in his 23 | [YouTube video series](https://www.youtube.com/watch?v=LnzuMJLZRdU&list=PLowKtXNTBypFbtuVMUVXNR0z1mu7dp7eH). 24 | The following original SMON functions are **not** available in this version: 25 | - Loading and saving programs/data to disk or tape (L/S/I commands) 26 | - Sending output to a printer (P command) 27 | - Producing BASIC DATA statements for memory content (B command) 28 | - Disk monitor mode and other extensions 29 | 30 | The following new commands have been added in this version 31 | - H - show a help screen with a brief overview of available commands 32 | - L - load files in Intel HEX format into the 6502 by pasting them into the terminal 33 | - MS - check and print size of installed memory 34 | - MT - test memory 35 | 36 | ## Installing and running SMON 6502 37 | 38 | If you are using Ben Eater's standard setup (16k RAM at $0-$3FFF, ACIA at $5000, VIA at $6000, ROM at $8000-$FFFF, 1MHz clock) 39 | you can just download the [smon.bin](https://github.com/dhansel/smon6502/raw/main/smon.bin) file from 40 | this repository and burn it to the EEROM. 41 | 42 | Connect your terminal or USB-to-serial converter to the 65C51N ACIA as described by Ben in his videos. 43 | 44 | Configure your terminal (program) for 9600 baud, 8 data bits, 1 stop bit and no parity. After turning 45 | on the 6502 you should see SMON showing the 6502 register contents and command prompt. 46 | 47 | If you are using a non-standard setup, SMON can easily be adapted by changing the settings 48 | in the `config.asm` file (see below). 49 | 50 | ## Basic usage 51 | 52 | At startup, SMON shows the current 6502 processor status, followed by a "." command prompt 53 | ``` 54 | PC SR AC XR YR SP NV-BDIZC 55 | ;E00B B4 E7 00 FF FF 10110100 56 | . 57 | ``` 58 | Where "PC" is the program counter, "SR" is the status register, "AC" is the accumulator, "XR" and "YR" are 59 | the X and Y registers and "SP" is the stack pointer. the "NV-BDIZC" column shows the individual bits 60 | in the status register. 61 | 62 | At the command prompt you can enter commands. For example, entering "m 1000 1020" will show the memory 63 | content from $1000-$1020: 64 | ``` 65 | .m 1000 1030 66 | :1000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ........ ........ 67 | :1010 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ........ ........ 68 | :1020 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&' ()*+,-./ 69 | ``` 70 | The column on the right shows the (printable) ASCII characters corresponding to the data bytes. 71 | 72 | If your terminal supports the VT100 cursor movement sequences, you can **modify** the memory 73 | content by just moving the cursor into the displayed lines, editing data and pressing ENTER 74 | on each line where data was modified. If your terminal does not support cursor keys you can 75 | modify memory by typing (for example) `:1015 AA BB` and pressing ENTER. The example here will 76 | set $1015 to AA and $1016 to BB. 77 | 78 | If you supply only one argument to the "m" command, SMON will show the memory content line-by-line, 79 | stopping after each line. Press SPACE to advance to the next line, ESC to go back to the command prompt 80 | or any other key to keep displaying memory without pausing (press SPACE to pause the scrolling display). 81 | 82 | The "d" (disassemble) command will disassemble code in memory, for example: 83 | ``` 84 | .d f000 85 | ,F009 A9 FF LDA #FF 86 | ,F00B A2 04 LDX #04 87 | ,F00D 95 FA STA FA,X 88 | ,F00F CA DEX 89 | ,F010 D0 FB BNE F00D 90 | ``` 91 | You can use the cursor keys to move over the displayed assembly statements and their arguments and modify 92 | them (assuming the code is in RAM). 93 | 94 | You can use the "a" (assemble) command to assemble code directly into memory. SMON will show the current 95 | address as a prompt and you can enter an assembly statement (e.g. `LDX #12`). Press ENTER and SMON will 96 | assemble it, place it directly in memory, and advance the address to the next location according to the 97 | previous opcode's size. To exit assembly mode, type "f" as the opcode. SMON will then show you the full 98 | disassembly of the code you entered, in which you can edit again. For example: 99 | ``` 100 | .a 2000 101 | 2000 ldx #00 102 | 2002 inx 103 | 2003 bne 2002 104 | 2005 brk 105 | 2006 f 106 | ,2000 A2 00 LDX #00 107 | ,2002 E8 INX 108 | ,2003 D0 FD BNE 2002 109 | ,2005 00 BRK 110 | ``` 111 | 112 | To run your code just enter `g 2000`. Note that to jump back into SMON after your code 113 | finishes, it should end with a `BRK` instruction. 114 | 115 | SMON also allows you to single-step through code using the `tw` (trace walk) command. For example: 116 | 117 | ``` 118 | PC SR AC XR YR SP NV-BDIZC 119 | ;2002 23 E7 00 FF FF 00100011 120 | .tw 2000 121 | 2002 23 E7 00 FF FF INX 122 | 2003 21 E7 01 FF FF BNE 2002 123 | 2002 21 E7 01 FF FF INX 124 | 2003 21 E7 02 FF FF BNE 2002 125 | 2002 21 E7 02 FF FF INX 126 | 2003 21 E7 03 FF FF BNE 2002 127 | ``` 128 | 129 | After entering the `tw` command, SMON executes the first opcode and stops after 130 | finishing it and displays the next opcode (the first opcode is not shown). 131 | It also shows you the processor registers in the same order as they appear in the 132 | register display line. Press any key to advance one step or ESC to stop. 133 | If the next command is a `JSR`, press 'j' to "jump" over the subroutine and 134 | continue after it finishes (this only works if the `JSR` command is located in RAM). 135 | 136 | SMON has a number of other "trace" related commands, a range of "find" 137 | commands to examine memory and several other commands. To get a quick overview 138 | of commands type "h" at the command line. For a bit more information on each command, 139 | refer to the [C64Wiki](https://www.c64-wiki.com/wiki/SMON) page or for the full description 140 | read the [64er article](https://archive.org/details/64er_sonderheft_1985_08/page/n121/mode/2up) 141 | (in German). 142 | 143 | ## New commands 144 | 145 | ### Intel HEX load 146 | 147 | This version of SMON provides the "l" (load [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX)) command to 148 | help test 6502 programs written on your PC and compiled there using a compiler such as VASM: 149 | 1. Tell your compiler to produce Intel HEX output (in VASM, use the "-Fihex" command line parameter). 150 | 2. In SMON, type "l" followed by ENTER on the command line 151 | 3. Copy-and-paste the content of the (plain text ASCII) .hex file produced by your compiler into the terminal. 152 | 153 | SMON will show a "+" for each HEX record processed. If a transmission error occurs, SMON shows 154 | a one-character error code followed by "?". Possible error codes are: 155 | - I?: Input character error - an unexpected character was received in the input 156 | - C?: Checksum error - the checksum at the end of a record did not match the expected value 157 | - M?: Memory error - After writing a byte to memory it did not read back properly (most likely attempting to write to ROM) 158 | - B?: Break - Either ESC or CTRL-C was received before the end of the transmission 159 | 160 | If no "?" is shown and SMON goes back to the command prompt then the transmission succeeded. 161 | 162 | ### Memory size and test 163 | 164 | The new "MS" (memory size) command checks memory starting at address $0100 and upwards until it finds 165 | and address where a read after write does not result in the same data. It then shows that address as 166 | the memory size. 167 | 168 | The "MT xxxx yyyy [nn]" command tests memory between $xxxx and $yyyy by writing different patterns 169 | of data to it and checking whether the data reads back the same. Each time a difference is found 170 | the corresponding address is printed. The optional "nn" parameter specifies a repetition count 171 | (defaults to 1). At the end of each test, a "+" is printed. 172 | 173 | ## Configuring SMON 6502 174 | 175 | There are three basic settings that can be changed by modifying the `config.asm` file: 176 | - RAM size (default: 16k). RAM is assumed to occupy the address space from $0 to the RAMTOP setting. 177 | For example, if you have 32K of RAM then set RAMTOP to $7FFF 178 | - VIA location (default: $6000). Change this if the location of the VIA differs from the default setting. 179 | - Clock speed (default: 1000000). Change this if your system's clock is running at a different rate 180 | than the standart 1MHz. This setting is used for UART timing. 181 | - UART driver. Communication with SMON works via RS232 protocol. The following UARTs are supported at this point: 182 | - *WCS 65C51N ACIA (default)*. This is the UART Ben Eater is using in his project. The serial parameters are 183 | set to 9600 baud, 8 data bits, 1 stop bit and no parity. You can change the serial parameters and base 184 | address for the ACIA at the top of the `uart_6551.asm` file. 185 | - *Pseudo-UART using 6522 VIA*. This emulates a UART using the 6522 VIA present in Ben Eater's design. 186 | The serial parameters can be modified at the top of `uart_6522.asm` and default to 1200 baud 8N1. 187 | Note that on a 1MHz system baud rates above 1200 may lead to corruption of received data. 188 | Connect your terminal (or serial-to-usb adapter) to the VIA as follows: 189 | - Receive (RX) pin of the terminal goes to pin 39 (CA2) of the VIA. 190 | - Transmit (TX) pin of the terminal goes to pin 40 (CA1) **and** pin 2 (PA0) of the VIA. 191 | - Make sure the VIA's pin 21 (IRQ) is connected to the 6502 CPU's pin 4 (IRQ) 192 | The RX and TX pins can also be configured at the top of `uart_6522.asm`. 193 | - *Motorola MC6850*. If you choose this UART in the config.asm file you can configure it in the `uart_6850.asm` file, 194 | most importantly the base address (default is $8100) and the serial parameters. 195 | 196 | 197 | ## Compiling SMON 6502 198 | 199 | To produce a binary file that can be programmed into an EEPROM for the 6502 computer, 200 | do the following: 201 | 1. Download the `*.asm` files from this repository (there are only 7) 202 | 2. Download the VASM compiler ([vasm6502_oldstyle_Win64.zip](http://sun.hasenbraten.de/vasm/bin/rel/vasm6502_oldstyle_Win64.zip)). 203 | 3. Extract `vasm6502_oldstyle.exe` from the archive and put it into the same directory as the .asm files 204 | 4. Issue the following command: `vasm6502_oldstyle.exe -dotdir -Fbin -o smon.bin smon.asm` 205 | 206 | Then just burn the generated smon.bin file to the EEPROM using whichever programmer 207 | you have been using. 208 | 209 | ## Running Commodore BASIC 210 | 211 | After implementing the C64 kernal functions necessary to get SMON to work I realized that 212 | the same functions are enough to run Commodore BASIC. Installing and/or compiling BASIC 213 | follows the same rules as SMON (just use `basic.bin` or `basic.asm`). 214 | 215 | Note that this is more of a toy example since only very simple BASIC programs will work 216 | (nothing with graphics or sound). Also saving or loading programs is obviously not supported. 217 | 218 | ## Credits 219 | 220 | The SMON machine language monitor was originally published in three parts in the 221 | [November](https://archive.org/details/64er_1984_11/page/n59/mode/2up) 222 | / [December](https://archive.org/details/64er_1984_12/page/n59/mode/2up) 223 | / [January](https://archive.org/details/64er_1985_01/page/n68/mode/2up) 224 | 1984/85 issues of German magazine "[64er](https://www.c64-wiki.com/wiki/64%27er)". 225 | 226 | SMON was written for the Commodore 64 by Norfried Mann and Dietrich Weineck. 227 | 228 | The [code](https://github.com/dhansel/smon6502/blob/main/smon.asm) here is based 229 | on a (partially) commented [disassembly of SMON](https://github.com/cbmuser/smon-reassembly/blob/master/smon_acme.asm) 230 | by GitHub user Michael ([cbmuser](https://github.com/cbmuser)). 231 | 232 | The [code](https://github.com/dhansel/smon6502/blob/main/uart_6522.asm) for handling RS232 communication via the 6522 VIA chip was taken 233 | and (heavily) adapted from the VIC-20 kernal, using Lee Davidson's 234 | [commented disassembly](https://www.mdawson.net/vic20chrome/vic20/docs/kernel_disassembly.txt). 235 | 236 | The [code](https://github.com/dhansel/smon6502/blob/main/uart_6551.asm) for handling RS232 communication via the 237 | 65C51N ACIA chip was put together and tested by Chris McBrien, based on the ACIA code from 238 | [Adrien Kohlbecker](https://github.com/adrienkohlbecker/65C816/blob/ep.30/software/lib/acia.a). 239 | -------------------------------------------------------------------------------- /basic.asm: -------------------------------------------------------------------------------- 1 | .include "config.asm" 2 | 3 | .org $8000 4 | 5 | ;; C64 BASIC ROM (A000-BFFF) 6 | .org $A000 7 | .byte $94,$e3,$7b,$e3,$43,$42,$4d,$42,$41,$53,$49,$43,$30,$a8,$41,$a7 8 | .byte $1d,$ad,$f7,$a8,$a4,$ab,$be,$ab,$80,$b0,$05,$ac,$a4,$a9,$9f,$a8 9 | .byte $70,$a8,$27,$a9,$1c,$a8,$82,$a8,$d1,$a8,$3a,$a9,$2e,$a8,$4a,$a9 10 | .byte $2c,$b8,$67,$e1,$55,$e1,$64,$e1,$b2,$b3,$23,$b8,$7f,$aa,$9f,$aa 11 | .byte $56,$a8,$9b,$a6,$5d,$a6,$85,$aa,$29,$e1,$bd,$e1,$c6,$e1,$7a,$ab 12 | .byte $41,$a6,$39,$bc,$cc,$bc,$58,$bc,$10,$03,$7d,$b3,$9e,$b3,$71,$bf 13 | .byte $97,$e0,$ea,$b9,$ed,$bf,$64,$e2,$6b,$e2,$b4,$e2,$0e,$e3,$0d,$b8 14 | .byte $7c,$b7,$65,$b4,$ad,$b7,$8b,$b7,$ec,$b6,$00,$b7,$2c,$b7,$37,$b7 15 | .byte $79,$69,$b8,$79,$52,$b8,$7b,$2a,$ba,$7b,$11,$bb,$7f,$7a,$bf,$50 16 | .byte $e8,$af,$46,$e5,$af,$7d,$b3,$bf,$5a,$d3,$ae,$64,$15,$b0,$45,$4e 17 | .byte $c4,$46,$4f,$d2,$4e,$45,$58,$d4,$44,$41,$54,$c1,$49,$4e,$50,$55 18 | .byte $54,$a3,$49,$4e,$50,$55,$d4,$44,$49,$cd,$52,$45,$41,$c4,$4c,$45 19 | .byte $d4,$47,$4f,$54,$cf,$52,$55,$ce,$49,$c6,$52,$45,$53,$54,$4f,$52 20 | .byte $c5,$47,$4f,$53,$55,$c2,$52,$45,$54,$55,$52,$ce,$52,$45,$cd,$53 21 | .byte $54,$4f,$d0,$4f,$ce,$57,$41,$49,$d4,$4c,$4f,$41,$c4,$53,$41,$56 22 | .byte $c5,$56,$45,$52,$49,$46,$d9,$44,$45,$c6,$50,$4f,$4b,$c5,$50,$52 23 | .byte $49,$4e,$54,$a3,$50,$52,$49,$4e,$d4,$43,$4f,$4e,$d4,$4c,$49,$53 24 | .byte $d4,$43,$4c,$d2,$43,$4d,$c4,$53,$59,$d3,$4f,$50,$45,$ce,$43,$4c 25 | .byte $4f,$53,$c5,$47,$45,$d4,$4e,$45,$d7,$54,$41,$42,$a8,$54,$cf,$46 26 | .byte $ce,$53,$50,$43,$a8,$54,$48,$45,$ce,$4e,$4f,$d4,$53,$54,$45,$d0 27 | .byte $ab,$ad,$aa,$af,$de,$41,$4e,$c4,$4f,$d2,$be,$bd,$bc,$53,$47,$ce 28 | .byte $49,$4e,$d4,$41,$42,$d3,$55,$53,$d2,$46,$52,$c5,$50,$4f,$d3,$53 29 | .byte $51,$d2,$52,$4e,$c4,$4c,$4f,$c7,$45,$58,$d0,$43,$4f,$d3,$53,$49 30 | .byte $ce,$54,$41,$ce,$41,$54,$ce,$50,$45,$45,$cb,$4c,$45,$ce,$53,$54 31 | .byte $52,$a4,$56,$41,$cc,$41,$53,$c3,$43,$48,$52,$a4,$4c,$45,$46,$54 32 | .byte $a4,$52,$49,$47,$48,$54,$a4,$4d,$49,$44,$a4,$47,$cf,$00,$54,$4f 33 | .byte $4f,$20,$4d,$41,$4e,$59,$20,$46,$49,$4c,$45,$d3,$46,$49,$4c,$45 34 | .byte $20,$4f,$50,$45,$ce,$46,$49,$4c,$45,$20,$4e,$4f,$54,$20,$4f,$50 35 | .byte $45,$ce,$46,$49,$4c,$45,$20,$4e,$4f,$54,$20,$46,$4f,$55,$4e,$c4 36 | .byte $44,$45,$56,$49,$43,$45,$20,$4e,$4f,$54,$20,$50,$52,$45,$53,$45 37 | .byte $4e,$d4,$4e,$4f,$54,$20,$49,$4e,$50,$55,$54,$20,$46,$49,$4c,$c5 38 | .byte $4e,$4f,$54,$20,$4f,$55,$54,$50,$55,$54,$20,$46,$49,$4c,$c5,$4d 39 | .byte $49,$53,$53,$49,$4e,$47,$20,$46,$49,$4c,$45,$20,$4e,$41,$4d,$c5 40 | .byte $49,$4c,$4c,$45,$47,$41,$4c,$20,$44,$45,$56,$49,$43,$45,$20,$4e 41 | .byte $55,$4d,$42,$45,$d2,$4e,$45,$58,$54,$20,$57,$49,$54,$48,$4f,$55 42 | .byte $54,$20,$46,$4f,$d2,$53,$59,$4e,$54,$41,$d8,$52,$45,$54,$55,$52 43 | .byte $4e,$20,$57,$49,$54,$48,$4f,$55,$54,$20,$47,$4f,$53,$55,$c2,$4f 44 | .byte $55,$54,$20,$4f,$46,$20,$44,$41,$54,$c1,$49,$4c,$4c,$45,$47,$41 45 | .byte $4c,$20,$51,$55,$41,$4e,$54,$49,$54,$d9,$4f,$56,$45,$52,$46,$4c 46 | .byte $4f,$d7,$4f,$55,$54,$20,$4f,$46,$20,$4d,$45,$4d,$4f,$52,$d9,$55 47 | .byte $4e,$44,$45,$46,$27,$44,$20,$53,$54,$41,$54,$45,$4d,$45,$4e,$d4 48 | .byte $42,$41,$44,$20,$53,$55,$42,$53,$43,$52,$49,$50,$d4,$52,$45,$44 49 | .byte $49,$4d,$27,$44,$20,$41,$52,$52,$41,$d9,$44,$49,$56,$49,$53,$49 50 | .byte $4f,$4e,$20,$42,$59,$20,$5a,$45,$52,$cf,$49,$4c,$4c,$45,$47,$41 51 | .byte $4c,$20,$44,$49,$52,$45,$43,$d4,$54,$59,$50,$45,$20,$4d,$49,$53 52 | .byte $4d,$41,$54,$43,$c8,$53,$54,$52,$49,$4e,$47,$20,$54,$4f,$4f,$20 53 | .byte $4c,$4f,$4e,$c7,$46,$49,$4c,$45,$20,$44,$41,$54,$c1,$46,$4f,$52 54 | .byte $4d,$55,$4c,$41,$20,$54,$4f,$4f,$20,$43,$4f,$4d,$50,$4c,$45,$d8 55 | .byte $43,$41,$4e,$27,$54,$20,$43,$4f,$4e,$54,$49,$4e,$55,$c5,$55,$4e 56 | .byte $44,$45,$46,$27,$44,$20,$46,$55,$4e,$43,$54,$49,$4f,$ce,$56,$45 57 | .byte $52,$49,$46,$d9,$4c,$4f,$41,$c4,$9e,$a1,$ac,$a1,$b5,$a1,$c2,$a1 58 | .byte $d0,$a1,$e2,$a1,$f0,$a1,$ff,$a1,$10,$a2,$25,$a2,$35,$a2,$3b,$a2 59 | .byte $4f,$a2,$5a,$a2,$6a,$a2,$72,$a2,$7f,$a2,$90,$a2,$9d,$a2,$aa,$a2 60 | .byte $ba,$a2,$c8,$a2,$d5,$a2,$e4,$a2,$ed,$a2,$00,$a3,$0e,$a3,$1e,$a3 61 | .byte $24,$a3,$83,$a3,$0d,$4f,$4b,$0d,$00,$20,$20,$45,$52,$52,$4f,$52 62 | .byte $00,$20,$49,$4e,$20,$00,$0d,$0a,$52,$45,$41,$44,$59,$2e,$0d,$0a 63 | .byte $00,$0d,$0a,$42,$52,$45,$41,$4b,$00,$a0,$ba,$e8,$e8,$e8,$e8,$bd 64 | .byte $01,$01,$c9,$81,$d0,$21,$a5,$4a,$d0,$0a,$bd,$02,$01,$85,$49,$bd 65 | .byte $03,$01,$85,$4a,$dd,$03,$01,$d0,$07,$a5,$49,$dd,$02,$01,$f0,$07 66 | .byte $8a,$18,$69,$12,$aa,$d0,$d8,$60,$20,$08,$a4,$85,$31,$84,$32,$38 67 | .byte $a5,$5a,$e5,$5f,$85,$22,$a8,$a5,$5b,$e5,$60,$aa,$e8,$98,$f0,$23 68 | .byte $a5,$5a,$38,$e5,$22,$85,$5a,$b0,$03,$c6,$5b,$38,$a5,$58,$e5,$22 69 | .byte $85,$58,$b0,$08,$c6,$59,$90,$04,$b1,$5a,$91,$58,$88,$d0,$f9,$b1 70 | .byte $5a,$91,$58,$c6,$5b,$c6,$59,$ca,$d0,$f2,$60,$0a,$69,$3e,$b0,$35 71 | .byte $85,$22,$ba,$e4,$22,$90,$2e,$60,$c4,$34,$90,$28,$d0,$04,$c5,$33 72 | .byte $90,$22,$48,$a2,$09,$98,$48,$b5,$57,$ca,$10,$fa,$20,$26,$b5,$a2 73 | .byte $f7,$68,$95,$61,$e8,$30,$fa,$68,$a8,$68,$c4,$34,$90,$06,$d0,$05 74 | .byte $c5,$33,$b0,$01,$60,$a2,$10,$6c,$00,$03,$8a,$0a,$aa,$bd,$26,$a3 75 | .byte $85,$22,$bd,$27,$a3,$85,$23,$20,$cc,$ff,$a9,$00,$85,$13,$20,$d7 76 | .byte $aa,$20,$45,$ab,$a0,$00,$b1,$22,$48,$29,$7f,$20,$47,$ab,$c8,$68 77 | .byte $10,$f4,$20,$7a,$a6,$a9,$69,$a0,$a3,$20,$1e,$ab,$a4,$3a,$c8,$f0 78 | .byte $03,$20,$c2,$bd,$a9,$76,$a0,$a3,$20,$1e,$ab,$a9,$80,$20,$90,$ff 79 | .byte $6c,$02,$03,$20,$60,$a5,$86,$7a,$84,$7b,$20,$73,$00,$aa,$f0,$f0 80 | .byte $a2,$ff,$86,$3a,$90,$06,$20,$79,$a5,$4c,$e1,$a7,$20,$6b,$a9,$20 81 | .byte $79,$a5,$84,$0b,$20,$13,$a6,$90,$44,$a0,$01,$b1,$5f,$85,$23,$a5 82 | .byte $2d,$85,$22,$a5,$60,$85,$25,$a5,$5f,$88,$f1,$5f,$18,$65,$2d,$85 83 | .byte $2d,$85,$24,$a5,$2e,$69,$ff,$85,$2e,$e5,$60,$aa,$38,$a5,$5f,$e5 84 | .byte $2d,$a8,$b0,$03,$e8,$c6,$25,$18,$65,$22,$90,$03,$c6,$23,$18,$b1 85 | .byte $22,$91,$24,$c8,$d0,$f9,$e6,$23,$e6,$25,$ca,$d0,$f2,$20,$59,$a6 86 | .byte $20,$33,$a5,$ad,$00,$02,$f0,$88,$18,$a5,$2d,$85,$5a,$65,$0b,$85 87 | .byte $58,$a4,$2e,$84,$5b,$90,$01,$c8,$84,$59,$20,$b8,$a3,$a5,$14,$a4 88 | .byte $15,$8d,$fe,$01,$8c,$ff,$01,$a5,$31,$a4,$32,$85,$2d,$84,$2e,$a4 89 | .byte $0b,$88,$b9,$fc,$01,$91,$5f,$88,$10,$f8,$20,$59,$a6,$20,$33,$a5 90 | .byte $4c,$80,$a4,$a5,$2b,$a4,$2c,$85,$22,$84,$23,$18,$a0,$01,$b1,$22 91 | .byte $f0,$1d,$a0,$04,$c8,$b1,$22,$d0,$fb,$c8,$98,$65,$22,$aa,$a0,$00 92 | .byte $91,$22,$a5,$23,$69,$00,$c8,$91,$22,$86,$22,$85,$23,$90,$dd,$60 93 | .byte $a2,$00,$20,$12,$e1,$c9,$0d,$f0,$0d,$9d,$00,$02,$e8,$e0,$59,$90 94 | .byte $f1,$a2,$17,$4c,$37,$a4,$4c,$ca,$aa,$6c,$04,$03,$a6,$7a,$a0,$04 95 | .byte $84,$0f,$bd,$00,$02,$10,$07,$c9,$ff,$f0,$3e,$e8,$d0,$f4,$c9,$20 96 | .byte $f0,$37,$85,$08,$c9,$22,$f0,$56,$24,$0f,$70,$2d,$c9,$3f,$d0,$04 97 | .byte $a9,$99,$d0,$25,$c9,$30,$90,$04,$c9,$3c,$90,$1d,$84,$71,$a0,$00 98 | .byte $84,$0b,$88,$86,$7a,$ca,$c8,$e8,$bd,$00,$02,$38,$f9,$9e,$a0,$f0 99 | .byte $f5,$c9,$80,$d0,$30,$05,$0b,$a4,$71,$e8,$c8,$99,$fb,$01,$b9,$fb 100 | .byte $01,$f0,$36,$38,$e9,$3a,$f0,$04,$c9,$49,$d0,$02,$85,$0f,$38,$e9 101 | .byte $55,$d0,$9f,$85,$08,$bd,$00,$02,$f0,$df,$c5,$08,$f0,$db,$c8,$99 102 | .byte $fb,$01,$e8,$d0,$f0,$a6,$7a,$e6,$0b,$c8,$b9,$9d,$a0,$10,$fa,$b9 103 | .byte $9e,$a0,$d0,$b4,$bd,$00,$02,$10,$be,$99,$fd,$01,$c6,$7b,$a9,$ff 104 | .byte $85,$7a,$60,$a5,$2b,$a6,$2c,$a0,$01,$85,$5f,$86,$60,$b1,$5f,$f0 105 | .byte $1f,$c8,$c8,$a5,$15,$d1,$5f,$90,$18,$f0,$03,$88,$d0,$09,$a5,$14 106 | .byte $88,$d1,$5f,$90,$0c,$f0,$0a,$88,$b1,$5f,$aa,$88,$b1,$5f,$b0,$d7 107 | .byte $18,$60,$d0,$fd,$a9,$00,$a8,$91,$2b,$c8,$91,$2b,$a5,$2b,$18,$69 108 | .byte $02,$85,$2d,$a5,$2c,$69,$00,$85,$2e,$20,$8e,$a6,$a9,$00,$d0,$2d 109 | .byte $20,$e7,$ff,$a5,$37,$a4,$38,$85,$33,$84,$34,$a5,$2d,$a4,$2e,$85 110 | .byte $2f,$84,$30,$85,$31,$84,$32,$20,$1d,$a8,$a2,$19,$86,$16,$68,$a8 111 | .byte $68,$a2,$fa,$9a,$48,$98,$48,$a9,$00,$85,$3e,$85,$10,$60,$18,$a5 112 | .byte $2b,$69,$ff,$85,$7a,$a5,$2c,$69,$ff,$85,$7b,$60,$90,$06,$f0,$04 113 | .byte $c9,$ab,$d0,$e9,$20,$6b,$a9,$20,$13,$a6,$20,$79,$00,$f0,$0c,$c9 114 | .byte $ab,$d0,$8e,$20,$73,$00,$20,$6b,$a9,$d0,$86,$68,$68,$a5,$14,$05 115 | .byte $15,$d0,$06,$a9,$ff,$85,$14,$85,$15,$a0,$01,$84,$0f,$b1,$5f,$f0 116 | .byte $43,$20,$2c,$a8,$20,$d7,$aa,$c8,$b1,$5f,$aa,$c8,$b1,$5f,$c5,$15 117 | .byte $d0,$04,$e4,$14,$f0,$02,$b0,$2c,$84,$49,$20,$cd,$bd,$a9,$20,$a4 118 | .byte $49,$29,$7f,$20,$47,$ab,$c9,$22,$d0,$06,$a5,$0f,$49,$ff,$85,$0f 119 | .byte $c8,$f0,$11,$b1,$5f,$d0,$10,$a8,$b1,$5f,$aa,$c8,$b1,$5f,$86,$5f 120 | .byte $85,$60,$d0,$b5,$4c,$86,$e3,$6c,$06,$03,$10,$d7,$c9,$ff,$f0,$d3 121 | .byte $24,$0f,$30,$cf,$38,$e9,$7f,$aa,$84,$49,$a0,$ff,$ca,$f0,$08,$c8 122 | .byte $b9,$9e,$a0,$10,$fa,$30,$f5,$c8,$b9,$9e,$a0,$30,$b2,$20,$47,$ab 123 | .byte $d0,$f5,$a9,$80,$85,$10,$20,$a5,$a9,$20,$8a,$a3,$d0,$05,$8a,$69 124 | .byte $0f,$aa,$9a,$68,$68,$a9,$09,$20,$fb,$a3,$20,$06,$a9,$18,$98,$65 125 | .byte $7a,$48,$a5,$7b,$69,$00,$48,$a5,$3a,$48,$a5,$39,$48,$a9,$a4,$20 126 | .byte $ff,$ae,$20,$8d,$ad,$20,$8a,$ad,$a5,$66,$09,$7f,$25,$62,$85,$62 127 | .byte $a9,$8b,$a0,$a7,$85,$22,$84,$23,$4c,$43,$ae,$a9,$bc,$a0,$b9,$20 128 | .byte $a2,$bb,$20,$79,$00,$c9,$a9,$d0,$06,$20,$73,$00,$20,$8a,$ad,$20 129 | .byte $2b,$bc,$20,$38,$ae,$a5,$4a,$48,$a5,$49,$48,$a9,$81,$48,$20,$2c 130 | .byte $a8,$a5,$7a,$a4,$7b,$c0,$02,$ea,$f0,$04,$85,$3d,$84,$3e,$a0,$00 131 | .byte $b1,$7a,$d0,$43,$a0,$02,$b1,$7a,$18,$d0,$03,$4c,$4b,$a8,$c8,$b1 132 | .byte $7a,$85,$39,$c8,$b1,$7a,$85,$3a,$98,$65,$7a,$85,$7a,$90,$02,$e6 133 | .byte $7b,$6c,$08,$03,$20,$73,$00,$20,$ed,$a7,$4c,$ae,$a7,$f0,$3c,$e9 134 | .byte $80,$90,$11,$c9,$23,$b0,$17,$0a,$a8,$b9,$0d,$a0,$48,$b9,$0c,$a0 135 | .byte $48,$4c,$73,$00,$4c,$a5,$a9,$c9,$3a,$f0,$d6,$4c,$08,$af,$c9,$4b 136 | .byte $d0,$f9,$20,$73,$00,$a9,$a4,$20,$ff,$ae,$4c,$a0,$a8,$38,$a5,$2b 137 | .byte $e9,$01,$a4,$2c,$b0,$01,$88,$85,$41,$84,$42,$60,$20,$e1,$ff,$b0 138 | .byte $01,$18,$d0,$3c,$a5,$7a,$a4,$7b,$a6,$3a,$e8,$f0,$0c,$85,$3d,$84 139 | .byte $3e,$a5,$39,$a4,$3a,$85,$3b,$84,$3c,$68,$68,$a9,$81,$a0,$a3,$90 140 | .byte $03,$4c,$69,$a4,$4c,$86,$e3,$d0,$17,$a2,$1a,$a4,$3e,$d0,$03,$4c 141 | .byte $37,$a4,$a5,$3d,$85,$7a,$84,$7b,$a5,$3b,$a4,$3c,$85,$39,$84,$3a 142 | .byte $60,$08,$a9,$00,$20,$90,$ff,$28,$d0,$03,$4c,$59,$a6,$20,$60,$a6 143 | .byte $4c,$97,$a8,$a9,$03,$20,$fb,$a3,$a5,$7b,$48,$a5,$7a,$48,$a5,$3a 144 | .byte $48,$a5,$39,$48,$a9,$8d,$48,$20,$79,$00,$20,$a0,$a8,$4c,$ae,$a7 145 | .byte $20,$6b,$a9,$20,$09,$a9,$38,$a5,$39,$e5,$14,$a5,$3a,$e5,$15,$b0 146 | .byte $0b,$98,$38,$65,$7a,$a6,$7b,$90,$07,$e8,$b0,$04,$a5,$2b,$a6,$2c 147 | .byte $20,$17,$a6,$90,$1e,$a5,$5f,$e9,$01,$85,$7a,$a5,$60,$e9,$00,$85 148 | .byte $7b,$60,$d0,$fd,$a9,$ff,$85,$4a,$20,$8a,$a3,$9a,$c9,$8d,$f0,$0b 149 | .byte $a2,$0c,$2c,$a2,$11,$4c,$37,$a4,$4c,$08,$af,$68,$68,$85,$39,$68 150 | .byte $85,$3a,$68,$85,$7a,$68,$85,$7b,$20,$06,$a9,$98,$18,$65,$7a,$85 151 | .byte $7a,$90,$02,$e6,$7b,$60,$a2,$3a,$2c,$a2,$00,$86,$07,$a0,$00,$84 152 | .byte $08,$a5,$08,$a6,$07,$85,$07,$86,$08,$b1,$7a,$f0,$e8,$c5,$08,$f0 153 | .byte $e4,$c8,$c9,$22,$d0,$f3,$f0,$e9,$20,$9e,$ad,$20,$79,$00,$c9,$89 154 | .byte $f0,$05,$a9,$a7,$20,$ff,$ae,$a5,$61,$d0,$05,$20,$09,$a9,$f0,$bb 155 | .byte $20,$79,$00,$b0,$03,$4c,$a0,$a8,$4c,$ed,$a7,$20,$9e,$b7,$48,$c9 156 | .byte $8d,$f0,$04,$c9,$89,$d0,$91,$c6,$65,$d0,$04,$68,$4c,$ef,$a7,$20 157 | .byte $73,$00,$20,$6b,$a9,$c9,$2c,$f0,$ee,$68,$60,$a2,$00,$86,$14,$86 158 | .byte $15,$b0,$f7,$e9,$2f,$85,$07,$a5,$15,$85,$22,$c9,$19,$b0,$d4,$a5 159 | .byte $14,$0a,$26,$22,$0a,$26,$22,$65,$14,$85,$14,$a5,$22,$65,$15,$85 160 | .byte $15,$06,$14,$26,$15,$a5,$14,$65,$07,$85,$14,$90,$02,$e6,$15,$20 161 | .byte $73,$00,$4c,$71,$a9,$20,$8b,$b0,$85,$49,$84,$4a,$a9,$b2,$20,$ff 162 | .byte $ae,$a5,$0e,$48,$a5,$0d,$48,$20,$9e,$ad,$68,$2a,$20,$90,$ad,$d0 163 | .byte $18,$68,$10,$12,$20,$1b,$bc,$20,$bf,$b1,$a0,$00,$a5,$64,$91,$49 164 | .byte $c8,$a5,$65,$91,$49,$60,$4c,$d0,$bb,$68,$a4,$4a,$c0,$bf,$d0,$4c 165 | .byte $20,$a6,$b6,$c9,$06,$d0,$3d,$a0,$00,$84,$61,$84,$66,$84,$71,$20 166 | .byte $1d,$aa,$20,$e2,$ba,$e6,$71,$a4,$71,$20,$1d,$aa,$20,$0c,$bc,$aa 167 | .byte $f0,$05,$e8,$8a,$20,$ed,$ba,$a4,$71,$c8,$c0,$06,$d0,$df,$20,$e2 168 | .byte $ba,$20,$9b,$bc,$a6,$64,$a4,$63,$a5,$65,$4c,$db,$ff,$b1,$22,$20 169 | .byte $80,$00,$90,$03,$4c,$48,$b2,$e9,$2f,$4c,$7e,$bd,$a0,$02,$b1,$64 170 | .byte $c5,$34,$90,$17,$d0,$07,$88,$b1,$64,$c5,$33,$90,$0e,$a4,$65,$c4 171 | .byte $2e,$90,$08,$d0,$0d,$a5,$64,$c5,$2d,$b0,$07,$a5,$64,$a4,$65,$4c 172 | .byte $68,$aa,$a0,$00,$b1,$64,$20,$75,$b4,$a5,$50,$a4,$51,$85,$6f,$84 173 | .byte $70,$20,$7a,$b6,$a9,$61,$a0,$00,$85,$50,$84,$51,$20,$db,$b6,$a0 174 | .byte $00,$b1,$50,$91,$49,$c8,$b1,$50,$91,$49,$c8,$b1,$50,$91,$49,$60 175 | .byte $20,$86,$aa,$4c,$b5,$ab,$20,$9e,$b7,$f0,$05,$a9,$2c,$20,$ff,$ae 176 | .byte $08,$86,$13,$20,$18,$e1,$28,$4c,$a0,$aa,$20,$21,$ab,$20,$79,$00 177 | .byte $f0,$35,$f0,$43,$c9,$a3,$f0,$50,$c9,$a6,$18,$f0,$4b,$c9,$2c,$f0 178 | .byte $37,$c9,$3b,$f0,$5e,$20,$9e,$ad,$24,$0d,$30,$de,$20,$dd,$bd,$20 179 | .byte $87,$b4,$20,$21,$ab,$20,$3b,$ab,$d0,$d3,$a9,$00,$9d,$00,$02,$a2 180 | .byte $ff,$a0,$01,$a5,$13,$d0,$10,$a9,$0d,$20,$47,$ab,$24,$13,$10,$05 181 | .byte $a9,$0a,$20,$47,$ab,$49,$ff,$60,$38,$20,$f0,$ff,$98,$38,$e9,$0a 182 | .byte $b0,$fc,$49,$ff,$69,$01,$d0,$16,$08,$38,$20,$f0,$ff,$84,$09,$20 183 | .byte $9b,$b7,$c9,$29,$d0,$59,$28,$90,$06,$8a,$e5,$09,$90,$05,$aa,$e8 184 | .byte $ca,$d0,$06,$20,$73,$00,$4c,$a2,$aa,$20,$3b,$ab,$d0,$f2,$20,$87 185 | .byte $b4,$20,$a6,$b6,$aa,$a0,$00,$e8,$ca,$f0,$bc,$b1,$22,$20,$47,$ab 186 | .byte $c8,$c9,$0d,$d0,$f3,$20,$e5,$aa,$4c,$28,$ab,$a5,$13,$f0,$03,$a9 187 | .byte $20,$2c,$a9,$1d,$2c,$a9,$3f,$20,$0c,$e1,$29,$ff,$60,$a5,$11,$f0 188 | .byte $11,$30,$04,$a0,$ff,$d0,$04,$a5,$3f,$a4,$40,$85,$39,$84,$3a,$4c 189 | .byte $08,$af,$a5,$13,$f0,$05,$a2,$18,$4c,$37,$a4,$a9,$0c,$a0,$ad,$20 190 | .byte $1e,$ab,$a5,$3d,$a4,$3e,$85,$7a,$84,$7b,$60,$20,$a6,$b3,$c9,$23 191 | .byte $d0,$10,$20,$73,$00,$20,$9e,$b7,$a9,$2c,$20,$ff,$ae,$86,$13,$20 192 | .byte $1e,$e1,$a2,$01,$a0,$02,$a9,$00,$8d,$01,$02,$a9,$40,$20,$0f,$ac 193 | .byte $a6,$13,$d0,$13,$60,$20,$9e,$b7,$a9,$2c,$20,$ff,$ae,$86,$13,$20 194 | .byte $1e,$e1,$20,$ce,$ab,$a5,$13,$20,$cc,$ff,$a2,$00,$86,$13,$60,$c9 195 | .byte $22,$d0,$0b,$20,$bd,$ae,$a9,$3b,$20,$ff,$ae,$20,$21,$ab,$20,$a6 196 | .byte $b3,$a9,$2c,$8d,$ff,$01,$20,$f9,$ab,$a5,$13,$f0,$0d,$20,$b7,$ff 197 | .byte $29,$02,$f0,$06,$20,$b5,$ab,$4c,$f8,$a8,$ad,$00,$02,$d0,$1e,$a5 198 | .byte $13,$d0,$e3,$20,$06,$a9,$4c,$fb,$a8,$a5,$13,$d0,$06,$20,$45,$ab 199 | .byte $20,$3b,$ab,$4c,$60,$a5,$a6,$41,$a4,$42,$a9,$98,$2c,$a9,$00,$85 200 | .byte $11,$86,$43,$84,$44,$20,$8b,$b0,$85,$49,$84,$4a,$a5,$7a,$a4,$7b 201 | .byte $85,$4b,$84,$4c,$a6,$43,$a4,$44,$86,$7a,$84,$7b,$20,$79,$00,$d0 202 | .byte $20,$24,$11,$50,$0c,$20,$24,$e1,$8d,$00,$02,$a2,$ff,$a0,$01,$d0 203 | .byte $0c,$30,$75,$a5,$13,$d0,$03,$20,$45,$ab,$20,$f9,$ab,$86,$7a,$84 204 | .byte $7b,$20,$73,$00,$24,$0d,$10,$31,$24,$11,$50,$09,$e8,$86,$7a,$a9 205 | .byte $00,$85,$07,$f0,$0c,$85,$07,$c9,$22,$f0,$07,$a9,$3a,$85,$07,$a9 206 | .byte $2c,$18,$85,$08,$a5,$7a,$a4,$7b,$69,$00,$90,$01,$c8,$20,$8d,$b4 207 | .byte $20,$e2,$b7,$20,$da,$a9,$4c,$91,$ac,$20,$f3,$bc,$a5,$0e,$20,$c2 208 | .byte $a9,$20,$79,$00,$f0,$07,$c9,$2c,$f0,$03,$4c,$4d,$ab,$a5,$7a,$a4 209 | .byte $7b,$85,$43,$84,$44,$a5,$4b,$a4,$4c,$85,$7a,$84,$7b,$20,$79,$00 210 | .byte $f0,$2d,$20,$fd,$ae,$4c,$15,$ac,$20,$06,$a9,$c8,$aa,$d0,$12,$a2 211 | .byte $0d,$c8,$b1,$7a,$f0,$6c,$c8,$b1,$7a,$85,$3f,$c8,$b1,$7a,$c8,$85 212 | .byte $40,$20,$fb,$a8,$20,$79,$00,$aa,$e0,$83,$d0,$dc,$4c,$51,$ac,$a5 213 | .byte $43,$a4,$44,$a6,$11,$10,$03,$4c,$27,$a8,$a0,$00,$b1,$43,$f0,$0b 214 | .byte $a5,$13,$d0,$07,$a9,$fc,$a0,$ac,$4c,$1e,$ab,$60,$3f,$45,$58,$54 215 | .byte $52,$41,$20,$49,$47,$4e,$4f,$52,$45,$44,$0d,$00,$3f,$52,$45,$44 216 | .byte $4f,$20,$46,$52,$4f,$4d,$20,$53,$54,$41,$52,$54,$0d,$00,$d0,$04 217 | .byte $a0,$00,$f0,$03,$20,$8b,$b0,$85,$49,$84,$4a,$20,$8a,$a3,$f0,$05 218 | .byte $a2,$0a,$4c,$37,$a4,$9a,$8a,$18,$69,$04,$48,$69,$06,$85,$24,$68 219 | .byte $a0,$01,$20,$a2,$bb,$ba,$bd,$09,$01,$85,$66,$a5,$49,$a4,$4a,$20 220 | .byte $67,$b8,$20,$d0,$bb,$a0,$01,$20,$5d,$bc,$ba,$38,$fd,$09,$01,$f0 221 | .byte $17,$bd,$0f,$01,$85,$39,$bd,$10,$01,$85,$3a,$bd,$12,$01,$85,$7a 222 | .byte $bd,$11,$01,$85,$7b,$4c,$ae,$a7,$8a,$69,$11,$aa,$9a,$20,$79,$00 223 | .byte $c9,$2c,$d0,$f1,$20,$73,$00,$20,$24,$ad,$20,$9e,$ad,$18,$24,$38 224 | .byte $24,$0d,$30,$03,$b0,$03,$60,$b0,$fd,$a2,$16,$4c,$37,$a4,$a6,$7a 225 | .byte $d0,$02,$c6,$7b,$c6,$7a,$a2,$00,$24,$48,$8a,$48,$a9,$01,$20,$fb 226 | .byte $a3,$20,$83,$ae,$a9,$00,$85,$4d,$20,$79,$00,$38,$e9,$b1,$90,$17 227 | .byte $c9,$03,$b0,$13,$c9,$01,$2a,$49,$01,$45,$4d,$c5,$4d,$90,$61,$85 228 | .byte $4d,$20,$73,$00,$4c,$bb,$ad,$a6,$4d,$d0,$2c,$b0,$7b,$69,$07,$90 229 | .byte $77,$65,$0d,$d0,$03,$4c,$3d,$b6,$69,$ff,$85,$22,$0a,$65,$22,$a8 230 | .byte $68,$d9,$80,$a0,$b0,$67,$20,$8d,$ad,$48,$20,$20,$ae,$68,$a4,$4b 231 | .byte $10,$17,$aa,$f0,$56,$d0,$5f,$46,$0d,$8a,$2a,$a6,$7a,$d0,$02,$c6 232 | .byte $7b,$c6,$7a,$a0,$1b,$85,$4d,$d0,$d7,$d9,$80,$a0,$b0,$48,$90,$d9 233 | .byte $b9,$82,$a0,$48,$b9,$81,$a0,$48,$20,$33,$ae,$a5,$4d,$4c,$a9,$ad 234 | .byte $4c,$08,$af,$a5,$66,$be,$80,$a0,$a8,$68,$85,$22,$e6,$22,$68,$85 235 | .byte $23,$98,$48,$20,$1b,$bc,$a5,$65,$48,$a5,$64,$48,$a5,$63,$48,$a5 236 | .byte $62,$48,$a5,$61,$48,$6c,$22,$00,$a0,$ff,$68,$f0,$23,$c9,$64,$f0 237 | .byte $03,$20,$8d,$ad,$84,$4b,$68,$4a,$85,$12,$68,$85,$69,$68,$85,$6a 238 | .byte $68,$85,$6b,$68,$85,$6c,$68,$85,$6d,$68,$85,$6e,$45,$66,$85,$6f 239 | .byte $a5,$61,$60,$6c,$0a,$03,$a9,$00,$85,$0d,$20,$73,$00,$b0,$03,$4c 240 | .byte $f3,$bc,$20,$13,$b1,$90,$03,$4c,$28,$af,$c9,$ff,$d0,$0f,$a9,$a8 241 | .byte $a0,$ae,$20,$a2,$bb,$4c,$73,$00,$82,$49,$0f,$da,$a1,$c9,$2e,$f0 242 | .byte $de,$c9,$ab,$f0,$58,$c9,$aa,$f0,$d1,$c9,$22,$d0,$0f,$a5,$7a,$a4 243 | .byte $7b,$69,$00,$90,$01,$c8,$20,$87,$b4,$4c,$e2,$b7,$c9,$a8,$d0,$13 244 | .byte $a0,$18,$d0,$3b,$20,$bf,$b1,$a5,$65,$49,$ff,$a8,$a5,$64,$49,$ff 245 | .byte $4c,$91,$b3,$c9,$a5,$d0,$03,$4c,$f4,$b3,$c9,$b4,$90,$03,$4c,$a7 246 | .byte $af,$20,$fa,$ae,$20,$9e,$ad,$a9,$29,$2c,$a9,$28,$2c,$a9,$2c,$a0 247 | .byte $00,$d1,$7a,$d0,$03,$4c,$73,$00,$a2,$0b,$4c,$37,$a4,$a0,$15,$68 248 | .byte $68,$4c,$fa,$ad,$38,$a5,$64,$e9,$00,$a5,$65,$e9,$a0,$90,$08,$a9 249 | .byte $a2,$e5,$64,$a9,$e3,$e5,$65,$60,$20,$8b,$b0,$85,$64,$84,$65,$a6 250 | .byte $45,$a4,$46,$a5,$0d,$f0,$26,$a9,$00,$85,$70,$20,$14,$af,$90,$1c 251 | .byte $e0,$54,$d0,$18,$c0,$c9,$d0,$14,$20,$84,$af,$84,$5e,$88,$84,$71 252 | .byte $a0,$06,$84,$5d,$a0,$24,$20,$68,$be,$4c,$6f,$b4,$60,$24,$0e,$10 253 | .byte $0d,$a0,$00,$b1,$64,$aa,$c8,$b1,$64,$a8,$8a,$4c,$91,$b3,$20,$14 254 | .byte $af,$90,$2d,$e0,$54,$d0,$1b,$c0,$49,$d0,$25,$20,$84,$af,$98,$a2 255 | .byte $a0,$4c,$4f,$bc,$20,$de,$ff,$86,$64,$84,$63,$85,$65,$a0,$00,$84 256 | .byte $62,$60,$e0,$53,$d0,$0a,$c0,$54,$d0,$06,$20,$b7,$ff,$4c,$3c,$bc 257 | .byte $a5,$64,$a4,$65,$4c,$a2,$bb,$0a,$48,$aa,$20,$73,$00,$e0,$8f,$90 258 | .byte $20,$20,$fa,$ae,$20,$9e,$ad,$20,$fd,$ae,$20,$8f,$ad,$68,$aa,$a5 259 | .byte $65,$48,$a5,$64,$48,$8a,$48,$20,$9e,$b7,$68,$a8,$8a,$48,$4c,$d6 260 | .byte $af,$20,$f1,$ae,$68,$a8,$b9,$ea,$9f,$85,$55,$b9,$eb,$9f,$85,$56 261 | .byte $20,$54,$00,$4c,$8d,$ad,$a0,$ff,$2c,$a0,$00,$84,$0b,$20,$bf,$b1 262 | .byte $a5,$64,$45,$0b,$85,$07,$a5,$65,$45,$0b,$85,$08,$20,$fc,$bb,$20 263 | .byte $bf,$b1,$a5,$65,$45,$0b,$25,$08,$45,$0b,$a8,$a5,$64,$45,$0b,$25 264 | .byte $07,$45,$0b,$4c,$91,$b3,$20,$90,$ad,$b0,$13,$a5,$6e,$09,$7f,$25 265 | .byte $6a,$85,$6a,$a9,$69,$a0,$00,$20,$5b,$bc,$aa,$4c,$61,$b0,$a9,$00 266 | .byte $85,$0d,$c6,$4d,$20,$a6,$b6,$85,$61,$86,$62,$84,$63,$a5,$6c,$a4 267 | .byte $6d,$20,$aa,$b6,$86,$6c,$84,$6d,$aa,$38,$e5,$61,$f0,$08,$a9,$01 268 | .byte $90,$04,$a6,$61,$a9,$ff,$85,$66,$a0,$ff,$e8,$c8,$ca,$d0,$07,$a6 269 | .byte $66,$30,$0f,$18,$90,$0c,$b1,$6c,$d1,$62,$f0,$ef,$a2,$ff,$b0,$02 270 | .byte $a2,$01,$e8,$8a,$2a,$25,$12,$f0,$02,$a9,$ff,$4c,$3c,$bc,$20,$fd 271 | .byte $ae,$aa,$20,$90,$b0,$20,$79,$00,$d0,$f4,$60,$a2,$00,$20,$79,$00 272 | .byte $86,$0c,$85,$45,$20,$79,$00,$20,$13,$b1,$b0,$03,$4c,$08,$af,$a2 273 | .byte $00,$86,$0d,$86,$0e,$20,$73,$00,$90,$05,$20,$13,$b1,$90,$0b,$aa 274 | .byte $20,$73,$00,$90,$fb,$20,$13,$b1,$b0,$f6,$c9,$24,$d0,$06,$a9,$ff 275 | .byte $85,$0d,$d0,$10,$c9,$25,$d0,$13,$a5,$10,$d0,$d0,$a9,$80,$85,$0e 276 | .byte $05,$45,$85,$45,$8a,$09,$80,$aa,$20,$73,$00,$86,$46,$38,$05,$10 277 | .byte $e9,$28,$d0,$03,$4c,$d1,$b1,$a0,$00,$84,$10,$a5,$2d,$a6,$2e,$86 278 | .byte $60,$85,$5f,$e4,$30,$d0,$04,$c5,$2f,$f0,$22,$a5,$45,$d1,$5f,$d0 279 | .byte $08,$a5,$46,$c8,$d1,$5f,$f0,$7d,$88,$18,$a5,$5f,$69,$07,$90,$e1 280 | .byte $e8,$d0,$dc,$c9,$41,$90,$05,$e9,$5b,$38,$e9,$a5,$60,$68,$48,$c9 281 | .byte $2a,$d0,$05,$a9,$13,$a0,$bf,$60,$a5,$45,$a4,$46,$c9,$54,$d0,$0b 282 | .byte $c0,$c9,$f0,$ef,$c0,$49,$d0,$03,$4c,$08,$af,$c9,$53,$d0,$04,$c0 283 | .byte $54,$f0,$f5,$a5,$2f,$a4,$30,$85,$5f,$84,$60,$a5,$31,$a4,$32,$85 284 | .byte $5a,$84,$5b,$18,$69,$07,$90,$01,$c8,$85,$58,$84,$59,$20,$b8,$a3 285 | .byte $a5,$58,$a4,$59,$c8,$85,$2f,$84,$30,$a0,$00,$a5,$45,$91,$5f,$c8 286 | .byte $a5,$46,$91,$5f,$a9,$00,$c8,$91,$5f,$c8,$91,$5f,$c8,$91,$5f,$c8 287 | .byte $91,$5f,$c8,$91,$5f,$a5,$5f,$18,$69,$02,$a4,$60,$90,$01,$c8,$85 288 | .byte $47,$84,$48,$60,$a5,$0b,$0a,$69,$05,$65,$5f,$a4,$60,$90,$01,$c8 289 | .byte $85,$58,$84,$59,$60,$90,$80,$00,$00,$00,$20,$bf,$b1,$a5,$64,$a4 290 | .byte $65,$60,$20,$73,$00,$20,$9e,$ad,$20,$8d,$ad,$a5,$66,$30,$0d,$a5 291 | .byte $61,$c9,$90,$90,$09,$a9,$a5,$a0,$b1,$20,$5b,$bc,$d0,$7a,$4c,$9b 292 | .byte $bc,$a5,$0c,$05,$0e,$48,$a5,$0d,$48,$a0,$00,$98,$48,$a5,$46,$48 293 | .byte $a5,$45,$48,$20,$b2,$b1,$68,$85,$45,$68,$85,$46,$68,$a8,$ba,$bd 294 | .byte $02,$01,$48,$bd,$01,$01,$48,$a5,$64,$9d,$02,$01,$a5,$65,$9d,$01 295 | .byte $01,$c8,$20,$79,$00,$c9,$2c,$f0,$d2,$84,$0b,$20,$f7,$ae,$68,$85 296 | .byte $0d,$68,$85,$0e,$29,$7f,$85,$0c,$a6,$2f,$a5,$30,$86,$5f,$85,$60 297 | .byte $c5,$32,$d0,$04,$e4,$31,$f0,$39,$a0,$00,$b1,$5f,$c8,$c5,$45,$d0 298 | .byte $06,$a5,$46,$d1,$5f,$f0,$16,$c8,$b1,$5f,$18,$65,$5f,$aa,$c8,$b1 299 | .byte $5f,$65,$60,$90,$d7,$a2,$12,$2c,$a2,$0e,$4c,$37,$a4,$a2,$13,$a5 300 | .byte $0c,$d0,$f7,$20,$94,$b1,$a5,$0b,$a0,$04,$d1,$5f,$d0,$e7,$4c,$ea 301 | .byte $b2,$20,$94,$b1,$20,$08,$a4,$a0,$00,$84,$72,$a2,$05,$a5,$45,$91 302 | .byte $5f,$10,$01,$ca,$c8,$a5,$46,$91,$5f,$10,$02,$ca,$ca,$86,$71,$a5 303 | .byte $0b,$c8,$c8,$c8,$91,$5f,$a2,$0b,$a9,$00,$24,$0c,$50,$08,$68,$18 304 | .byte $69,$01,$aa,$68,$69,$00,$c8,$91,$5f,$c8,$8a,$91,$5f,$20,$4c,$b3 305 | .byte $86,$71,$85,$72,$a4,$22,$c6,$0b,$d0,$dc,$65,$59,$b0,$5d,$85,$59 306 | .byte $a8,$8a,$65,$58,$90,$03,$c8,$f0,$52,$20,$08,$a4,$85,$31,$84,$32 307 | .byte $a9,$00,$e6,$72,$a4,$71,$f0,$05,$88,$91,$58,$d0,$fb,$c6,$59,$c6 308 | .byte $72,$d0,$f5,$e6,$59,$38,$a5,$31,$e5,$5f,$a0,$02,$91,$5f,$a5,$32 309 | .byte $c8,$e5,$60,$91,$5f,$a5,$0c,$d0,$62,$c8,$b1,$5f,$85,$0b,$a9,$00 310 | .byte $85,$71,$85,$72,$c8,$68,$aa,$85,$64,$68,$85,$65,$d1,$5f,$90,$0e 311 | .byte $d0,$06,$c8,$8a,$d1,$5f,$90,$07,$4c,$45,$b2,$4c,$35,$a4,$c8,$a5 312 | .byte $72,$05,$71,$18,$f0,$0a,$20,$4c,$b3,$8a,$65,$64,$aa,$98,$a4,$22 313 | .byte $65,$65,$86,$71,$c6,$0b,$d0,$ca,$85,$72,$a2,$05,$a5,$45,$10,$01 314 | .byte $ca,$a5,$46,$10,$02,$ca,$ca,$86,$28,$a9,$00,$20,$55,$b3,$8a,$65 315 | .byte $58,$85,$47,$98,$65,$59,$85,$48,$a8,$a5,$47,$60,$84,$22,$b1,$5f 316 | .byte $85,$28,$88,$b1,$5f,$85,$29,$a9,$10,$85,$5d,$a2,$00,$a0,$00,$8a 317 | .byte $0a,$aa,$98,$2a,$a8,$b0,$a4,$06,$71,$26,$72,$90,$0b,$18,$8a,$65 318 | .byte $28,$aa,$98,$65,$29,$a8,$b0,$93,$c6,$5d,$d0,$e3,$60,$a5,$0d,$f0 319 | .byte $03,$20,$a6,$b6,$20,$26,$b5,$38,$a5,$33,$e5,$31,$a8,$a5,$34,$e5 320 | .byte $32,$a2,$00,$86,$0d,$85,$62,$84,$63,$a2,$90,$4c,$44,$bc,$38,$20 321 | .byte $f0,$ff,$a9,$00,$f0,$eb,$a6,$3a,$e8,$d0,$a0,$a2,$15,$2c,$a2,$1b 322 | .byte $4c,$37,$a4,$20,$e1,$b3,$20,$a6,$b3,$20,$fa,$ae,$a9,$80,$85,$10 323 | .byte $20,$8b,$b0,$20,$8d,$ad,$20,$f7,$ae,$a9,$b2,$20,$ff,$ae,$48,$a5 324 | .byte $48,$48,$a5,$47,$48,$a5,$7b,$48,$a5,$7a,$48,$20,$f8,$a8,$4c,$4f 325 | .byte $b4,$a9,$a5,$20,$ff,$ae,$09,$80,$85,$10,$20,$92,$b0,$85,$4e,$84 326 | .byte $4f,$4c,$8d,$ad,$20,$e1,$b3,$a5,$4f,$48,$a5,$4e,$48,$20,$f1,$ae 327 | .byte $20,$8d,$ad,$68,$85,$4e,$68,$85,$4f,$a0,$02,$b1,$4e,$85,$47,$aa 328 | .byte $c8,$b1,$4e,$f0,$99,$85,$48,$c8,$b1,$47,$48,$88,$10,$fa,$a4,$48 329 | .byte $20,$d4,$bb,$a5,$7b,$48,$a5,$7a,$48,$b1,$4e,$85,$7a,$c8,$b1,$4e 330 | .byte $85,$7b,$a5,$48,$48,$a5,$47,$48,$20,$8a,$ad,$68,$85,$4e,$68,$85 331 | .byte $4f,$20,$79,$00,$f0,$03,$4c,$08,$af,$68,$85,$7a,$68,$85,$7b,$a0 332 | .byte $00,$68,$91,$4e,$68,$c8,$91,$4e,$68,$c8,$91,$4e,$68,$c8,$91,$4e 333 | .byte $68,$c8,$91,$4e,$60,$20,$8d,$ad,$a0,$00,$20,$df,$bd,$68,$68,$a9 334 | .byte $ff,$a0,$00,$f0,$12,$a6,$64,$a4,$65,$86,$50,$84,$51,$20,$f4,$b4 335 | .byte $86,$62,$84,$63,$85,$61,$60,$a2,$22,$86,$07,$86,$08,$85,$6f,$84 336 | .byte $70,$85,$62,$84,$63,$a0,$ff,$c8,$b1,$6f,$f0,$0c,$c5,$07,$f0,$04 337 | .byte $c5,$08,$d0,$f3,$c9,$22,$f0,$01,$18,$84,$61,$98,$65,$6f,$85,$71 338 | .byte $a6,$70,$90,$01,$e8,$86,$72,$a5,$70,$f0,$04,$c9,$02,$d0,$0b,$98 339 | .byte $20,$75,$b4,$a6,$6f,$a4,$70,$20,$88,$b6,$a6,$16,$e0,$22,$d0,$05 340 | .byte $a2,$19,$4c,$37,$a4,$a5,$61,$95,$00,$a5,$62,$95,$01,$a5,$63,$95 341 | .byte $02,$a0,$00,$86,$64,$84,$65,$84,$70,$88,$84,$0d,$86,$17,$e8,$e8 342 | .byte $e8,$86,$16,$60,$46,$0f,$48,$49,$ff,$38,$65,$33,$a4,$34,$b0,$01 343 | .byte $88,$c4,$32,$90,$11,$d0,$04,$c5,$31,$90,$0b,$85,$33,$84,$34,$85 344 | .byte $35,$84,$36,$aa,$68,$60,$a2,$10,$a5,$0f,$30,$b6,$20,$26,$b5,$a9 345 | .byte $80,$85,$0f,$68,$d0,$d0,$a6,$37,$a5,$38,$86,$33,$85,$34,$a0,$00 346 | .byte $84,$4f,$84,$4e,$a5,$31,$a6,$32,$85,$5f,$86,$60,$a9,$19,$a2,$00 347 | .byte $85,$22,$86,$23,$c5,$16,$f0,$05,$20,$c7,$b5,$f0,$f7,$a9,$07,$85 348 | .byte $53,$a5,$2d,$a6,$2e,$85,$22,$86,$23,$e4,$30,$d0,$04,$c5,$2f,$f0 349 | .byte $05,$20,$bd,$b5,$f0,$f3,$85,$58,$86,$59,$a9,$03,$85,$53,$a5,$58 350 | .byte $a6,$59,$e4,$32,$d0,$07,$c5,$31,$d0,$03,$4c,$06,$b6,$85,$22,$86 351 | .byte $23,$a0,$00,$b1,$22,$aa,$c8,$b1,$22,$08,$c8,$b1,$22,$65,$58,$85 352 | .byte $58,$c8,$b1,$22,$65,$59,$85,$59,$28,$10,$d3,$8a,$30,$d0,$c8,$b1 353 | .byte $22,$a0,$00,$0a,$69,$05,$65,$22,$85,$22,$90,$02,$e6,$23,$a6,$23 354 | .byte $e4,$59,$d0,$04,$c5,$58,$f0,$ba,$20,$c7,$b5,$f0,$f3,$b1,$22,$30 355 | .byte $35,$c8,$b1,$22,$10,$30,$c8,$b1,$22,$f0,$2b,$c8,$b1,$22,$aa,$c8 356 | .byte $b1,$22,$c5,$34,$90,$06,$d0,$1e,$e4,$33,$b0,$1a,$c5,$60,$90,$16 357 | .byte $d0,$04,$e4,$5f,$90,$10,$86,$5f,$85,$60,$a5,$22,$a6,$23,$85,$4e 358 | .byte $86,$4f,$a5,$53,$85,$55,$a5,$53,$18,$65,$22,$85,$22,$90,$02,$e6 359 | .byte $23,$a6,$23,$a0,$00,$60,$a5,$4f,$05,$4e,$f0,$f5,$a5,$55,$29,$04 360 | .byte $4a,$a8,$85,$55,$b1,$4e,$65,$5f,$85,$5a,$a5,$60,$69,$00,$85,$5b 361 | .byte $a5,$33,$a6,$34,$85,$58,$86,$59,$20,$bf,$a3,$a4,$55,$c8,$a5,$58 362 | .byte $91,$4e,$aa,$e6,$59,$a5,$59,$c8,$91,$4e,$4c,$2a,$b5,$a5,$65,$48 363 | .byte $a5,$64,$48,$20,$83,$ae,$20,$8f,$ad,$68,$85,$6f,$68,$85,$70,$a0 364 | .byte $00,$b1,$6f,$18,$71,$64,$90,$05,$a2,$17,$4c,$37,$a4,$20,$75,$b4 365 | .byte $20,$7a,$b6,$a5,$50,$a4,$51,$20,$aa,$b6,$20,$8c,$b6,$a5,$6f,$a4 366 | .byte $70,$20,$aa,$b6,$20,$ca,$b4,$4c,$b8,$ad,$a0,$00,$b1,$6f,$48,$c8 367 | .byte $b1,$6f,$aa,$c8,$b1,$6f,$a8,$68,$86,$22,$84,$23,$a8,$f0,$0a,$48 368 | .byte $88,$b1,$22,$91,$35,$98,$d0,$f8,$68,$18,$65,$35,$85,$35,$90,$02 369 | .byte $e6,$36,$60,$20,$8f,$ad,$a5,$64,$a4,$65,$85,$22,$84,$23,$20,$db 370 | .byte $b6,$08,$a0,$00,$b1,$22,$48,$c8,$b1,$22,$aa,$c8,$b1,$22,$a8,$68 371 | .byte $28,$d0,$13,$c4,$34,$d0,$0f,$e4,$33,$d0,$0b,$48,$18,$65,$33,$85 372 | .byte $33,$90,$02,$e6,$34,$68,$86,$22,$84,$23,$60,$c4,$18,$d0,$0c,$c5 373 | .byte $17,$d0,$08,$85,$16,$e9,$03,$85,$17,$a0,$00,$60,$20,$a1,$b7,$8a 374 | .byte $48,$a9,$01,$20,$7d,$b4,$68,$a0,$00,$91,$62,$68,$68,$4c,$ca,$b4 375 | .byte $20,$61,$b7,$d1,$50,$98,$90,$04,$b1,$50,$aa,$98,$48,$8a,$48,$20 376 | .byte $7d,$b4,$a5,$50,$a4,$51,$20,$aa,$b6,$68,$a8,$68,$18,$65,$22,$85 377 | .byte $22,$90,$02,$e6,$23,$98,$20,$8c,$b6,$4c,$ca,$b4,$20,$61,$b7,$18 378 | .byte $f1,$50,$49,$ff,$4c,$06,$b7,$a9,$ff,$85,$65,$20,$79,$00,$c9,$29 379 | .byte $f0,$06,$20,$fd,$ae,$20,$9e,$b7,$20,$61,$b7,$f0,$4b,$ca,$8a,$48 380 | .byte $18,$a2,$00,$f1,$50,$b0,$b6,$49,$ff,$c5,$65,$90,$b1,$a5,$65,$b0 381 | .byte $ad,$20,$f7,$ae,$68,$a8,$68,$85,$55,$68,$68,$68,$aa,$68,$85,$50 382 | .byte $68,$85,$51,$a5,$55,$48,$98,$48,$a0,$00,$8a,$60,$20,$82,$b7,$4c 383 | .byte $a2,$b3,$20,$a3,$b6,$a2,$00,$86,$0d,$a8,$60,$20,$82,$b7,$f0,$08 384 | .byte $a0,$00,$b1,$22,$a8,$4c,$a2,$b3,$4c,$48,$b2,$20,$73,$00,$20,$8a 385 | .byte $ad,$20,$b8,$b1,$a6,$64,$d0,$f0,$a6,$65,$4c,$79,$00,$20,$82,$b7 386 | .byte $d0,$03,$4c,$f7,$b8,$a6,$7a,$a4,$7b,$86,$71,$84,$72,$a6,$22,$86 387 | .byte $7a,$18,$65,$22,$85,$24,$a6,$23,$86,$7b,$90,$01,$e8,$86,$25,$a0 388 | .byte $00,$b1,$24,$48,$98,$91,$24,$20,$79,$00,$20,$f3,$bc,$68,$a0,$00 389 | .byte $91,$24,$a6,$71,$a4,$72,$86,$7a,$84,$7b,$60,$20,$8a,$ad,$20,$f7 390 | .byte $b7,$20,$fd,$ae,$4c,$9e,$b7,$a5,$66,$30,$9d,$a5,$61,$c9,$91,$b0 391 | .byte $97,$20,$9b,$bc,$a5,$64,$a4,$65,$84,$14,$85,$15,$60,$a5,$15,$48 392 | .byte $a5,$14,$48,$20,$f7,$b7,$a0,$00,$b1,$14,$a8,$68,$85,$14,$68,$85 393 | .byte $15,$4c,$a2,$b3,$20,$eb,$b7,$8a,$a0,$00,$91,$14,$60,$20,$eb,$b7 394 | .byte $86,$49,$a2,$00,$20,$79,$00,$f0,$03,$20,$f1,$b7,$86,$4a,$a0,$00 395 | .byte $b1,$14,$45,$4a,$25,$49,$f0,$f8,$60,$a9,$11,$a0,$bf,$4c,$67,$b8 396 | .byte $20,$8c,$ba,$a5,$66,$49,$ff,$85,$66,$45,$6e,$85,$6f,$a5,$61,$4c 397 | .byte $6a,$b8,$20,$99,$b9,$90,$3c,$20,$8c,$ba,$d0,$03,$4c,$fc,$bb,$a6 398 | .byte $70,$86,$56,$a2,$69,$a5,$69,$a8,$f0,$ce,$38,$e5,$61,$f0,$24,$90 399 | .byte $12,$84,$61,$a4,$6e,$84,$66,$49,$ff,$69,$00,$a0,$00,$84,$56,$a2 400 | .byte $61,$d0,$04,$a0,$00,$84,$70,$c9,$f9,$30,$c7,$a8,$a5,$70,$56,$01 401 | .byte $20,$b0,$b9,$24,$6f,$10,$57,$a0,$61,$e0,$69,$f0,$02,$a0,$69,$38 402 | .byte $49,$ff,$65,$56,$85,$70,$b9,$04,$00,$f5,$04,$85,$65,$b9,$03,$00 403 | .byte $f5,$03,$85,$64,$b9,$02,$00,$f5,$02,$85,$63,$b9,$01,$00,$f5,$01 404 | .byte $85,$62,$b0,$03,$20,$47,$b9,$a0,$00,$98,$18,$a6,$62,$d0,$4a,$a6 405 | .byte $63,$86,$62,$a6,$64,$86,$63,$a6,$65,$86,$64,$a6,$70,$86,$65,$84 406 | .byte $70,$69,$08,$c9,$20,$d0,$e4,$a9,$00,$85,$61,$85,$66,$60,$65,$56 407 | .byte $85,$70,$a5,$65,$65,$6d,$85,$65,$a5,$64,$65,$6c,$85,$64,$a5,$63 408 | .byte $65,$6b,$85,$63,$a5,$62,$65,$6a,$85,$62,$4c,$36,$b9,$69,$01,$06 409 | .byte $70,$26,$65,$26,$64,$26,$63,$26,$62,$10,$f2,$38,$e5,$61,$b0,$c7 410 | .byte $49,$ff,$69,$01,$85,$61,$90,$0e,$e6,$61,$f0,$42,$66,$62,$66,$63 411 | .byte $66,$64,$66,$65,$66,$70,$60,$a5,$66,$49,$ff,$85,$66,$a5,$62,$49 412 | .byte $ff,$85,$62,$a5,$63,$49,$ff,$85,$63,$a5,$64,$49,$ff,$85,$64,$a5 413 | .byte $65,$49,$ff,$85,$65,$a5,$70,$49,$ff,$85,$70,$e6,$70,$d0,$0e,$e6 414 | .byte $65,$d0,$0a,$e6,$64,$d0,$06,$e6,$63,$d0,$02,$e6,$62,$60,$a2,$0f 415 | .byte $4c,$37,$a4,$a2,$25,$b4,$04,$84,$70,$b4,$03,$94,$04,$b4,$02,$94 416 | .byte $03,$b4,$01,$94,$02,$a4,$68,$94,$01,$69,$08,$30,$e8,$f0,$e6,$e9 417 | .byte $08,$a8,$a5,$70,$b0,$14,$16,$01,$90,$02,$f6,$01,$76,$01,$76,$01 418 | .byte $76,$02,$76,$03,$76,$04,$6a,$c8,$d0,$ec,$18,$60,$81,$00,$00,$00 419 | .byte $00,$03,$7f,$5e,$56,$cb,$79,$80,$13,$9b,$0b,$64,$80,$76,$38,$93 420 | .byte $16,$82,$38,$aa,$3b,$20,$80,$35,$04,$f3,$34,$81,$35,$04,$f3,$34 421 | .byte $80,$80,$00,$00,$00,$80,$31,$72,$17,$f8,$20,$2b,$bc,$f0,$02,$10 422 | .byte $03,$4c,$48,$b2,$a5,$61,$e9,$7f,$48,$a9,$80,$85,$61,$a9,$d6,$a0 423 | .byte $b9,$20,$67,$b8,$a9,$db,$a0,$b9,$20,$0f,$bb,$a9,$bc,$a0,$b9,$20 424 | .byte $50,$b8,$a9,$c1,$a0,$b9,$20,$43,$e0,$a9,$e0,$a0,$b9,$20,$67,$b8 425 | .byte $68,$20,$7e,$bd,$a9,$e5,$a0,$b9,$20,$8c,$ba,$d0,$03,$4c,$8b,$ba 426 | .byte $20,$b7,$ba,$a9,$00,$85,$26,$85,$27,$85,$28,$85,$29,$a5,$70,$20 427 | .byte $59,$ba,$a5,$65,$20,$59,$ba,$a5,$64,$20,$59,$ba,$a5,$63,$20,$59 428 | .byte $ba,$a5,$62,$20,$5e,$ba,$4c,$8f,$bb,$d0,$03,$4c,$83,$b9,$4a,$09 429 | .byte $80,$a8,$90,$19,$18,$a5,$29,$65,$6d,$85,$29,$a5,$28,$65,$6c,$85 430 | .byte $28,$a5,$27,$65,$6b,$85,$27,$a5,$26,$65,$6a,$85,$26,$66,$26,$66 431 | .byte $27,$66,$28,$66,$29,$66,$70,$98,$4a,$d0,$d6,$60,$85,$22,$84,$23 432 | .byte $a0,$04,$b1,$22,$85,$6d,$88,$b1,$22,$85,$6c,$88,$b1,$22,$85,$6b 433 | .byte $88,$b1,$22,$85,$6e,$45,$66,$85,$6f,$a5,$6e,$09,$80,$85,$6a,$88 434 | .byte $b1,$22,$85,$69,$a5,$61,$60,$a5,$69,$f0,$1f,$18,$65,$61,$90,$04 435 | .byte $30,$1d,$18,$2c,$10,$14,$69,$80,$85,$61,$d0,$03,$4c,$fb,$b8,$a5 436 | .byte $6f,$85,$66,$60,$a5,$66,$49,$ff,$30,$05,$68,$68,$4c,$f7,$b8,$4c 437 | .byte $7e,$b9,$20,$0c,$bc,$aa,$f0,$10,$18,$69,$02,$b0,$f2,$a2,$00,$86 438 | .byte $6f,$20,$77,$b8,$e6,$61,$f0,$e7,$60,$84,$20,$00,$00,$00,$20,$0c 439 | .byte $bc,$a9,$f9,$a0,$ba,$a2,$00,$86,$6f,$20,$a2,$bb,$4c,$12,$bb,$20 440 | .byte $8c,$ba,$f0,$76,$20,$1b,$bc,$a9,$00,$38,$e5,$61,$85,$61,$20,$b7 441 | .byte $ba,$e6,$61,$f0,$ba,$a2,$fc,$a9,$01,$a4,$6a,$c4,$62,$d0,$10,$a4 442 | .byte $6b,$c4,$63,$d0,$0a,$a4,$6c,$c4,$64,$d0,$04,$a4,$6d,$c4,$65,$08 443 | .byte $2a,$90,$09,$e8,$95,$29,$f0,$32,$10,$34,$a9,$01,$28,$b0,$0e,$06 444 | .byte $6d,$26,$6c,$26,$6b,$26,$6a,$b0,$e6,$30,$ce,$10,$e2,$a8,$a5,$6d 445 | .byte $e5,$65,$85,$6d,$a5,$6c,$e5,$64,$85,$6c,$a5,$6b,$e5,$63,$85,$6b 446 | .byte $a5,$6a,$e5,$62,$85,$6a,$98,$4c,$4f,$bb,$a9,$40,$d0,$ce,$0a,$0a 447 | .byte $0a,$0a,$0a,$0a,$85,$70,$28,$4c,$8f,$bb,$a2,$14,$4c,$37,$a4,$a5 448 | .byte $26,$85,$62,$a5,$27,$85,$63,$a5,$28,$85,$64,$a5,$29,$85,$65,$4c 449 | .byte $d7,$b8,$85,$22,$84,$23,$a0,$04,$b1,$22,$85,$65,$88,$b1,$22,$85 450 | .byte $64,$88,$b1,$22,$85,$63,$88,$b1,$22,$85,$66,$09,$80,$85,$62,$88 451 | .byte $b1,$22,$85,$61,$84,$70,$60,$a2,$5c,$2c,$a2,$57,$a0,$00,$f0,$04 452 | .byte $a6,$49,$a4,$4a,$20,$1b,$bc,$86,$22,$84,$23,$a0,$04,$a5,$65,$91 453 | .byte $22,$88,$a5,$64,$91,$22,$88,$a5,$63,$91,$22,$88,$a5,$66,$09,$7f 454 | .byte $25,$62,$91,$22,$88,$a5,$61,$91,$22,$84,$70,$60,$a5,$6e,$85,$66 455 | .byte $a2,$05,$b5,$68,$95,$60,$ca,$d0,$f9,$86,$70,$60,$20,$1b,$bc,$a2 456 | .byte $06,$b5,$60,$95,$68,$ca,$d0,$f9,$86,$70,$60,$a5,$61,$f0,$fb,$06 457 | .byte $70,$90,$f7,$20,$6f,$b9,$d0,$f2,$4c,$38,$b9,$a5,$61,$f0,$09,$a5 458 | .byte $66,$2a,$a9,$ff,$b0,$02,$a9,$01,$60,$20,$2b,$bc,$85,$62,$a9,$00 459 | .byte $85,$63,$a2,$88,$a5,$62,$49,$ff,$2a,$a9,$00,$85,$65,$85,$64,$86 460 | .byte $61,$85,$70,$85,$66,$4c,$d2,$b8,$46,$66,$60,$85,$24,$84,$25,$a0 461 | .byte $00,$b1,$24,$c8,$aa,$f0,$c4,$b1,$24,$45,$66,$30,$c2,$e4,$61,$d0 462 | .byte $21,$b1,$24,$09,$80,$c5,$62,$d0,$19,$c8,$b1,$24,$c5,$63,$d0,$12 463 | .byte $c8,$b1,$24,$c5,$64,$d0,$0b,$c8,$a9,$7f,$c5,$70,$b1,$24,$e5,$65 464 | .byte $f0,$28,$a5,$66,$90,$02,$49,$ff,$4c,$31,$bc,$a5,$61,$f0,$4a,$38 465 | .byte $e9,$a0,$24,$66,$10,$09,$aa,$a9,$ff,$85,$68,$20,$4d,$b9,$8a,$a2 466 | .byte $61,$c9,$f9,$10,$06,$20,$99,$b9,$84,$68,$60,$a8,$a5,$66,$29,$80 467 | .byte $46,$62,$05,$62,$85,$62,$20,$b0,$b9,$84,$68,$60,$a5,$61,$c9,$a0 468 | .byte $b0,$20,$20,$9b,$bc,$84,$70,$a5,$66,$84,$66,$49,$80,$2a,$a9,$a0 469 | .byte $85,$61,$a5,$65,$85,$07,$4c,$d2,$b8,$85,$62,$85,$63,$85,$64,$85 470 | .byte $65,$a8,$60,$a0,$00,$a2,$0a,$94,$5d,$ca,$10,$fb,$90,$0f,$c9,$2d 471 | .byte $d0,$04,$86,$67,$f0,$04,$c9,$2b,$d0,$05,$20,$73,$00,$90,$5b,$c9 472 | .byte $2e,$f0,$2e,$c9,$45,$d0,$30,$20,$73,$00,$90,$17,$c9,$ab,$f0,$0e 473 | .byte $c9,$2d,$f0,$0a,$c9,$aa,$f0,$08,$c9,$2b,$f0,$04,$d0,$07,$66,$60 474 | .byte $20,$73,$00,$90,$5c,$24,$60,$10,$0e,$a9,$00,$38,$e5,$5e,$4c,$49 475 | .byte $bd,$66,$5f,$24,$5f,$50,$c3,$a5,$5e,$38,$e5,$5d,$85,$5e,$f0,$12 476 | .byte $10,$09,$20,$fe,$ba,$e6,$5e,$d0,$f9,$f0,$07,$20,$e2,$ba,$c6,$5e 477 | .byte $d0,$f9,$a5,$67,$30,$01,$60,$4c,$b4,$bf,$48,$24,$5f,$10,$02,$e6 478 | .byte $5d,$20,$e2,$ba,$68,$38,$e9,$30,$20,$7e,$bd,$4c,$0a,$bd,$48,$20 479 | .byte $0c,$bc,$68,$20,$3c,$bc,$a5,$6e,$45,$66,$85,$6f,$a6,$61,$4c,$6a 480 | .byte $b8,$a5,$5e,$c9,$0a,$90,$09,$a9,$64,$24,$60,$30,$11,$4c,$7e,$b9 481 | .byte $0a,$0a,$18,$65,$5e,$0a,$18,$a0,$00,$71,$7a,$38,$e9,$30,$85,$5e 482 | .byte $4c,$30,$bd,$9b,$3e,$bc,$1f,$fd,$9e,$6e,$6b,$27,$fd,$9e,$6e,$6b 483 | .byte $28,$00,$a9,$71,$a0,$a3,$20,$da,$bd,$a5,$3a,$a6,$39,$85,$62,$86 484 | .byte $63,$a2,$90,$38,$20,$49,$bc,$20,$df,$bd,$4c,$1e,$ab,$a0,$01,$a9 485 | .byte $20,$24,$66,$10,$02,$a9,$2d,$99,$ff,$00,$85,$66,$84,$71,$c8,$a9 486 | .byte $30,$a6,$61,$d0,$03,$4c,$04,$bf,$a9,$00,$e0,$80,$f0,$02,$b0,$09 487 | .byte $a9,$bd,$a0,$bd,$20,$28,$ba,$a9,$f7,$85,$5d,$a9,$b8,$a0,$bd,$20 488 | .byte $5b,$bc,$f0,$1e,$10,$12,$a9,$b3,$a0,$bd,$20,$5b,$bc,$f0,$02,$10 489 | .byte $0e,$20,$e2,$ba,$c6,$5d,$d0,$ee,$20,$fe,$ba,$e6,$5d,$d0,$dc,$20 490 | .byte $49,$b8,$20,$9b,$bc,$a2,$01,$a5,$5d,$18,$69,$0a,$30,$09,$c9,$0b 491 | .byte $b0,$06,$69,$ff,$aa,$a9,$02,$38,$e9,$02,$85,$5e,$86,$5d,$8a,$f0 492 | .byte $02,$10,$13,$a4,$71,$a9,$2e,$c8,$99,$ff,$00,$8a,$f0,$06,$a9,$30 493 | .byte $c8,$99,$ff,$00,$84,$71,$a0,$00,$a2,$80,$a5,$65,$18,$79,$19,$bf 494 | .byte $85,$65,$a5,$64,$79,$18,$bf,$85,$64,$a5,$63,$79,$17,$bf,$85,$63 495 | .byte $a5,$62,$79,$16,$bf,$85,$62,$e8,$b0,$04,$10,$de,$30,$02,$30,$da 496 | .byte $8a,$90,$04,$49,$ff,$69,$0a,$69,$2f,$c8,$c8,$c8,$c8,$84,$47,$a4 497 | .byte $71,$c8,$aa,$29,$7f,$99,$ff,$00,$c6,$5d,$d0,$06,$a9,$2e,$c8,$99 498 | .byte $ff,$00,$84,$71,$a4,$47,$8a,$49,$ff,$29,$80,$aa,$c0,$24,$f0,$04 499 | .byte $c0,$3c,$d0,$a6,$a4,$71,$b9,$ff,$00,$88,$c9,$30,$f0,$f8,$c9,$2e 500 | .byte $f0,$01,$c8,$a9,$2b,$a6,$5e,$f0,$2e,$10,$08,$a9,$00,$38,$e5,$5e 501 | .byte $aa,$a9,$2d,$99,$01,$01,$a9,$45,$99,$00,$01,$8a,$a2,$2f,$38,$e8 502 | .byte $e9,$0a,$b0,$fb,$69,$3a,$99,$03,$01,$8a,$99,$02,$01,$a9,$00,$99 503 | .byte $04,$01,$f0,$08,$99,$ff,$00,$a9,$00,$99,$00,$01,$a9,$00,$a0,$01 504 | .byte $60,$80,$00,$00,$00,$00,$fa,$0a,$1f,$00,$00,$98,$96,$80,$ff,$f0 505 | .byte $bd,$c0,$00,$01,$86,$a0,$ff,$ff,$d8,$f0,$00,$00,$03,$e8,$ff,$ff 506 | .byte $ff,$9c,$00,$00,$00,$0a,$ff,$ff,$ff,$ff,$ff,$df,$0a,$80,$00,$03 507 | .byte $4b,$c0,$ff,$ff,$73,$60,$00,$00,$0e,$10,$ff,$ff,$fd,$a8,$00,$00 508 | .byte $00,$3c,$ec,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa 509 | .byte $aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa 510 | .byte $aa,$20,$0c,$bc,$a9,$11,$a0,$bf,$20,$a2,$bb,$f0,$70,$a5,$69,$d0 511 | .byte $03,$4c,$f9,$b8,$a2,$4e,$a0,$00,$20,$d4,$bb,$a5,$6e,$10,$0f,$20 512 | .byte $cc,$bc,$a9,$4e,$a0,$00,$20,$5b,$bc,$d0,$03,$98,$a4,$07,$20,$fe 513 | .byte $bb,$98,$48,$20,$ea,$b9,$a9,$4e,$a0,$00,$20,$28,$ba,$20,$ed,$bf 514 | .byte $68,$4a,$90,$0a,$a5,$61,$f0,$06,$a5,$66,$49,$ff,$85,$66,$60,$81 515 | .byte $38,$aa,$3b,$29,$07,$71,$34,$58,$3e,$56,$74,$16,$7e,$b3,$1b,$77 516 | .byte $2f,$ee,$e3,$85,$7a,$1d,$84,$1c,$2a,$7c,$63,$59,$58,$0a,$7e,$75 517 | .byte $fd,$e7,$c6,$80,$31,$72,$18,$10,$81,$00,$00,$00,$00,$a9,$bf,$a0 518 | .byte $bf,$20,$28,$ba,$a5,$70,$69,$50,$90,$03,$20,$23,$bc,$4c,$00,$e0 519 | 520 | ;; SMON 521 | .org $C000 522 | .byte $a9,$14,$8d,$16,$03,$a9,$c2,$8d,$17,$03,$00,$27,$23,$24,$25,$2c 523 | .byte $3a,$3b,$3d,$3f,$41,$42,$43,$44,$46,$47,$49,$4b,$4c,$4d,$4f,$50 524 | .byte $52,$53,$54,$56,$57,$58,$5a,$00,$00,$00,$00,$da,$ca,$2d,$c9,$07 525 | .byte $c9,$1b,$c9,$fb,$c6,$1c,$c4,$b5,$c3,$f4,$ca,$99,$c8,$d0,$c6,$6b 526 | .byte $c9,$3c,$ca,$5c,$c5,$10,$cb,$e2,$c3,$43,$c8,$b6,$ca,$4d,$c8,$f8 527 | .byte $c3,$c0,$c9,$3c,$c8,$85,$c3,$4d,$c8,$f0,$cb,$42,$ca,$d2,$c9,$6d 528 | .byte $c3,$08,$ce,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$ff,$01,$00,$41 529 | .byte $5a,$49,$52,$54,$80,$20,$40,$10,$00,$02,$01,$01,$02,$00,$91,$91 530 | .byte $0d,$53,$d9,$31,$37,$32,$0d,$00,$7d,$4c,$7d,$c9,$0d,$0d,$20,$20 531 | .byte $50,$43,$20,$20,$53,$52,$20,$41,$43,$20,$58,$52,$20,$59,$52,$20 532 | .byte $53,$50,$20,$20,$4e,$56,$2d,$42,$44,$49,$5a,$43,$00,$02,$04,$01 533 | .byte $2c,$00,$2c,$59,$29,$58,$9d,$1f,$ff,$1c,$1c,$1f,$1f,$1f,$1c,$df 534 | .byte $1c,$1f,$df,$ff,$ff,$03,$1f,$80,$09,$20,$0c,$04,$10,$01,$11,$14 535 | .byte $96,$1c,$19,$94,$be,$6c,$03,$13,$01,$02,$02,$03,$03,$02,$02,$02 536 | .byte $02,$02,$02,$03,$03,$02,$03,$03,$03,$02,$00,$40,$40,$80,$80,$20 537 | .byte $10,$25,$26,$21,$22,$81,$82,$21,$82,$84,$08,$08,$e7,$e7,$e7,$e7 538 | .byte $e3,$e3,$e3,$e3,$e3,$e3,$e3,$e3,$e3,$e3,$e7,$a7,$e7,$e7,$f3,$f3 539 | .byte $f7,$df,$26,$46,$06,$66,$41,$81,$e1,$01,$a0,$a2,$a1,$c1,$21,$61 540 | .byte $84,$86,$e6,$c6,$e0,$c0,$24,$4c,$20,$90,$b0,$f0,$30,$d0,$10,$50 541 | .byte $70,$78,$00,$18,$d8,$58,$b8,$ca,$88,$e8,$c8,$ea,$48,$08,$68,$28 542 | .byte $40,$60,$aa,$a8,$ba,$8a,$9a,$98,$38,$f8,$89,$9c,$9e,$b2,$2a,$4a 543 | .byte $0a,$6a,$4f,$23,$93,$b3,$f3,$33,$d3,$13,$53,$73,$52,$4c,$41,$52 544 | .byte $45,$53,$53,$4f,$4c,$4c,$4c,$43,$41,$41,$53,$53,$49,$44,$43,$43 545 | .byte $42,$4a,$4a,$42,$42,$42,$42,$42,$42,$42,$42,$53,$42,$43,$43,$43 546 | .byte $43,$44,$44,$49,$49,$4e,$50,$50,$50,$50,$52,$52,$54,$54,$54,$54 547 | .byte $54,$54,$53,$53,$4f,$53,$53,$4f,$4f,$54,$42,$52,$44,$44,$44,$4d 548 | .byte $4e,$44,$54,$54,$4e,$45,$50,$50,$49,$4d,$53,$43,$43,$45,$4d,$4e 549 | .byte $50,$56,$56,$45,$52,$4c,$4c,$4c,$4c,$45,$45,$4e,$4e,$4f,$48,$48 550 | .byte $4c,$4c,$54,$54,$41,$41,$53,$58,$58,$59,$45,$45,$4c,$52,$4c,$52 551 | .byte $52,$41,$43,$41,$59,$58,$41,$50,$44,$43,$59,$58,$43,$43,$58,$59 552 | .byte $54,$50,$52,$43,$53,$51,$49,$45,$4c,$43,$53,$49,$4b,$43,$44,$49 553 | .byte $56,$58,$59,$58,$59,$50,$41,$50,$41,$50,$49,$53,$58,$59,$58,$41 554 | .byte $53,$41,$43,$44,$08,$84,$81,$22,$21,$26,$20,$80,$03,$20,$1c,$14 555 | .byte $14,$10,$04,$0c,$d8,$a9,$08,$8d,$b0,$02,$a9,$04,$8d,$af,$02,$a9 556 | .byte $06,$8d,$20,$d0,$8d,$21,$d0,$a9,$03,$8d,$86,$02,$a2,$05,$68,$9d 557 | .byte $a8,$02,$ca,$10,$f9,$ad,$a9,$02,$d0,$03,$ce,$a8,$02,$ce,$a9,$02 558 | .byte $ba,$8e,$ae,$02,$a9,$52,$4c,$ff,$c2,$20,$c2,$c2,$f0,$0b,$20,$7e 559 | .byte $c2,$8d,$a9,$02,$a5,$fc,$8d,$a8,$02,$60,$a2,$a4,$20,$80,$c2,$20 560 | .byte $80,$c2,$d0,$1c,$20,$7e,$c2,$a9,$fe,$85,$fd,$a9,$ff,$85,$fe,$20 561 | .byte $c2,$c2,$d0,$0c,$8d,$77,$02,$e6,$c6,$60,$20,$7e,$c2,$2c,$a2,$fb 562 | .byte $20,$8d,$c2,$95,$01,$20,$9a,$c2,$95,$00,$e8,$e8,$60,$20,$ca,$c2 563 | .byte $c9,$20,$f0,$f9,$c9,$2c,$f0,$f5,$d0,$03,$20,$ca,$c2,$20,$af,$c2 564 | .byte $0a,$0a,$0a,$0a,$85,$b4,$20,$ca,$c2,$20,$af,$c2,$05,$b4,$60,$c9 565 | .byte $3a,$90,$02,$69,$08,$29,$0f,$60,$20,$ca,$c2,$c9,$20,$f0,$f9,$c6 566 | .byte $d3,$60,$20,$cf,$ff,$c6,$d3,$c9,$0d,$60,$20,$cf,$ff,$c9,$0d,$d0 567 | .byte $f8,$a9,$3f,$20,$d2,$ff,$ae,$ae,$02,$9a,$a2,$00,$86,$c6,$20,$51 568 | .byte $c3,$a1,$d1,$c9,$27,$f0,$11,$c9,$3a,$f0,$0d,$c9,$3b,$f0,$09,$c9 569 | .byte $2c,$f0,$05,$a9,$2e,$20,$d2,$ff,$20,$ca,$c2,$c9,$2e,$f0,$f9,$85 570 | .byte $ac,$29,$7f,$a2,$20,$dd,$0a,$c0,$f0,$05,$ca,$d0,$f8,$f0,$c2,$20 571 | .byte $15,$c3,$4c,$d6,$c2,$8a,$0a,$aa,$e8,$bd,$29,$c0,$48,$ca,$bd,$29 572 | .byte $c0,$48,$60,$a5,$fc,$20,$2a,$c3,$a5,$fb,$48,$4a,$4a,$4a,$4a,$20 573 | .byte $35,$c3,$68,$29,$0f,$c9,$0a,$90,$02,$69,$06,$69,$30,$4c,$d2,$ff 574 | .byte $a9,$0d,$20,$d2,$ff,$8a,$4c,$d2,$ff,$20,$4c,$c3,$a9,$20,$4c,$d2 575 | .byte $ff,$a9,$0d,$4c,$d2,$ff,$85,$bb,$84,$bc,$a0,$00,$b1,$bb,$f0,$06 576 | .byte $20,$d2,$ff,$c8,$d0,$f6,$60,$e6,$fb,$d0,$02,$e6,$fc,$60,$a9,$0e 577 | .byte $8d,$86,$02,$8d,$20,$d0,$a9,$06,$8d,$21,$d0,$a9,$37,$85,$01,$ae 578 | .byte $ae,$02,$9a,$4c,$74,$a4,$a0,$c0,$a9,$8c,$20,$56,$c3,$a2,$3b,$20 579 | .byte $40,$c3,$ad,$a8,$02,$85,$fc,$ad,$a9,$02,$85,$fb,$20,$23,$c3,$20 580 | .byte $4c,$c3,$a2,$fb,$bd,$af,$01,$20,$2a,$c3,$20,$4c,$c3,$e8,$d0,$f4 581 | .byte $ad,$aa,$02,$4c,$d0,$c3,$20,$4e,$c2,$a2,$fb,$20,$ca,$c2,$20,$9a 582 | .byte $c2,$9d,$af,$01,$e8,$d0,$f4,$20,$4c,$c3,$bd,$aa,$02,$4c,$d0,$c3 583 | .byte $85,$aa,$a9,$20,$a0,$09,$20,$d2,$ff,$06,$aa,$a9,$30,$69,$00,$88 584 | .byte $d0,$f4,$60,$20,$49,$c2,$ae,$ae,$02,$9a,$a2,$fa,$bd,$ae,$01,$48 585 | .byte $e8,$d0,$f9,$68,$a8,$68,$aa,$68,$40,$20,$64,$c2,$a2,$3a,$20,$40 586 | .byte $c3,$20,$23,$c3,$a0,$20,$a2,$00,$20,$4c,$c3,$a1,$fb,$20,$2a,$c3 587 | .byte $a1,$fb,$20,$39,$c4,$d0,$f1,$20,$5d,$c4,$90,$e0,$60,$20,$7e,$c2 588 | .byte $a0,$20,$a2,$00,$20,$ca,$c2,$20,$9a,$c2,$81,$fb,$c1,$fb,$f0,$03 589 | .byte $4c,$d1,$c2,$20,$39,$c4,$d0,$ec,$60,$c9,$20,$90,$0c,$c9,$60,$90 590 | .byte $0a,$c9,$c0,$90,$04,$c9,$db,$90,$04,$a9,$2e,$29,$3f,$29,$7f,$91 591 | .byte $d1,$ad,$86,$02,$91,$f3,$20,$67,$c3,$c8,$c0,$28,$60,$20,$6f,$c4 592 | .byte $4c,$66,$c4,$20,$67,$c3,$a5,$fb,$c5,$fd,$a5,$fc,$e5,$fe,$60,$20 593 | .byte $94,$c4,$20,$86,$c4,$f0,$0e,$20,$86,$c4,$f0,$fb,$c9,$20,$d0,$05 594 | .byte $8d,$77,$02,$e6,$c6,$60,$20,$e4,$ff,$48,$20,$e1,$ff,$f0,$02,$68 595 | .byte $60,$4c,$d6,$c2,$a0,$28,$24,$ac,$10,$f6,$84,$c8,$84,$d0,$a9,$ff 596 | .byte $20,$c3,$ff,$a9,$ff,$85,$b8,$85,$b9,$ad,$af,$02,$85,$ba,$20,$c0 597 | .byte $ff,$a2,$00,$86,$d3,$ca,$20,$c9,$ff,$20,$cf,$ff,$20,$d2,$ff,$c9 598 | .byte $0d,$d0,$f6,$20,$cc,$ff,$a9,$91,$4c,$d2,$ff,$a0,$00,$b1,$fb,$24 599 | .byte $aa,$30,$02,$50,$0c,$a2,$1f,$dd,$3c,$c1,$f0,$2f,$ca,$e0,$15,$d0 600 | .byte $f6,$a2,$04,$dd,$49,$c1,$f0,$21,$dd,$4d,$c1,$f0,$1e,$ca,$d0,$f3 601 | .byte $a2,$38,$dd,$11,$c1,$f0,$14,$ca,$e0,$16,$d0,$f6,$b1,$fb,$3d,$fb 602 | .byte $c0,$5d,$11,$c1,$f0,$05,$ca,$d0,$f3,$a2,$00,$86,$ad,$8a,$f0,$0f 603 | .byte $a2,$11,$b1,$fb,$3d,$b5,$c0,$5d,$c6,$c0,$f0,$03,$ca,$d0,$f3,$bd 604 | .byte $ea,$c0,$85,$ab,$bd,$d8,$c0,$85,$b6,$a6,$ad,$60,$a0,$01,$b1,$fb 605 | .byte $aa,$c8,$b1,$fb,$a0,$10,$c4,$ab,$d0,$07,$20,$4a,$c5,$a0,$03,$d0 606 | .byte $02,$a4,$b6,$8e,$ae,$00,$8d,$af,$00,$60,$a0,$01,$b1,$fb,$10,$01 607 | .byte $88,$38,$65,$fb,$aa,$e8,$f0,$01,$88,$98,$65,$fc,$60,$a2,$00,$86 608 | .byte $aa,$20,$64,$c2,$20,$8c,$c5,$a5,$ad,$c9,$16,$f0,$09,$c9,$30,$f0 609 | .byte $05,$c9,$21,$d0,$11,$ea,$20,$94,$c4,$20,$51,$c3,$a2,$23,$a9,$2d 610 | .byte $20,$d2,$ff,$ca,$d0,$fa,$20,$5d,$c4,$90,$d9,$60,$a2,$2c,$20,$40 611 | .byte $c3,$20,$23,$c3,$20,$4c,$c3,$20,$75,$c6,$20,$cb,$c4,$20,$4c,$c3 612 | .byte $b1,$fb,$20,$2a,$c3,$20,$4c,$c3,$c8,$c4,$b6,$d0,$f3,$a9,$03,$38 613 | .byte $e5,$b6,$aa,$f0,$09,$20,$49,$c3,$20,$4c,$c3,$ca,$d0,$f7,$a9,$20 614 | .byte $20,$d2,$ff,$a0,$00,$a6,$ad,$d0,$11,$a2,$03,$a9,$2a,$20,$d2,$ff 615 | .byte $ca,$d0,$f8,$24,$aa,$30,$85,$4c,$6a,$c6,$24,$aa,$50,$29,$a9,$08 616 | .byte $24,$ab,$f0,$23,$b1,$fb,$29,$fc,$85,$ad,$c8,$b1,$fb,$0a,$a8,$b9 617 | .byte $3c,$03,$8d,$ae,$00,$c8,$b9,$3c,$03,$8d,$af,$00,$20,$be,$c6,$a4 618 | .byte $b6,$20,$93,$c6,$20,$cb,$c4,$bd,$5b,$c1,$20,$d2,$ff,$bd,$93,$c1 619 | .byte $20,$d2,$ff,$bd,$cb,$c1,$20,$d2,$ff,$a9,$20,$24,$ab,$f0,$03,$20 620 | .byte $49,$c3,$a2,$20,$a9,$04,$24,$ab,$f0,$02,$a2,$28,$8a,$20,$d2,$ff 621 | .byte $24,$ab,$50,$05,$a9,$23,$20,$d2,$ff,$20,$2c,$c5,$88,$f0,$16,$a9 622 | .byte $08,$24,$ab,$f0,$07,$a9,$4d,$20,$d2,$ff,$a0,$01,$b9,$ad,$00,$20 623 | .byte $2a,$c3,$88,$d0,$f7,$a0,$03,$b9,$ac,$c0,$24,$ab,$f0,$09,$b9,$af 624 | .byte $c0,$be,$b2,$c0,$20,$42,$c3,$88,$d0,$ed,$a5,$b6,$20,$67,$c3,$38 625 | .byte $e9,$01,$d0,$f8,$60,$a4,$d3,$a9,$20,$91,$d1,$c8,$c0,$28,$90,$f9 626 | .byte $60,$e4,$ab,$d0,$04,$05,$ad,$85,$ad,$60,$b9,$ad,$00,$91,$fb,$d1 627 | .byte $fb,$d0,$04,$88,$10,$f4,$60,$68,$68,$60,$d0,$1c,$8a,$05,$ab,$85 628 | .byte $ab,$a9,$04,$85,$b5,$20,$cf,$ff,$c9,$20,$f0,$0d,$c9,$24,$f0,$09 629 | .byte $c9,$28,$f0,$05,$c9,$2c,$f0,$01,$60,$c6,$b5,$d0,$e8,$60,$e0,$18 630 | .byte $30,$0e,$ad,$ae,$00,$38,$e9,$02,$38,$e5,$fb,$8d,$ae,$00,$a0,$40 631 | .byte $60,$20,$7e,$c2,$85,$fd,$a5,$fc,$85,$fe,$20,$51,$c3,$20,$e4,$c6 632 | .byte $30,$fb,$10,$f6,$a9,$00,$85,$d3,$20,$4c,$c3,$20,$23,$c3,$20,$4c 633 | .byte $c3,$20,$cf,$ff,$a9,$01,$85,$d3,$a2,$80,$d0,$05,$a2,$80,$8e,$b1 634 | .byte $02,$86,$aa,$20,$7e,$c2,$a9,$25,$85,$c8,$2c,$b1,$02,$10,$08,$a2 635 | .byte $0a,$20,$cf,$ff,$ca,$d0,$fa,$a9,$00,$8d,$b1,$02,$20,$a1,$c6,$c9 636 | .byte $46,$d0,$16,$46,$aa,$68,$68,$a2,$02,$b5,$fa,$48,$b5,$fc,$95,$fa 637 | .byte $68,$95,$fc,$ca,$d0,$f3,$4c,$64,$c5,$c9,$2e,$d0,$11,$20,$9a,$c2 638 | .byte $a0,$00,$91,$fb,$d1,$fb,$d0,$04,$20,$67,$c3,$c8,$88,$60,$a2,$fd 639 | .byte $c9,$4d,$d0,$19,$20,$9a,$c2,$a0,$00,$c9,$3f,$b0,$ef,$0a,$a8,$a5 640 | .byte $fb,$99,$3c,$03,$a5,$fc,$c8,$99,$3c,$03,$20,$a1,$c6,$95,$a9,$e0 641 | .byte $fd,$d0,$04,$a9,$07,$85,$b7,$e8,$d0,$f0,$a2,$38,$a5,$a6,$dd,$5b 642 | .byte $c1,$f0,$05,$ca,$d0,$f6,$ca,$60,$a5,$a7,$dd,$93,$c1,$d0,$f4,$a5 643 | .byte $a8,$dd,$cb,$c1,$d0,$ed,$bd,$11,$c1,$85,$ad,$20,$a1,$c6,$a0,$00 644 | .byte $e0,$20,$10,$09,$c9,$20,$d0,$08,$bd,$4d,$c1,$85,$ad,$4c,$31,$c8 645 | .byte $a0,$08,$c9,$4d,$f0,$20,$a0,$40,$c9,$23,$f0,$1a,$20,$9d,$c2,$8d 646 | .byte $ae,$00,$8d,$af,$00,$20,$a1,$c6,$a0,$20,$c9,$30,$90,$1b,$c9,$47 647 | .byte $b0,$17,$a0,$80,$c6,$d3,$20,$a1,$c6,$20,$9d,$c2,$8d,$ae,$00,$20 648 | .byte $a1,$c6,$c0,$08,$f0,$03,$20,$be,$c6,$84,$ab,$a2,$01,$c9,$58,$20 649 | .byte $9a,$c6,$a2,$04,$c9,$29,$20,$9a,$c6,$a2,$02,$c9,$59,$20,$9a,$c6 650 | .byte $a5,$ad,$29,$0d,$f0,$0a,$a2,$40,$a9,$08,$20,$81,$c6,$a9,$18,$2c 651 | .byte $a9,$1c,$a2,$82,$20,$81,$c6,$a0,$08,$a5,$ad,$c9,$20,$f0,$09,$be 652 | .byte $03,$c2,$b9,$0b,$c2,$20,$81,$c6,$88,$d0,$f4,$a5,$ab,$10,$01,$c8 653 | .byte $c8,$20,$8a,$c6,$c6,$b7,$a5,$b7,$85,$d3,$4c,$97,$c5,$20,$8d,$c2 654 | .byte $8d,$af,$02,$60,$20,$8d,$c2,$8d,$b0,$02,$60,$4c,$d1,$c2,$a0,$02 655 | .byte $84,$bc,$88,$84,$b9,$84,$bb,$88,$84,$b7,$20,$ca,$c2,$c9,$22,$d0 656 | .byte $ea,$20,$ca,$c2,$91,$bb,$c8,$e6,$b7,$c9,$22,$d0,$f4,$c6,$b7,$ad 657 | .byte $b0,$02,$85,$ba,$a5,$ac,$c9,$53,$f0,$13,$20,$c2,$c2,$f0,$09,$a2 658 | .byte $c3,$20,$80,$c2,$a9,$00,$85,$b9,$a9,$00,$6c,$30,$03,$a2,$c1,$20 659 | .byte $80,$c2,$a2,$ae,$20,$80,$c2,$6c,$32,$03,$20,$7e,$c2,$20,$ca,$c2 660 | .byte $49,$02,$4a,$4a,$08,$20,$80,$c2,$20,$51,$c3,$28,$b0,$0c,$a5,$fd 661 | .byte $65,$fb,$aa,$a5,$fe,$65,$fc,$38,$b0,$09,$a5,$fb,$e5,$fd,$aa,$a5 662 | .byte $fc,$e5,$fe,$a8,$8a,$84,$fc,$85,$fb,$84,$62,$85,$63,$08,$a9,$00 663 | .byte $85,$d3,$20,$75,$c6,$a5,$fc,$d0,$0f,$20,$49,$c3,$a5,$fb,$20,$2a 664 | .byte $c3,$a5,$fb,$20,$d0,$c3,$f0,$03,$20,$23,$c3,$20,$4c,$c3,$a2,$90 665 | .byte $a5,$01,$8d,$b1,$02,$a9,$37,$85,$01,$28,$20,$49,$bc,$20,$dd,$bd 666 | .byte $ae,$b1,$02,$86,$01,$4c,$56,$c3,$20,$8d,$c2,$aa,$a4,$d3,$b1,$d1 667 | .byte $49,$20,$f0,$a3,$8a,$a8,$20,$9a,$c2,$38,$b0,$a9,$20,$b8,$c2,$a0 668 | .byte $08,$48,$20,$ca,$c2,$c9,$31,$68,$2a,$88,$d0,$f5,$f0,$eb,$20,$b8 669 | .byte $c2,$a2,$00,$8a,$86,$fb,$85,$fc,$a8,$20,$cf,$ff,$c9,$3a,$b0,$84 670 | .byte $e9,$2f,$b0,$04,$38,$4c,$c4,$c8,$85,$fd,$06,$fb,$26,$fc,$a5,$fc 671 | .byte $85,$fe,$a5,$fb,$0a,$26,$fe,$0a,$26,$fe,$18,$65,$fb,$08,$18,$65 672 | .byte $fd,$aa,$a5,$fe,$65,$fc,$28,$69,$00,$4c,$34,$c9,$20,$7a,$c2,$a9 673 | .byte $37,$85,$01,$a2,$04,$bd,$87,$c0,$95,$aa,$ca,$10,$f8,$20,$51,$c3 674 | .byte $a6,$aa,$a5,$ab,$20,$cd,$bd,$e6,$aa,$d0,$02,$e6,$ab,$a9,$44,$20 675 | .byte $d2,$ff,$a9,$c1,$20,$d2,$ff,$a0,$00,$b1,$fb,$84,$62,$85,$63,$20 676 | .byte $d1,$bd,$20,$63,$c4,$a2,$03,$b0,$0a,$a9,$2c,$a6,$d3,$e0,$49,$90 677 | .byte $e3,$a2,$09,$86,$c6,$bd,$7d,$c0,$9d,$76,$02,$ca,$d0,$f7,$4c,$6e 678 | .byte $c3,$20,$7a,$c2,$20,$8d,$c2,$a2,$00,$81,$fb,$48,$20,$63,$c4,$68 679 | .byte $90,$f7,$60,$20,$5a,$c2,$a5,$a6,$d0,$02,$c6,$a7,$c6,$a6,$20,$30 680 | .byte $ca,$86,$b5,$a0,$02,$90,$04,$a2,$02,$a0,$00,$18,$a5,$a6,$65,$ae 681 | .byte $85,$aa,$a5,$a7,$65,$af,$85,$ab,$a1,$a4,$81,$a8,$41,$a8,$05,$b5 682 | .byte $85,$b5,$a5,$a4,$c5,$a6,$a5,$a5,$e5,$a7,$b0,$1d,$18,$b5,$a4,$79 683 | .byte $6b,$c0,$95,$a4,$b5,$a5,$79,$6c,$c0,$95,$a5,$8a,$18,$69,$04,$aa 684 | .byte $c9,$07,$90,$e8,$e9,$08,$aa,$b0,$cf,$a5,$b5,$f0,$0f,$4c,$d1,$c2 685 | .byte $38,$a2,$fe,$b5,$aa,$f5,$a6,$95,$b0,$e8,$d0,$f7,$60,$20,$62,$ca 686 | .byte $4c,$d6,$c9,$4c,$62,$ca,$c5,$a7,$d0,$02,$e4,$a6,$b0,$13,$c5,$a5 687 | .byte $d0,$02,$e4,$a4,$90,$0b,$85,$b4,$8a,$18,$65,$ae,$aa,$a5,$b4,$65 688 | .byte $af,$60,$20,$5a,$c2,$20,$7a,$c2,$20,$30,$ca,$20,$cb,$c4,$c8,$a9 689 | .byte $10,$24,$ab,$f0,$26,$a6,$fb,$a5,$fc,$20,$46,$ca,$86,$aa,$b1,$fb 690 | .byte $85,$b5,$20,$4a,$c5,$a0,$01,$20,$46,$ca,$ca,$8a,$18,$e5,$aa,$91 691 | .byte $fb,$45,$b5,$10,$19,$20,$51,$c3,$20,$23,$c3,$24,$ab,$10,$0f,$b1 692 | .byte $fb,$aa,$c8,$b1,$fb,$20,$46,$ca,$91,$fb,$8a,$88,$91,$fb,$20,$6a 693 | .byte $c6,$20,$66,$c4,$90,$b5,$60,$20,$64,$c2,$a2,$27,$20,$40,$c3,$20 694 | .byte $23,$c3,$a0,$08,$a2,$00,$20,$4c,$c3,$a1,$fb,$20,$39,$c4,$d0,$f9 695 | .byte $a2,$00,$20,$5d,$c4,$f0,$03,$4c,$ba,$ca,$60,$20,$7e,$c2,$a0,$03 696 | .byte $20,$cf,$ff,$88,$d0,$fa,$20,$ca,$c2,$c9,$2e,$f0,$02,$91,$fb,$c8 697 | .byte $c0,$20,$90,$f2,$60,$20,$7a,$c2,$a2,$00,$a1,$fb,$c1,$fd,$d0,$0b 698 | .byte $20,$67,$c3,$e6,$fd,$d0,$f3,$e6,$fe,$d0,$ef,$20,$4c,$c3,$4c,$23 699 | .byte $c3,$a9,$ff,$a2,$04,$95,$fa,$ca,$d0,$fb,$20,$ca,$c2,$a2,$05,$dd 700 | .byte $6e,$c0,$f0,$45,$ca,$d0,$f8,$86,$a9,$20,$b4,$cb,$e8,$20,$cf,$ff 701 | .byte $c9,$20,$f0,$f3,$c9,$2c,$d0,$03,$20,$7a,$c2,$20,$51,$c3,$a4,$a9 702 | .byte $b1,$fb,$20,$d6,$cb,$d0,$18,$88,$10,$f6,$20,$23,$c3,$20,$4c,$c3 703 | .byte $a4,$d3,$c0,$24,$90,$09,$20,$94,$c4,$20,$72,$c4,$20,$51,$c3,$20 704 | .byte $63,$c4,$90,$da,$a0,$27,$4c,$96,$c4,$bd,$73,$c0,$85,$a8,$bd,$78 705 | .byte $c0,$85,$a9,$aa,$f0,$06,$20,$b4,$cb,$ca,$d0,$fa,$20,$7a,$c2,$20 706 | .byte $cb,$c4,$20,$2c,$c5,$a5,$a8,$24,$ab,$d0,$09,$a8,$d0,$21,$a5,$ad 707 | .byte $d0,$1d,$f0,$0d,$a4,$a9,$b9,$ad,$00,$20,$d6,$cb,$d0,$11,$88,$d0 708 | .byte $f5,$84,$aa,$20,$8c,$c5,$20,$6f,$c4,$20,$66,$c4,$90,$d1,$60,$20 709 | .byte $6a,$c6,$f0,$f5,$20,$c0,$cb,$9d,$cc,$03,$bd,$3c,$03,$9d,$6c,$03 710 | .byte $20,$ca,$c2,$a0,$0f,$c9,$2a,$d0,$02,$a0,$00,$20,$af,$c2,$9d,$3c 711 | .byte $03,$98,$9d,$9c,$03,$60,$85,$b4,$4a,$4a,$4a,$4a,$59,$6c,$03,$39 712 | .byte $cc,$03,$29,$0f,$d0,$0a,$a5,$b4,$59,$3c,$03,$39,$9c,$03,$29,$0f 713 | .byte $60,$68,$68,$20,$cf,$ff,$c9,$57,$d0,$03,$4c,$56,$cd,$c9,$42,$d0 714 | .byte $03,$4c,$d0,$cd,$c9,$51,$d0,$03,$4c,$4f,$cd,$c9,$53,$f0,$03,$4c 715 | .byte $d1,$c2,$20,$8d,$c2,$48,$20,$8d,$c2,$48,$20,$49,$c2,$a0,$00,$b1 716 | .byte $fb,$8d,$bc,$02,$98,$91,$fb,$a9,$36,$8d,$16,$03,$a9,$cc,$8d,$17 717 | .byte $03,$a2,$fc,$4c,$ec,$c3,$a2,$03,$68,$9d,$aa,$02,$ca,$10,$f9,$68 718 | .byte $68,$ba,$8e,$ae,$02,$ad,$a8,$02,$85,$fc,$ad,$a9,$02,$85,$fb,$ad 719 | .byte $bc,$02,$a0,$00,$91,$fb,$a9,$14,$8d,$16,$03,$a9,$c2,$8d,$17,$03 720 | .byte $a9,$52,$4c,$ff,$c2,$20,$51,$c3,$ad,$11,$d0,$09,$10,$8d,$11,$d0 721 | .byte $60,$8d,$ab,$02,$08,$68,$29,$ef,$8d,$aa,$02,$8e,$ac,$02,$8c,$ad 722 | .byte $02,$68,$18,$69,$01,$8d,$a9,$02,$68,$69,$00,$8d,$a8,$02,$a9,$80 723 | .byte $8d,$bc,$02,$d0,$10,$20,$e5,$cd,$20,$dd,$fd,$d8,$a2,$05,$68,$9d 724 | .byte $a8,$02,$ca,$10,$f9,$ad,$14,$03,$8d,$bb,$02,$ad,$15,$03,$8d,$ba 725 | .byte $02,$ba,$8e,$ae,$02,$58,$ad,$aa,$02,$29,$10,$f0,$08,$20,$65,$cc 726 | .byte $a9,$52,$4c,$ff,$c2,$2c,$bc,$02,$50,$1f,$38,$ad,$a9,$02,$ed,$bd 727 | .byte $02,$8d,$b1,$02,$ad,$a8,$02,$ed,$be,$02,$0d,$b1,$02,$d0,$67,$ad 728 | .byte $bf,$02,$d0,$5f,$a9,$80,$8d,$bc,$02,$30,$12,$4e,$bc,$02,$90,$cd 729 | .byte $ae,$ae,$02,$9a,$a9,$cc,$48,$a9,$70,$48,$4c,$ba,$cd,$20,$65,$cc 730 | .byte $a9,$a8,$85,$fb,$a9,$02,$85,$fc,$20,$4c,$c3,$a0,$00,$b1,$fb,$20 731 | .byte $2a,$c3,$c8,$c0,$07,$f0,$09,$c0,$01,$f0,$f2,$20,$4c,$c3,$d0,$ed 732 | .byte $ad,$a9,$02,$ae,$a8,$02,$85,$fb,$86,$fc,$20,$49,$c3,$20,$cb,$c4 733 | .byte $20,$c7,$c5,$20,$e4,$ff,$f0,$fb,$c9,$4a,$d0,$0a,$a9,$01,$8d,$bc 734 | .byte $02,$d0,$2f,$ce,$bf,$02,$a5,$91,$c9,$7f,$d0,$26,$4c,$bd,$cc,$20 735 | .byte $f2,$cd,$a9,$40,$d0,$0a,$20,$f2,$cd,$08,$68,$8d,$aa,$02,$a9,$80 736 | .byte $8d,$bc,$02,$ba,$8e,$ae,$02,$20,$49,$c2,$20,$65,$cc,$ad,$bc,$02 737 | .byte $f0,$37,$a2,$00,$ad,$11,$d0,$a8,$29,$10,$f0,$10,$98,$29,$ef,$8d 738 | .byte $11,$d0,$ea,$ea,$a0,$0c,$ca,$d0,$fd,$88,$d0,$fa,$78,$a9,$47,$8d 739 | .byte $04,$dc,$8e,$05,$dc,$ad,$0e,$dc,$29,$80,$09,$11,$8d,$0e,$dc,$a9 740 | .byte $95,$a2,$cc,$8d,$bb,$02,$8e,$ba,$02,$ae,$ae,$02,$9a,$78,$ad,$bb 741 | .byte $02,$ae,$ba,$02,$8d,$14,$03,$8e,$15,$03,$ad,$a8,$02,$48,$ad,$a9 742 | .byte $02,$48,$ad,$aa,$02,$48,$ad,$ab,$02,$ae,$ac,$02,$ac,$ad,$02,$40 743 | .byte $20,$8d,$c2,$8d,$be,$02,$20,$8d,$c2,$8d,$bd,$02,$20,$8d,$c2,$8d 744 | .byte $bf,$02,$4c,$d6,$c2,$ad,$b8,$02,$ae,$b9,$02,$8d,$14,$03,$8e,$15 745 | .byte $03,$60,$ad,$14,$03,$ae,$15,$03,$8d,$b8,$02,$8e,$b9,$02,$a9,$95 746 | .byte $8d,$16,$03,$a9,$cc,$8d,$17,$03,$60,$a9,$07,$8d,$20,$d0,$a9,$36 747 | .byte $85,$01,$a2,$00,$bd,$e4,$cf,$9d,$d0,$02,$e8,$e0,$0d,$90,$f5,$a2 748 | .byte $2a,$20,$40,$c3,$20,$cf,$ff,$c9,$2a,$f0,$f9,$a2,$06,$dd,$d2,$cf 749 | .byte $d0,$11,$8e,$c1,$02,$8a,$0a,$aa,$e8,$bd,$d8,$cf,$48,$ca,$bd,$d8 750 | .byte $cf,$48,$60,$ca,$10,$e7,$4c,$1f,$ce,$a9,$00,$85,$fb,$a9,$bf,$85 751 | .byte $fc,$85,$fe,$a5,$fb,$69,$04,$85,$fd,$20,$fc,$c3,$20,$e1,$ff,$f0 752 | .byte $0f,$ad,$8d,$02,$f0,$f6,$a9,$00,$85,$c6,$a5,$fc,$c9,$c0,$90,$e3 753 | .byte $4c,$1f,$ce,$20,$7e,$c2,$a0,$20,$a2,$00,$20,$ca,$c2,$20,$9a,$c2 754 | .byte $81,$fb,$20,$39,$c4,$d0,$f3,$20,$51,$c3,$4c,$24,$ce,$20,$55,$cf 755 | .byte $ad,$c1,$02,$c9,$02,$d0,$03,$4c,$eb,$ce,$a2,$00,$bd,$00,$bf,$8d 756 | .byte $c3,$02,$e8,$bd,$00,$bf,$8d,$c4,$02,$8a,$4c,$cb,$ce,$20,$c2,$c2 757 | .byte $d0,$03,$4c,$8d,$ce,$20,$8d,$c2,$8d,$c3,$02,$20,$8d,$c2,$8d,$c4 758 | .byte $02,$20,$55,$cf,$ad,$c1,$02,$c9,$02,$f0,$20,$20,$0d,$cf,$a2,$0d 759 | .byte $20,$c6,$ff,$a0,$00,$20,$cf,$ff,$ea,$ea,$ea,$ea,$99,$00,$bf,$c8 760 | .byte $d0,$f3,$20,$cc,$ff,$20,$bc,$cf,$4c,$49,$ce,$20,$40,$cf,$a2,$0d 761 | .byte $20,$c9,$ff,$a0,$00,$b9,$00,$bf,$20,$d2,$ff,$a6,$90,$d0,$03,$c8 762 | .byte $d0,$f3,$20,$cc,$ff,$a9,$32,$20,$0d,$cf,$4c,$b6,$cf,$8d,$d1,$02 763 | .byte $ad,$c3,$02,$20,$79,$cf,$8e,$d8,$02,$8d,$d9,$02,$ad,$c4,$02,$20 764 | .byte $79,$cf,$8e,$db,$02,$8d,$dc,$02,$a2,$0f,$20,$c9,$ff,$a2,$00,$bd 765 | .byte $d0,$02,$20,$d2,$ff,$e8,$e0,$0d,$90,$f5,$20,$cc,$ff,$4c,$8c,$cf 766 | .byte $a2,$0f,$20,$c9,$ff,$a2,$00,$bd,$f2,$cf,$20,$d2,$ff,$e8,$e0,$08 767 | .byte $90,$f5,$4c,$cc,$ff,$a9,$0f,$a8,$a2,$08,$20,$ba,$ff,$a9,$00,$20 768 | .byte $bd,$ff,$20,$c0,$ff,$a9,$0d,$a8,$a2,$08,$20,$ba,$ff,$a9,$01,$a2 769 | .byte $f1,$a0,$cf,$20,$bd,$ff,$4c,$c0,$ff,$a2,$30,$38,$e9,$0a,$90,$03 770 | .byte $e8,$b0,$f9,$69,$3a,$60,$20,$8c,$cf,$4c,$b6,$cf,$a9,$00,$85,$90 771 | .byte $20,$51,$c3,$a9,$08,$20,$b4,$ff,$a9,$6f,$20,$96,$ff,$20,$a5,$ff 772 | .byte $c9,$30,$d0,$06,$4c,$ab,$ff,$20,$a5,$ff,$20,$d2,$ff,$c9,$0d,$d0 773 | .byte $f6,$20,$ab,$ff,$68,$68,$20,$bc,$cf,$4c,$1f,$ce,$a9,$0d,$20,$c3 774 | .byte $ff,$a9,$0f,$4c,$c3,$ff,$a9,$06,$8d,$20,$d0,$a9,$37,$85,$01,$4c 775 | .byte $d6,$c2,$3a,$52,$57,$4d,$58,$40,$72,$ce,$ac,$ce,$ac,$ce,$48,$ce 776 | .byte $c5,$cf,$85,$cf,$55,$31,$3a,$31,$33,$20,$30,$20,$31,$38,$20,$30 777 | .byte $30,$23,$42,$2d,$50,$20,$31,$33,$20,$30,$00 778 | 779 | ;; bottom part of C64 KERNAL ROM (E000-E4AF) 780 | .org $E000 781 | .byte $85,$56,$20,$0f,$bc,$a5,$61,$c9,$88,$90,$03,$20,$d4,$ba,$20,$cc 782 | .byte $bc,$a5,$07,$18,$69,$81,$f0,$f3,$38,$e9,$01,$48,$a2,$05,$b5,$69 783 | .byte $b4,$61,$95,$61,$94,$69,$ca,$10,$f5,$a5,$56,$85,$70,$20,$53,$b8 784 | .byte $20,$b4,$bf,$a9,$c4,$a0,$bf,$20,$59,$e0,$a9,$00,$85,$6f,$68,$20 785 | .byte $b9,$ba,$60,$85,$71,$84,$72,$20,$ca,$bb,$a9,$57,$20,$28,$ba,$20 786 | .byte $5d,$e0,$a9,$57,$a0,$00,$4c,$28,$ba,$85,$71,$84,$72,$20,$c7,$bb 787 | .byte $b1,$71,$85,$67,$a4,$71,$c8,$98,$d0,$02,$e6,$72,$85,$71,$a4,$72 788 | .byte $20,$28,$ba,$a5,$71,$a4,$72,$18,$69,$05,$90,$01,$c8,$85,$71,$84 789 | .byte $72,$20,$67,$b8,$a9,$5c,$a0,$00,$c6,$67,$d0,$e4,$60,$98,$35,$44 790 | .byte $7a,$00,$68,$28,$b1,$46,$00,$20,$2b,$bc,$30,$37,$d0,$20,$20,$f3 791 | .byte $ff,$86,$22,$84,$23,$a0,$04,$b1,$22,$85,$62,$c8,$b1,$22,$85,$64 792 | .byte $a0,$08,$b1,$22,$85,$63,$c8,$b1,$22,$85,$65,$4c,$e3,$e0,$a9,$8b 793 | .byte $a0,$00,$20,$a2,$bb,$a9,$8d,$a0,$e0,$20,$28,$ba,$a9,$92,$a0,$e0 794 | .byte $20,$67,$b8,$a6,$65,$a5,$62,$85,$65,$86,$62,$a6,$63,$a5,$64,$85 795 | .byte $63,$86,$64,$a9,$00,$85,$66,$a5,$61,$85,$70,$a9,$80,$85,$61,$20 796 | .byte $d7,$b8,$a2,$8b,$a0,$00,$4c,$d4,$bb,$c9,$f0,$d0,$07,$84,$38,$86 797 | .byte $37,$4c,$63,$a6,$aa,$d0,$02,$a2,$1e,$4c,$37,$a4,$20,$d2,$ff,$b0 798 | .byte $e8,$60,$20,$cf,$ff,$b0,$e2,$60,$20,$ad,$e4,$b0,$dc,$60,$20,$c6 799 | .byte $ff,$b0,$d6,$60,$20,$e4,$ff,$b0,$d0,$60,$20,$8a,$ad,$20,$f7,$b7 800 | .byte $a9,$e1,$48,$a9,$46,$48,$ad,$0f,$03,$48,$ad,$0c,$03,$ae,$0d,$03 801 | .byte $ac,$0e,$03,$28,$6c,$14,$00,$08,$8d,$0c,$03,$8e,$0d,$03,$8c,$0e 802 | .byte $03,$68,$8d,$0f,$03,$60,$20,$d4,$e1,$a6,$2d,$a4,$2e,$a9,$2b,$20 803 | .byte $d8,$ff,$b0,$95,$60,$a9,$01,$2c,$a9,$00,$85,$0a,$20,$d4,$e1,$a5 804 | .byte $0a,$a6,$2b,$a4,$2c,$20,$d5,$ff,$b0,$57,$a5,$0a,$f0,$17,$a2,$1c 805 | .byte $20,$b7,$ff,$29,$10,$d0,$17,$a5,$7a,$c9,$02,$f0,$07,$a9,$64,$a0 806 | .byte $a3,$4c,$1e,$ab,$60,$20,$b7,$ff,$29,$bf,$f0,$05,$a2,$1d,$4c,$37 807 | .byte $a4,$a5,$7b,$c9,$02,$d0,$0e,$86,$2d,$84,$2e,$a9,$76,$a0,$a3,$20 808 | .byte $1e,$ab,$4c,$2a,$a5,$20,$8e,$a6,$20,$33,$a5,$4c,$77,$a6,$20,$19 809 | .byte $e2,$20,$c0,$ff,$b0,$0b,$60,$20,$19,$e2,$a5,$49,$20,$c3,$ff,$90 810 | .byte $c3,$4c,$f9,$e0,$a9,$00,$20,$bd,$ff,$a2,$01,$a0,$00,$20,$ba,$ff 811 | .byte $20,$06,$e2,$20,$57,$e2,$20,$06,$e2,$20,$00,$e2,$a0,$00,$86,$49 812 | .byte $20,$ba,$ff,$20,$06,$e2,$20,$00,$e2,$8a,$a8,$a6,$49,$4c,$ba,$ff 813 | .byte $20,$0e,$e2,$4c,$9e,$b7,$20,$79,$00,$d0,$02,$68,$68,$60,$20,$fd 814 | .byte $ae,$20,$79,$00,$d0,$f7,$4c,$08,$af,$a9,$00,$20,$bd,$ff,$20,$11 815 | .byte $e2,$20,$9e,$b7,$86,$49,$8a,$a2,$01,$a0,$00,$20,$ba,$ff,$20,$06 816 | .byte $e2,$20,$00,$e2,$86,$4a,$a0,$00,$a5,$49,$e0,$03,$90,$01,$88,$20 817 | .byte $ba,$ff,$20,$06,$e2,$20,$00,$e2,$8a,$a8,$a6,$4a,$a5,$49,$20,$ba 818 | .byte $ff,$20,$06,$e2,$20,$0e,$e2,$20,$9e,$ad,$20,$a3,$b6,$a6,$22,$a4 819 | .byte $23,$4c,$bd,$ff,$a9,$e0,$a0,$e2,$20,$67,$b8,$20,$0c,$bc,$a9,$e5 820 | .byte $a0,$e2,$a6,$6e,$20,$07,$bb,$20,$0c,$bc,$20,$cc,$bc,$a9,$00,$85 821 | .byte $6f,$20,$53,$b8,$a9,$ea,$a0,$e2,$20,$50,$b8,$a5,$66,$48,$10,$0d 822 | .byte $20,$49,$b8,$a5,$66,$30,$09,$a5,$12,$49,$ff,$85,$12,$20,$b4,$bf 823 | .byte $a9,$ea,$a0,$e2,$20,$67,$b8,$68,$10,$03,$20,$b4,$bf,$a9,$ef,$a0 824 | .byte $e2,$4c,$43,$e0,$20,$ca,$bb,$a9,$00,$85,$12,$20,$6b,$e2,$a2,$4e 825 | .byte $a0,$00,$20,$f6,$e0,$a9,$57,$a0,$00,$20,$a2,$bb,$a9,$00,$85,$66 826 | .byte $a5,$12,$20,$dc,$e2,$a9,$4e,$a0,$00,$4c,$0f,$bb,$48,$4c,$9d,$e2 827 | .byte $81,$49,$0f,$da,$a2,$83,$49,$0f,$da,$a2,$7f,$00,$00,$00,$00,$05 828 | .byte $84,$e6,$1a,$2d,$1b,$86,$28,$07,$fb,$f8,$87,$99,$68,$89,$01,$87 829 | .byte $23,$35,$df,$e1,$86,$a5,$5d,$e7,$28,$83,$49,$0f,$da,$a2,$a5,$66 830 | .byte $48,$10,$03,$20,$b4,$bf,$a5,$61,$48,$c9,$81,$90,$07,$a9,$bc,$a0 831 | .byte $b9,$20,$0f,$bb,$a9,$3e,$a0,$e3,$20,$43,$e0,$68,$c9,$81,$90,$07 832 | .byte $a9,$e0,$a0,$e2,$20,$50,$b8,$68,$10,$03,$4c,$b4,$bf,$60,$0b,$76 833 | .byte $b3,$83,$bd,$d3,$79,$1e,$f4,$a6,$f5,$7b,$83,$fc,$b0,$10,$7c,$0c 834 | .byte $1f,$67,$ca,$7c,$de,$53,$cb,$c1,$7d,$14,$64,$70,$4c,$7d,$b7,$ea 835 | .byte $51,$7a,$7d,$63,$30,$88,$7e,$7e,$92,$44,$99,$3a,$7e,$4c,$cc,$91 836 | .byte $c7,$7f,$aa,$aa,$aa,$13,$81,$00,$00,$00,$00,$20,$cc,$ff,$a9,$00 837 | .byte $85,$13,$20,$7a,$a6,$58,$a2,$80,$6c,$00,$03,$8a,$30,$03,$4c,$3a 838 | .byte $a4,$4c,$74,$a4,$20,$53,$e4,$20,$bf,$e3,$20,$22,$e4,$a2,$fb,$9a 839 | .byte $d0,$e4,$e6,$7a,$d0,$02,$e6,$7b,$ad,$60,$ea,$c9,$3a,$b0,$0a,$c9 840 | .byte $20,$f0,$ef,$38,$e9,$30,$38,$e9,$d0,$60,$80,$4f,$c7,$52,$58,$a9 841 | .byte $4c,$85,$54,$8d,$10,$03,$a9,$48,$a0,$b2,$8d,$11,$03,$8c,$12,$03 842 | .byte $a9,$91,$a0,$b3,$85,$05,$84,$06,$a9,$aa,$a0,$b1,$85,$03,$84,$04 843 | .byte $a2,$1c,$bd,$a2,$e3,$95,$73,$ca,$10,$f8,$a9,$03,$85,$53,$a9,$00 844 | .byte $85,$68,$85,$13,$85,$18,$a2,$01,$8e,$fd,$01,$8e,$fc,$01,$a2,$19 845 | .byte $86,$16,$38,$20,$9c,$ff,$86,$2b,$84,$2c,$38,$20,$99,$ff,$86,$37 846 | .byte $84,$38,$86,$33,$84,$34,$a0,$00,$98,$91,$2b,$e6,$2b,$d0,$02,$e6 847 | .byte $2c,$60,$a5,$2b,$a4,$2c,$20,$08,$a4,$a9,$73,$a0,$e4,$20,$1e,$ab 848 | .byte $a5,$37,$38,$e5,$2b,$aa,$a5,$38,$e5,$2c,$20,$cd,$bd,$a9,$60,$a0 849 | .byte $e4,$20,$1e,$ab,$4c,$44,$a6,$8b,$e3,$83,$a4,$7c,$a5,$1a,$a7,$e4 850 | .byte $a7,$86,$ae,$a2,$0b,$bd,$47,$e4,$9d,$00,$03,$ca,$10,$f7,$60,$00 851 | .byte $20,$42,$41,$53,$49,$43,$20,$42,$59,$54,$45,$53,$20,$46,$52,$45 852 | .byte $45,$0d,$00,$93,$0d,$20,$20,$20,$20,$2a,$2a,$2a,$2a,$20,$43,$4f 853 | .byte $4d,$4d,$4f,$44,$4f,$52,$45,$20,$36,$34,$20,$42,$41,$53,$49,$43 854 | .byte $20,$56,$32,$20,$2a,$2a,$2a,$2a,$0d,$0d,$20,$36,$34,$4b,$20,$52 855 | .byte $41,$4d,$20,$53,$59,$53,$54,$45,$4d,$20,$20,$00 856 | 857 | 858 | ;;; ---------------------------------------------------------------------------- 859 | ;;; ------------- C64 KERNAL ROM emulation and stub routines ---------------- 860 | ;;; ---------------------------------------------------------------------------- 861 | 862 | LINEBUF = $0400 ; screen buffer start in memory 863 | NUMCOLS = 80 ; length of a row 864 | NUMROWS = 25 ; number of rows in buffer 865 | INPUT_UCASE = 1 ; convert all input to uppercase 866 | SUPPRESS_NP = 1 ; do not output non-printable characters 867 | 868 | .org $F000 869 | 870 | WSTART: CLD ; clear decimal mode flag 871 | LDX #$FF ; reset stack pointer 872 | TXS 873 | CLI ; allow interrupts 874 | JMP ($A002) ; BASIC warm start 875 | 876 | ENTRY: LDX #RAMTOP 878 | JSR $FF99 ; set RAM top 879 | LDX #<(LINEBUF + (NUMCOLS*NUMROWS) + 1) 880 | LDY #>(LINEBUF + (NUMCOLS*NUMROWS) + 1) 881 | JSR $FF9C ; set RAM bottom 882 | LDA #WSTART ; (we are not using IRQs) 886 | STA $0317 887 | STA $0319 888 | JMP ($A000) ; BASIC cold start 889 | 890 | .include "kernal.asm" 891 | -------------------------------------------------------------------------------- /basic.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhansel/smon6502/6b149bc3277fd9b2648fb7df281d55b3f54fcf5e/basic.bin -------------------------------------------------------------------------------- /config.asm: -------------------------------------------------------------------------------- 1 | ; Base address of the VIA chip in the system. The VIA is only 2 | ; necessary if you 3 | ; - want to use the trace (TW/TQ/TS) functions in SMON 4 | ; and/or 5 | ; - want to use the VIA UART driver 6 | ; If neither of these applies, set the VIA address to 0 7 | VIA = $6000 8 | 9 | ; Highest address of installed RAM - all RAM is assumed to be 10 | ; in one consecutive range from 0-RAMTOP 11 | RAMTOP = $3FFF 12 | 13 | ; main CPU clock rate (used for UART timing) 14 | CPU_CLOCK_RATE = 1000000 15 | 16 | ; Currently supported UART options are: 17 | ; 6522: MOS 6522 (VIA) 18 | ; 6551: MOS 6551 or WDC 65C51N (ACIA) 19 | ; 6850: Motorola MC6850 UART 20 | UART_TYPE = 6551 21 | 22 | ;;; ------------------------------------------------------------------ 23 | 24 | VIA_DRB = VIA + 0 ; VIA port B data register 25 | VIA_DRA = VIA + 1 ; VIA port A data register 26 | VIA_DDRB = VIA + 2 ; VIA port B data direction register 27 | VIA_DDRA = VIA + 3 ; VIA port A data direction register 28 | VIA_T1CL = VIA + 4 ; VIA timer 1 counter low register 29 | VIA_T1CH = VIA + 5 ; VIA timer 1 counter high register 30 | VIA_T1LL = VIA + 6 ; VIA timer 1 latch low register 31 | VIA_T1LH = VIA + 7 ; VIA timer 1 latch high register 32 | VIA_T2CL = VIA + 8 ; VIA timer 2 counter low register 33 | VIA_T2CH = VIA + 9 ; VIA timer 2 counter low register 34 | VIA_SR = VIA + 10 ; VIA shift register 35 | VIA_ACR = VIA + 11 ; VIA peripheral control register 36 | VIA_PCR = VIA + 12 ; VIA peripheral control register 37 | VIA_IFR = VIA + 13 ; VIA interrupt flag register 38 | VIA_IER = VIA + 14 ; VIA interrupt enable register 39 | -------------------------------------------------------------------------------- /kernal.asm: -------------------------------------------------------------------------------- 1 | ;;; ---------------------------------------------------------------------------- 2 | ;;; ---------------------- C64 KERNAL routines and stubs -------------------- 3 | ;;; ---------------------------------------------------------------------------- 4 | 5 | TERMCOL = $01 ; cursor column on terminal 6 | STOPFLAG = $91 ; flag for "STOP" key pressed 7 | LASTRECV = $93 ; previous received char 8 | ROWLIMIT = $9C ; number of rows currently in buffer 9 | TMPBUF = $9E ; temporary storage 10 | LASTCOL = $C8 ; last cursor column for input 11 | ESCFLAG = $D0 ; ESC sequence flag (shared with CRFLAG) 12 | CRFLAG = $D0 ; <>0 => there is input ready to read 13 | LINEPTR = $D1 ; pointer to screen buffer for current line 14 | CSRCOL = $D3 ; current cursor column 15 | CSRROW = $D6 ; current cursor row 16 | LASTPRNT = $D7 ; last character printed to screen 17 | 18 | 19 | ;; get/set bottom-of-memory address 20 | KRWMEMB:BCC WMEMB 21 | LDX $0281 22 | LDY $0282 23 | WMEMB: STX $0281 24 | STY $0282 25 | RTS 26 | 27 | ;; get/set top-of-memory address 28 | KRWMEMT:BCC WMEMT 29 | LDX $0283 30 | LDY $0284 31 | WMEMT: STX $0283 32 | STY $0284 33 | RTS 34 | 35 | ;; set flag for kernal output messages 36 | KMSGFLG:STA $9D 37 | RTS 38 | 39 | ;; stub routine for I/O functions 40 | KIOSTUB:LDA #$05 ; "device not present" error 41 | SEC ; signal error 42 | KSTUB: RTS 43 | 44 | ;; STOP (FFE1): test stop key (Z set if stop key pressed) 45 | KSTOP: LDA STOPFLAG 46 | CMP #$7F ; have STOP flag? 47 | BEQ STOPL1 ; jump if so 48 | JSR GETIN1 49 | BEQ STOPL2 ; done if nothing 50 | STA $0277 ; save received character 51 | INC $C6 52 | LDA STOPFLAG 53 | CMP #$7F ; have STOP flag now? 54 | BNE STOPR ; done if not 55 | STOPL1: LDA #$FF ; clear STOP flag 56 | STA STOPFLAG 57 | LDA #$7F 58 | CMP #$7F ; set Z flag 59 | RTS 60 | STOPL2: LDA #$FF ; clear Z flag 61 | STOPR: RTS 62 | 63 | ;; GETIN (FFE4): get input character (0 if none) 64 | KGETIN: LDA $C6 65 | BEQ GETIN1 66 | DEC $C6 67 | LDA $0277 68 | RTS 69 | GETIN1: JSR UAGET ; get char from UART, zero if none 70 | CMP #$00 ; did we receive a character? 71 | BEQ GETINR ; if not, return with 0 72 | CMP #27 ; is it ESC (stop)? 73 | BEQ SETSF ; set STOP flag if so 74 | CMP #3 ; is it CTRL-C (stop)? 75 | BEQ SETSF ; set STOP flag if so 76 | JMP MAPCHR 77 | SETSF: LDA #$7F ; set stop flag 78 | STA STOPFLAG 79 | GETINR: RTS 80 | 81 | ;; CHRIN (FFCF): get next input character (read until CR if none) 82 | KCHRIN: TXA ; save X 83 | PHA 84 | TYA ; save Y 85 | PHA 86 | LDA CRFLAG ; have we received a CR? 87 | BNE CHRIN1 ; if yes then get next char 88 | JSR GETLIN ; no => get input from UART until CR 89 | BCC CHRIN4 ; jump if there was no input at all 90 | LDA #$80 ; now have received CR 91 | STA CRFLAG 92 | CHRIN1: LDY CSRCOL ; current cursor (read) position 93 | CPY LASTCOL ; have we reached the end? 94 | BCS CHRIN3 ; jump if so 95 | LDA (LINEPTR),Y ; get next character 96 | INC CSRCOL ; move cursor position 97 | JMP CHRIN2 ; done 98 | CHRIN3: LDA #$00 ; turn off CR flag 99 | STA CRFLAG 100 | INC CSRCOL ; still increment CSRCOL 101 | CHRIN4: LDA #13 ; return CR 102 | CHRIN2: STA TMPBUF 103 | PLA ; restore Y 104 | TAY 105 | PLA ; restor X 106 | TAX 107 | LDA TMPBUF ; get character back 108 | CLC ; no error 109 | RTS 110 | 111 | ;; read UART input into line buffer up to but not including CR 112 | ;; returns with carry set if there was any input 113 | ;; (I flag gets set by BRK and C64 kernal clears it in CHRIN so 114 | ;; we need to do that too) 115 | GETLIN: CLI 116 | JSR CHKCOL ; check terminal cursor column 117 | LDY CSRCOL 118 | LDA CSRROW 119 | PHA ; save current row 120 | LDA #0 121 | STA STOPFLAG 122 | STA ESCFLAG 123 | WTCHR: JSR UAGETW ; wait for character from UART 124 | BIT ESCFLAG ; are we in an ESC sequence? 125 | BMI ESCHDL ; go to ESC handler 126 | CMP #27 ; is it ESC? 127 | BEQ ESCS ; go to ESC start handler 128 | CMP #8 ; is it backspace? 129 | BEQ CHRBS ; go to DELETE handler 130 | CMP #127 ; is it delete? 131 | BEQ CHRBS ; go to DELETE handler 132 | JSR MAPCHR ; map ASCII 133 | BEQ WTCHR ; ignore character if we can not map it 134 | CMP #13 ; was character CR (or LF)? 135 | BEQ GLDONE ; if yes then we're done 136 | CPY #NUMCOLS ; are we at the end of the line buffer? 137 | BCS WTCHR ; if so then ignore input 138 | STA (LINEPTR),Y ; store character 139 | INY 140 | JSR UAPUTW ; output character 141 | JMP WTCHR ; wait for more input 142 | GLDONE: LDY #NUMCOLS-1 ; start Y at line length 143 | GLL1: LDA (LINEPTR),Y ; get character from buffer 144 | CMP #' ' ; is it "space" 145 | BNE GLL2 ; jump if not 146 | DEY ; next position 147 | BNE GLL1 ; repeat until 0 148 | GLL2: INY ; Y now is first space character pos 149 | STY LASTCOL ; set column for end-of-input 150 | STY TERMCOL ; set terminal cursor column 151 | PLA ; get original cursor row back 152 | CMP CSRROW ; compare to current 153 | BEQ GLL3 ; jump if same 154 | LDY #0 ; cursor row changed 155 | STY CSRCOL ; => input start at first column 156 | SEC 157 | RTS 158 | GLL3 CPY CSRCOL ; do we have any non-space characters 159 | BEQ GLRETC ; jump if CSRCOL==TERMCOL, i.e. no input 160 | BCS GLRET ; after initial cursor position? 161 | STY CSRCOL ; no => set beginning=end of input 162 | GLRETC: CLC ; no input => clear carry 163 | GLRET: RTS 164 | 165 | ;; backspace handling 166 | CHRBS: CPY #0 ; is cursor at start of line? 167 | BEQ WTCHR ; if so then we cannot backspace any more 168 | DEY ; cursor one back 169 | LDA #8 ; send backspace-space-backspace 170 | JSR UAPUTW 171 | LDA #' ' 172 | STA (LINEPTR),Y ; clear out character in line buffer 173 | JSR UAPUTW 174 | LDA #8 175 | JSR UAPUTW 176 | JMP WTCHR ; wait for more input 177 | 178 | ;; ESC (cursor) sequence handling 179 | ESCS: LDA #$80 ; start ESC mode 180 | .byte $2C ; skip next 2-byte instruction 181 | ESCCLR: LDA #$00 ; clear ESC flag 182 | STA ESCFLAG 183 | JMP WTCHR 184 | ESCHDL: BIT ESCFLAG 185 | BVS ESCL1 ; jump if we are waiting for char #3 186 | CMP #'[' ; did we receive expected second char? 187 | BNE ESCCLR ; if not, end ESC sequence 188 | LDA #$C0 ; set flag to wait for third char 189 | STA ESCFLAG 190 | JMP WTCHR ; wait for next input character 191 | ESCL1: CMP #'A' ; ESC [ A (cursor up)? 192 | BEQ ESCCU ; jump if so 193 | CMP #'B' ; ESC [ A (cursor down)? 194 | BEQ ESCCD ; jump if so 195 | CMP #'C' ; ESC [ C (cursor right)? 196 | BEQ ESCCR ; jump if so 197 | CMP #'D' ; ESC [ D (cursor left)? 198 | BEQ ESCCL ; jump if so 199 | BNE ESCCLR ; end ESC sequence 200 | ESCCU: LDA CSRROW 201 | CMP ROWLIMIT ; is cursor in first row? 202 | BEQ ESCCLR ; if so then we cannot go up any more 203 | JSR ROWUP ; move cursor pointer up one row 204 | LDA #'A' 205 | JMP ESCPS ; send "cursor up" sequence 206 | ESCCD: LDA CSRROW 207 | CMP #NUMROWS-1 ; is cursor in last row? 208 | BEQ ESCCD1 ; if so then we cannot go down any more 209 | JSR ROWDN ; move cursor pointer down one row 210 | LDA #'B' 211 | JMP ESCPS ; send "cursor down" sequence 212 | ESCCD1: JSR SCRL ; scroll line buffer down 213 | LDA #10 ; send line feed 214 | JSR UAPUTW 215 | JMP ESCCLR ; end ESC mode 216 | ESCCL: CPY #0 ; is cursor at start of line? 217 | BEQ ESCCLR ; if so then we cannot go left any more 218 | DEY ; move cursor pointer left 219 | JMP ESCPS 220 | ESCCR: CPY #NUMCOLS-1 ; is cursor at end of line? 221 | BEQ ESCCLR ; if so then we cannot go right any more 222 | INY ; move cursor pointer right 223 | ESCPS: PHA ; save final character 224 | LDA #27 ; send cursor sequence back to terminal 225 | JSR UAPUTW 226 | LDA #'[' 227 | JSR UAPUTW 228 | PLA 229 | JSR UAPUTW 230 | JMP ESCCLR ; clear ESC mode and wait for next char 231 | 232 | ;; map input char: 233 | ;; - clear bit 7 of character 234 | ;; - ignore character codes < 32 (space) 235 | ;; - map LF to CR, ignore LF after CR 236 | ;; - return with Z bit set if invalid character 237 | MAPCHR: PHA 238 | LDA LASTRECV ; transfer previous character 239 | STA TMPBUF ; to TMPBUF 240 | PLA 241 | STA LASTRECV ; rememver new character 242 | AND #$7F ; clear bit 7 243 | CMP #13 ; is character CR? 244 | BEQ MCICR ; jump if so 245 | CMP #10 ; is character NL? 246 | BNE MC1 ; jump if not 247 | LDA #13 248 | CMP TMPBUF ; was previous character CR? 249 | BEQ MCINUL ; if so then ignore NL 250 | BNE MCICR ; return CR 251 | MC1: 252 | .if INPUT_UCASE 253 | CMP #'a' 254 | BCC MC2 255 | CMP #'z'+1 256 | BCS MC2 257 | AND #$DF 258 | MC2: 259 | .endif 260 | CMP #' ' ; character < ' '? 261 | BCC MCINUL ; skip if so 262 | ORA #0 ; clear Z flag 263 | RTS 264 | MCINUL: LDA #00 265 | RTS 266 | MCICR: LDA #13 267 | MCIR: RTS 268 | 269 | ;; process CR output 270 | PROCCR: TYA 271 | PHA 272 | TXA 273 | PHA 274 | LDA #13 ; output CR 275 | JSR UAPUTW 276 | LDA #10 ; output LF 277 | JSR UAPUTW 278 | LDA #0 ; beginning of line 279 | STA TERMCOL ; reset terminal cursor position 280 | STA CSRCOL ; reset cursor pointer 281 | STA LASTCOL ; reset last input column 282 | STA CRFLAG ; no input waiting 283 | LDA CSRROW 284 | CMP #NUMROWS-1 ; cursor in last row? 285 | BNE PROC1 286 | JSR SCRL ; scroll buffer 287 | JMP PROC2 288 | PROC1: JSR ROWDN ; move cursor one row down 289 | PROC2: PLA 290 | TAX 291 | PLA 292 | TAY 293 | RTS 294 | 295 | ;; move cursor row (and line pointer) down 296 | ROWDN: INC CSRROW 297 | CLC 298 | LDA LINEPTR 299 | ADC #NUMCOLS 300 | STA LINEPTR 301 | LDA LINEPTR+1 302 | ADC #0 303 | STA LINEPTR+1 304 | RTS 305 | 306 | ;; move cursor row (and line pointer) up 307 | ROWUP: DEC CSRROW 308 | SEC 309 | LDA LINEPTR 310 | SBC #NUMCOLS 311 | STA LINEPTR 312 | LDA LINEPTR+1 313 | SBC #0 314 | STA LINEPTR+1 315 | RTS 316 | 317 | ;; scroll screen buffer 318 | SCRL: PHA 319 | TXA 320 | PHA 321 | TYA 322 | PHA 323 | LDA CSRROW 324 | PHA 325 | LDA LINEPTR 326 | PHA 327 | LDA LINEPTR+1 328 | PHA 329 | LDA #LINEBUF 332 | STA LINEPTR+1 333 | LDX #NUMROWS-1 334 | SCRL1: LDA LINEPTR 335 | STA $C1 336 | LDA LINEPTR+1 337 | STA $C2 338 | JSR ROWDN ; go one row down 339 | LDY #NUMCOLS-1 ; fill line buffer 340 | SCRL2: LDA (LINEPTR),Y ; move character 341 | STA ($C1),Y ; one row up 342 | DEY 343 | BPL SCRL2 ; repeat for all columns 344 | DEX 345 | BNE SCRL1 346 | JSR CLRL ; clear bottom row 347 | LDA ROWLIMIT 348 | BEQ SCRL3 349 | DEC ROWLIMIT 350 | SCRL3: PLA 351 | STA LINEPTR+1 352 | PLA 353 | STA LINEPTR 354 | PLA 355 | STA CSRROW 356 | PLA 357 | TAY 358 | PLA 359 | TAX 360 | PLA 361 | RTS 362 | 363 | ;; clear current row 364 | CLRL: LDY #NUMCOLS-1 ; fill line buffer 365 | LDA #' ' ; with SPACE 366 | CLRL1: STA (LINEPTR),Y 367 | DEY 368 | BPL CLRL1 ; repeat for all columns 369 | RTS 370 | 371 | ;; clear line buffer 372 | CLRLB: LDA #LINEBUF 375 | STA LINEPTR+1 376 | LDA #0 377 | STA CSRROW 378 | LDX #NUMROWS 379 | CLRLB1: JSR CLRL ; clear row 380 | JSR ROWDN ; next row 381 | DEX 382 | BNE CLRLB1 ; repeat for all rows 383 | JSR ROWUP ; gone one too far 384 | RTS 385 | 386 | ;; CHROUT (FFD2): write output character 387 | KCHROUT:STA LASTPRNT 388 | TYA 389 | PHA 390 | LDA LASTPRNT 391 | CMP #13 ; was it CR? 392 | BNE CHROL3 ; jump if not 393 | JSR PREOL ; print characters in line buffer after cursor 394 | JSR PROCCR ; print CR/LF and clear line buffer 395 | JMP CHRODN ; done 396 | CHROL3: 397 | .if SUPPRESS_NP 398 | CMP #$80 ; ignore 399 | BCS CHRODN ; non-printable 400 | CMP #$20 ; characters 401 | BCC CHRODN 402 | .endif 403 | JSR CHKCOL 404 | ;; output character 405 | LDA LASTPRNT 406 | JSR UAPUTW ; output character 407 | LDY CSRCOL 408 | STA (LINEPTR),Y ; write output character to line buffer 409 | INY 410 | STY CSRCOL 411 | STY TERMCOL ; remember previous column 412 | LDA #0 ; outputting character stops... 413 | STA CRFLAG ; ...input sequence (CRFLAG=0) 414 | CPY #NUMCOLS ; are we at the end of the line buffer? 415 | BCC CHRODN ; jump if not 416 | JSR PROCCR ; go to next line 417 | CHRODN: PLA ; restore Y 418 | TAY 419 | LDA LASTPRNT ; get printed character back 420 | CLC ; no error 421 | RTS 422 | 423 | ;; make sure terminal cursor position agrees with CSRCOL 424 | CHKCOL: LDY CSRCOL 425 | CPY TERMCOL 426 | BCS CHROL5 ; jump if CSRCOL>=TERMCOL 427 | ;; cursor has moved back => output CR followed by 428 | ;; all characters from the line buffer up to new cursor pos 429 | LDA #13 ; output CR 430 | JSR UAPUTW 431 | LDY #0 432 | CHROL4: CPY CSRCOL 433 | BEQ CHROL5 434 | LDA (LINEPTR),Y 435 | JSR UAPUTW 436 | INY 437 | JMP CHROL4 438 | CHROL5: BEQ CHROL7 ; jump if CSRCOL==TERMCOL 439 | ;; cursor has moved forward => output line buffer up to new position 440 | CHROL6: LDA (LINEPTR),Y 441 | JSR UAPUTW 442 | DEY 443 | CPY TERMCOL 444 | BNE CHROL6 445 | CHROL7: STY TERMCOL 446 | RTS 447 | 448 | ;; re-print the current line 449 | PRLINE: LDA #13 ; print CR 450 | JSR UAPUTW ; (move terminal cursor to beginning of line) 451 | LDA #0 ; set terminal cursor position to 0 452 | STA TERMCOL ; fall through to print line buffer 453 | 454 | ;; print characters in line buffer after terminal cursor position 455 | PREOL: LDY #NUMCOLS-1 ; start at end of line buffer 456 | PREOL0: CPY TERMCOL ; have we reached the cursor column yet? 457 | BEQ PREOL2 ; jump if Y<=TERMCOL 458 | BCC PREOL2 459 | LDA (LINEPTR),Y ; get character 460 | DEY 461 | CMP #$20 ; is it SPACE? 462 | BEQ PREOL0 ; repeat if so 463 | INY ; remember one more than last 464 | STY TMPBUF ; non-space column after cursor 465 | LDY TERMCOL 466 | DEY 467 | PREOL1: INY 468 | LDA (LINEPTR),Y ; get character 469 | .if SUPPRESS_NP 470 | CMP #$80 ; ignore 471 | BCS PREOL3 ; non-printable 472 | CMP #$20 ; characters 473 | BCS PREOL4 474 | PREOL3: LDA #$20 475 | PREOL4: .endif 476 | JSR UAPUTW ; output character 477 | CPY TMPBUF 478 | BNE PREOL1 479 | STY TERMCOL ; set new cursor position 480 | PREOL2: RTS 481 | 482 | ;; NMI handler 483 | NMI: SEI 484 | JMP ($0318) ; jump to NMI vector 485 | 486 | ;; IRQ and BRK handler 487 | IRQ: PHA 488 | TXA 489 | PHA 490 | TYA 491 | PHA 492 | TSX 493 | LDA $0104,X ; get status byte from stack 494 | AND #$10 ; "B" (BRK) flag set 495 | BEQ BRK ; jump if not 496 | JMP ($0316) ; jump to BREAK vector 497 | BRK: JMP ($0314) ; jump to IRQ vector 498 | 499 | ;; interrupt stub function 500 | ISTUB: RTI 501 | 502 | ;; RESET handler 503 | RESET: SEI ; prevent IRQ interrupts 504 | CLD ; clear decimal mode flag 505 | LDX #$FF ; initialize stack pointer 506 | TXS 507 | LDA #ISTUB 512 | STA $0315 513 | STA $0317 514 | STA $0319 515 | JSR UAINIT ; init UART 516 | LDA #0 517 | STA LASTPRNT 518 | STA LASTRECV 519 | STA CSRCOL 520 | LDA #NUMROWS-1 521 | STA CSRROW 522 | STA ROWLIMIT 523 | LDA #$FF ; clear stop flag 524 | STA STOPFLAG 525 | JSR CLRLB ; clear line buffer 526 | JSR PROCCR ; set cursor to start of line 527 | JMP ENTRY 528 | 529 | ;;; ---------------------------------------------------------------------------- 530 | ;;; ---------------------- UART communication functions ----------------------- 531 | ;;; ---------------------------------------------------------------------------- 532 | 533 | .if UART_TYPE==6522 534 | .include "uart_6522.asm" 535 | .else 536 | .if UART_TYPE==6551 537 | .include "uart_6551.asm" 538 | .else 539 | .if UART_TYPE==6850 540 | .include "uart_6850.asm" 541 | .else 542 | .err "invalid UART_TYPE" 543 | .endif 544 | .endif 545 | .endif 546 | 547 | ;;; ---------------------------------------------------------------------------- 548 | ;;; ------------------------- C64 kernal jump table -------------------------- 549 | ;;; ---------------------------------------------------------------------------- 550 | 551 | .org $FF81 552 | JMP KSTUB ; FF81: 553 | JMP KSTUB ; FF84: 554 | JMP KSTUB ; FF87: 555 | JMP KSTUB ; FF8A: 556 | JMP KSTUB ; FF8D: 557 | JMP KMSGFLG ; FF90: set kernal message output flag 558 | JMP KSTUB ; FF93: 559 | JMP KSTUB ; FF96: 560 | JMP KRWMEMT ; FF99: get or set memory top address 561 | JMP KRWMEMB ; FF9C: get or set memory bottom address 562 | JMP KSTUB ; FF9F: 563 | JMP KSTUB ; FFA2: 564 | JMP KSTUB ; FFA5: 565 | JMP KSTUB ; FFA8: 566 | JMP KSTUB ; FFAB: 567 | JMP KSTUB ; FFAE: 568 | JMP KSTUB ; FFB1: 569 | JMP KSTUB ; FFB4: 570 | JMP KIOSTUB ; FFB7: read I/O status word 571 | JMP KIOSTUB ; FFBA: set logical, first and second address 572 | JMP KIOSTUB ; FFBD: set file name 573 | JMP KIOSTUB ; FFC0: open loical file 574 | JMP KIOSTUB ; FFC3: close logical file 575 | JMP KIOSTUB ; FFC6: open channel for input 576 | JMP KIOSTUB ; FFC9: open channel for output 577 | JMP KIOSTUB ; FFCC: close channels 578 | JMP KCHRIN ; FFCF: get input character 579 | JMP KCHROUT ; FFD2: print output character 580 | JMP KIOSTUB ; FFD5: load data from device 581 | JMP KIOSTUB ; FFD8: save data to device 582 | JMP KSTUB ; FFDB: set the real time clock 583 | JMP KSTUB ; FFDB: get the real time clock 584 | JMP KSTOP ; FFE1: check stop key 585 | JMP KGETIN ; FFE4: get character from keyboard 586 | JMP KIOSTUB ; FFE7: close all channels 587 | JMP KSTUB ; FFEA: 588 | JMP KSTUB ; FFED: 589 | JMP KSTUB ; FFF0: 590 | JMP KSTUB ; FFF3: 591 | 592 | ;;; ---------------------------------------------------------------------------- 593 | ;;; ------------------------- 6502 hardware vectors ------------------------- 594 | ;;; ---------------------------------------------------------------------------- 595 | 596 | .org $FFFA 597 | .word NMI ; hardware NMI vector 598 | .word RESET ; hardware RESET vector 599 | .word IRQ ; hardware IRQ/BRK vector 600 | -------------------------------------------------------------------------------- /smon.asm: -------------------------------------------------------------------------------- 1 | ;;; The SMON machine language monitor was originally published 2 | ;;; in the November/December/January 1984/85 issues of German magazine "64er": 3 | ;;; https://archive.org/details/64er_1984_11/page/n59/mode/2up 4 | ;;; https://archive.org/details/64er_1984_12/page/n59/mode/2up 5 | ;;; https://archive.org/details/64er_1985_01/page/n68/mode/2up 6 | ;;; SMON was written for the Commodore 64 by Norfried Mann and Dietrich Weineck 7 | ;;; 8 | ;;; For an English description of SMON capabilities see: 9 | ;;; https://www.c64-wiki.com/wiki/SMON 10 | ;;; The following original SMON commands are NOT included in this version: 11 | ;;; B (BASIC data), L (disk load), S (disk save), P (printer), I (set I/O device) 12 | ;;; The following commands were added in this version: 13 | ;;; H - print help screen 14 | ;;; L - load Intel HEX data through terminal 15 | ;;; MS - check and print memory (RAM) size 16 | ;;; MT xxxx yyyy nn - test memory (RAM) xxxx-yyyy nn times (default 1) 17 | ;;; 18 | ;;; This code is an adaptation of SMON to a minimal 6502 system by David Hansel (2023). 19 | ;;; Minimum system requirements: 20 | ;;; - MOS 6502 CPU 21 | ;;; - MOS 6522 VIA (necessary only if "trace" functions are used) 22 | ;;; The VIA interrupt output must be attached to the 6502 IRQ input 23 | ;;; - 8K of ROM at address E000-F000 (for SMON) 24 | ;;; - 4K of RAM at address 0000-1000 25 | ;;; - UART for communication. As presented here, a MC6850 UART 26 | ;;; at address $8200 is expected. However, this can easily 27 | ;;; be adapted by modifying the code in file "uart.asm" 28 | ;;; 29 | ;;; This code is based on the SMON disassembly found at: 30 | ;;; https://github.com/cbmuser/smon-reassembly 31 | 32 | .include "config.asm" 33 | 34 | PCHSAVE = $02A8 ; PC hi 35 | PCLSAVE = $02A9 ; PC lo 36 | SRSAVE = $02AA ; SR 37 | AKSAVE = $02AB ; A 38 | XRSAVE = $02AC ; XR 39 | YSAVE = $02AD ; YR 40 | SPSAVE = $02AE ; SP 41 | IRQ_LO = $0314 ; Vector: Hardware IRQ Interrupt Address Lo 42 | IRQ_HI = $0315 ; Vector: Hardware IRQ Interrupt Address Hi 43 | BRK_LO = $0316 ; Vector: BRK Lo 44 | BRK_HI = $0317 ; Vector: BRK Hi 45 | CHRIN = $FFCF ; Kernal input routine 46 | CHROUT = $FFD2 ; Kernal output routine 47 | STOP = $FFE1 ; Kernal test STOP routine 48 | GETIN = $FFE4 ; Kernal get input routine 49 | 50 | .org $8000 51 | .org $e000 52 | 53 | ENTRY: lda #SMON 56 | sta BRK_HI 57 | brk 58 | 59 | ;; help message 60 | HLPMSG: .byte "A xxxx - Assemble starting at x (end assembly with 'f', use Mxx for label)",0 61 | .byte "C xxxx yyyy zzzz aaaa bbbb - Convert (execute V followed by W)",0 62 | .byte "D xxxx (yyyy) - Disassemble from x (to y)",0 63 | .byte "F aa bb cc ..., xxxxx yyyyy - Find byte sequence a b c in x-y",0 64 | .byte "FAaaaa, xxxx yyyy - Find absolute address used in opcode",0 65 | .byte "FRaaaa, xxxx yyyy - Find relative address used in opcode",0 66 | .byte "FTxxxx yyyy - Find table (non-opcode bytes) in x-y",0 67 | .byte "FZaa, xxxx yyyy - Find zero-page address used in opcode",0 68 | .byte "FIaa, xxxx yyyy - Find immediate argument used in opcode",0 69 | .byte "G (xxxx) - Run from x (or current PC)",0 70 | .byte "K xxxx (yyyy) - Dump memory from x (to y) as ASCII",0 71 | .byte "L - Load Intel HEX data from terminal",0 72 | .byte "M xxxx (yyyy) - Dump memory from x (to y) as HEX",0 73 | .byte "MS - Check and print memory size",0 74 | .byte "MT xxxx yyyy (nn) - Test memory x-y (repeat n times)",0 75 | .byte "O xxxx yyyy aa - Fill memory x-y with a",0 76 | .if VIA > 0 77 | .byte "TW xxxx - Trace walk (single step)",0 78 | .byte "TB xxxx nn - Trace break (set break point at x, stop when hit n times)",0 79 | .byte "TQ xxxx - Trace quick (run to break point)",0 80 | .byte "TS xxxx - Trace stop (run to x)",0 81 | .endif 82 | .byte "V xxxx yyyy zzzz aaaa bbbb - Within a-b, convert addresses referencing x-y to z",0 83 | .byte "W xxxx yyyy zzzz - Copy memory x-y to z",0 84 | .byte "= xxxx yyyy - compare memory starting at x to memory starting at y",0 85 | .byte "#ddd - convert DEC to HEX and BIN",0 86 | .byte "$xx - convert HEX to DEC and BIN",0 87 | .byte "%bbbbbbbb - convert BIN to DEC and HEX",0 88 | .byte 0 89 | 90 | ;; commands 91 | ICMD: .byte "'#$%,:;=?ACDFGHKLMORTVW" 92 | ICMDE: .byte $00,$00,$00,$00,$00 93 | 94 | ;; command entry point addresses 95 | IOFS: .byte <(TICK-1),>(TICK-1) ; ' 96 | .byte <(BEFDEC-1),>(BEFDEC-1) ; # 97 | .byte <(BEFHEX-1),>(BEFHEX-1) ; $ 98 | .byte <(BEFBIN-1),>(BEFBIN-1) ; % 99 | .byte <(COMMA-1),>(COMMA-1) ; , 100 | .byte <(COLON-1),>(COLON-1) ; : 101 | .byte <(SEMI-1),>(SEMI-1) ; ; 102 | .byte <(EQUALS-1),>(EQUALS-1) ; = 103 | .byte <(ADDSUB-1),>(ADDSUB-1) ; ? 104 | .byte <(ASSEMBLER-1),>(ASSEMBLER-1) ; A 105 | .byte <(CONVERT-1),>(CONVERT-1) ; C 106 | .byte <(DISASS-1),>(DISASS-1) ; D 107 | .byte <(FIND-1),>(FIND-1) ; F 108 | .byte <(GO-1),>(GO-1) ; G 109 | .byte <(HELP-1),>(HELP-1) ; H 110 | .byte <(KONTROLLE-1),>(KONTROLLE-1) ; K 111 | .byte <(LOAD-1),>(LOAD-1) ; L 112 | .byte <(MEMDUMP-1),>(MEMDUMP-1) ; M 113 | .byte <(OCCUPY-1),>(OCCUPY-1) ; O 114 | .byte <(REGISTER-1),>(REGISTER-1) ; R 115 | .byte <(TRACE-1),>(TRACE-1) ; T 116 | .byte <(MOVE-1),>(MOVE-1) ; V 117 | .byte <(WRITE-1),>(WRITE-1) ; W 118 | 119 | ;; output line start characters 120 | LC061: .byte "':;,()!" 121 | .byte $00,$00,$00 122 | 123 | LC06B: .byte $FF,$FF,$01,$00 124 | 125 | ;; sub-commands for "find" (F) 126 | FSCMD: .byte "AZIRT" 127 | ;; "find" sub-command 128 | LC074: .byte $80,$20,$40,$10,$00 129 | ;; "find" sub-command data length (2=word,1=byte,0=none) 130 | LC079: .byte $02,$01,$01,$02,$00 131 | 132 | REGHDR: .byte $0D,$0D," PC SR AC XR YR SP NV-BDIZC",$00 133 | LC0AD: .byte $02,$04,$01 134 | LC0B0: .byte $2C,$00,$2C 135 | LC0B3: .byte $59,$29,$58 136 | LC0B6: .byte $9D,$1F,$FF,$1C,$1C,$1F,$1F 137 | .byte $1F,$1C,$DF,$1C,$1F,$DF,$FF,$FF 138 | .byte $03,$1F 139 | LC0C7: .byte $80,$09,$20,$0C,$04,$10,$01 140 | .byte $11,$14,$96,$1C,$19,$94,$BE,$6C 141 | .byte $03,$13,$01 142 | LC0D9: .byte $02,$02,$03,$03,$02,$02,$02 143 | .byte $02,$02,$02,$03,$03,$02,$03,$03 144 | .byte $03,$02,$00 145 | LC0EB: .byte $40,$40,$80,$80,$20,$10,$25 146 | .byte $26,$21,$22,$81,$82,$21,$82,$84 147 | .byte $08,$08 148 | LC0FC: .byte $E7,$E7,$E7,$E7,$E3,$E3,$E3 149 | .byte $E3,$E3,$E3,$E3,$E3,$E3,$E3,$E7 150 | .byte $A7,$E7,$E7,$F3,$F3,$F7,$DF 151 | 152 | ;; opcodes (in same order as mnemonics below) 153 | OPC: .byte $26,$46,$06,$66,$41,$81,$E1 154 | .byte $01,$A0,$A2,$A1,$C1,$21,$61,$84 155 | .byte $86,$E6,$C6,$E0,$C0,$24,$4C,$20 156 | .byte $90,$B0,$F0,$30,$D0,$10,$50,$70 157 | .byte $78,$00,$18,$D8,$58,$B8,$CA,$88 158 | .byte $E8,$C8,$EA,$48 159 | 160 | LC13D: .byte $08,$68,$28,$40,$60,$AA,$A8 161 | .byte $BA,$8A,$9A,$98,$38,$F8 162 | LC14A: .byte $89,$9C,$9E,$B2 163 | LC14E: .byte $2A,$4A,$0A,$6A,$4F,$23,$93 164 | .byte $B3,$F3,$33,$D3,$13,$53,$73 165 | 166 | ;; first, second and third characters of opcode mnemonics 167 | OPMN1: .byte "RLARESSOLLLCAASSIDCCBJJBBBBBBBBSBCCCCDDIINPPPPRRTTTTTTSS" 168 | OPMN2: .byte "OSSOOTBRDDDMNDTTNEPPIMSCCEMNPVVERLLLLEENNOHHLLTTAASXXYEE" 169 | OPMN3: .byte "LRLRRACAYXAPDCYXCCXYTPRCSQIELCSIKCDIVXYXYPAPAPISXYXASACD" 170 | 171 | LC204: .byte $08,$84,$81,$22,$21,$26,$20,$80 172 | LC20C: .byte $03,$20,$1C,$14,$14,$10,$04,$0C 173 | 174 | ; SMON START 175 | SMON: cld 176 | ldx #$05 177 | LC22E: pla 178 | sta PCHSAVE,x ; save stack 179 | dex 180 | bpl LC22E 181 | lda PCLSAVE 182 | bne LC23D 183 | dec PCHSAVE ; PC high 184 | LC23D: dec PCLSAVE ; PC low 185 | tsx 186 | stx SPSAVE 187 | lda #'R' ; execute 'R' command 188 | jmp LC2FF ; jump to main loop 189 | 190 | LC249: jsr PEEKCH 191 | beq LC259 192 | LC24E: jsr GETWRD 193 | sta PCLSAVE 194 | lda $FC 195 | sta PCHSAVE 196 | LC259: rts 197 | 198 | ;; get 3 words into $A4-$A9 199 | LC25A: ldx #$A4 200 | jsr GETWRDX 201 | jsr GETWRDX 202 | bne GETWRDX 203 | 204 | ;; get start (FB/FC) and end (FD/FE) address from command line 205 | ;; end address is optional, defaults to $FFFE 206 | GETSE: jsr GETWRD ; get word from command line 207 | lda #$FE 208 | sta $FD 209 | lda #$FF 210 | sta $FE 211 | jsr PEEKCH ; is there more command line input? 212 | bne GETWRDX ; yes, get another word 213 | sta $0277 ; put NUL into keyboard buffer 214 | inc $C6 215 | rts 216 | 217 | ;; get two words from command line, store in $FB/$FC and $FD/$FE 218 | GETDW: jsr GETWRD 219 | .byte $2C ; skip next (2-byte) opcode 220 | 221 | ;; get word from command line, store in $FB/$FC 222 | GETWRD: ldx #$FB 223 | 224 | ;; get word from command line, store in (X)/(X+1) 225 | GETWRDX:jsr LC28D 226 | sta $01,x 227 | jsr GETBYT 228 | sta $00,x 229 | inx 230 | inx 231 | rts 232 | 233 | ;; get byte from command line, ignore leading " " and "," 234 | LC28D: jsr GETCHR 235 | cmp #$20 236 | beq LC28D 237 | cmp #$2C 238 | beq LC28D 239 | bne LC29D 240 | 241 | ;; get byte from command line, return in A 242 | GETBYT: jsr GETCHR ; get character 243 | LC29D: jsr LC2AF ; convert to 0-15 244 | asl 245 | asl 246 | asl 247 | asl 248 | sta $B4 249 | jsr GETCHR ; get character 250 | jsr LC2AF ; convert to 0-15 251 | ora $B4 252 | rts 253 | 254 | ;; convert character in A from ASCII HEX to 0-15 255 | LC2AF: cmp #$3A 256 | bcc LC2B5 257 | adc #$08 258 | LC2B5: and #$0F 259 | rts 260 | 261 | ;; skip spaces from command line 262 | LC2B8: jsr GETCHR 263 | cmp #$20 264 | beq LC2B8 265 | dec $D3 266 | rts 267 | 268 | ;; peek whether next character on command line is CR (Z set if so) 269 | PEEKCH: jsr CHRIN 270 | dec $D3 271 | cmp #$0D 272 | LC2C9: rts 273 | 274 | ;; convert character in A to uppercase 275 | UCASE: cmp #'a' 276 | bcc UCASE1 277 | cmp #'z'+1 278 | bcs UCASE1 279 | and #$DF 280 | UCASE1: rts 281 | 282 | ;; get next character from command line, error if CR (end of line) 283 | GETCHR: jsr CHRIN 284 | jsr UCASE 285 | GETCL1: cmp #$0D 286 | bne LC2C9 287 | 288 | ; invalid input 289 | ERROR: lda #$3F ; print "?" 290 | jsr CHROUT 291 | 292 | ;; main loop 293 | LC2D6: ldx SPSAVE 294 | txs 295 | ldx #$00 ; clear keyboard buffer 296 | stx $C6 297 | lda $D3 ; get cursor column 298 | beq SKIPCR ; jump if zero 299 | jsr LC351 ; print CR 300 | SKIPCR: lda ($D1,x) ; get first character of next line 301 | ldx #$06 ; compare to known line start characters: ':;,() 302 | LC2E5: cmp LC061,x 303 | beq LC2F2 ; skip prompt if found 304 | dex 305 | bpl LC2E5 306 | lda #$2E ; print prompt (".") 307 | jsr CHROUT 308 | LC2F2: jsr GETCHR ; await next input 309 | cmp #$2E 310 | beq LC2F2 ; ignore leading "." 311 | jmp LC2FF 312 | LC2FC: jmp ERROR 313 | 314 | ;; find user command in A 315 | LC2FF: sta $AC 316 | and #$7F 317 | ldx #ICMDE-ICMD 318 | FNDCMD: cmp ICMD-1,x ; compare command char 319 | beq LC30F ; found valid command 320 | dex ; next command char 321 | bne FNDCMD ; loop until we checked all command chars 322 | beq LC2FC ; no match => error 323 | LC30F: jsr LC315 ; execute command 324 | jmp LC2D6 ; back to main loop 325 | 326 | ;; execute command specified by index in X 327 | LC315: txa ; X = X*2+1 328 | asl 329 | tax 330 | inx 331 | lda IOFS-2,x ; low address 332 | pha ; on stack 333 | dex 334 | lda IOFS-2,x ; high address 335 | pha ; on stack 336 | rts ; execute command 337 | 338 | ;; output data word in FB/FC 339 | LC323: lda $FC 340 | jsr LC32A 341 | lda $FB 342 | 343 | ;; output data byte in A as HEX 344 | LC32A: pha 345 | lsr 346 | lsr 347 | lsr 348 | lsr 349 | jsr LC335 350 | pla 351 | and #$0F 352 | LC335: cmp #$0A 353 | bcc LC33B 354 | adc #$06 355 | LC33B: adc #$30 356 | jmp CHROUT 357 | 358 | ;; output CR, followed by character in X 359 | LC340: lda #$0D 360 | LC342: jsr CHROUT 361 | txa 362 | jmp CHROUT 363 | 364 | ;; output two SPACE 365 | LC349: jsr LC34C 366 | 367 | ;; output SPACE 368 | LC34C: lda #$20 369 | jmp CHROUT 370 | 371 | ;; output CR 372 | LC351: lda #$0D 373 | jmp CHROUT 374 | 375 | ;; print 0-terminated string pointed to by A/Y 376 | STROUT: sta $BB 377 | sty $BC 378 | ldy #$00 379 | STROUT1:lda ($BB),y 380 | beq LC366 381 | jsr CHROUT 382 | inc $BB 383 | bne STROUT1 384 | inc $BC 385 | bne STROUT1 386 | LC366: rts 387 | 388 | ;; increment address in $FB/$FC 389 | LC367: inc $FB 390 | bne LC36D 391 | inc $FC 392 | LC36D: rts 393 | 394 | ;; HELP (H) 395 | HELP: lda #HLPMSG 398 | sta $BC 399 | ldy #$00 400 | HLPL1: lda #$0d ; output CR 401 | jsr CHROUT 402 | jsr STROUT1 ; output string until 0 403 | iny ; next byte 404 | cpy #20 ; are we at line 20? 405 | bne HLPL2 ; jump if not 406 | lda #' ' ; put SPACE in keyboard buffer 407 | sta $0277 ; (to pause output) 408 | inc $C6 409 | HLPL2: jsr LC472 ; check for PAUSE,STOP 410 | lda ($BB),y ; get first byte of next string 411 | bne HLPL1 ; loop if not 0 412 | rts 413 | 414 | ;; REGISTER (R) 415 | REGISTER: 416 | ldy #>REGHDR 417 | lda # error 500 | 501 | ;; read Intel HEX end-of-file record 502 | jsr LDBYT ; get next byte (should be checksum) 503 | cmp #$FF ; checksum of EOF record is FF 504 | bne LDECS ; error if not 505 | LDEOF: rts 506 | 507 | ;; read Intel HEX data record 508 | LDDR: clc ; prepare checksum 509 | txa ; byte count 510 | adc $FB ; address low 511 | clc 512 | adc $FC ; address high 513 | sta $FD ; store checksum 514 | ldy #0 ; offset 515 | inx 516 | LDDR1: dex ; decrement number of bytes 517 | beq LDDR2 ; done if 0 518 | jsr LDBYT ; get next data byte 519 | sta ($FB),y ; store data byte 520 | cmp ($FB),y ; check data byte 521 | bne LDEM ; memory error if no match 522 | clc 523 | adc $FD ; add to checksum 524 | sta $FD ; store checksum 525 | iny 526 | bne LDDR1 527 | LDDR2: jsr LDBYT ; get checksum byte 528 | clc 529 | adc $FD ; add to computed checkum 530 | bne LDECS ; if sum is 0 then checksum is ok 531 | lda #'+' 532 | jsr UAPUTW 533 | inc $D3 534 | cpy #0 ; did we have 0 bytes in this record? 535 | bne LDNXT ; if not then expect another record 536 | beq LDEOF ; end of file 537 | 538 | 539 | LDBRK: lda #'B' ; received BREAK (ESC) 540 | .byte $2C 541 | LDERI: lda #'R' ; unknown record identifier error 542 | .byte $2C 543 | LDECS: lda #'C' ; checksum error 544 | .byte $2C 545 | LDEIC: lda #'I' ; input character error 546 | .byte $2C 547 | LDEM: lda #'M' ; memory error 548 | jsr CHROUT 549 | LDERR: jmp ERROR 550 | 551 | ;; get HEX byte from UART 552 | LDBYT: jsr LDNIB ; get high nibble 553 | asl 554 | asl 555 | asl 556 | asl 557 | sta $B4 558 | jsr LDNIB ; get low libble 559 | ora $B4 ; combine 560 | rts 561 | ;; get HEX character from UART, convert to 0-15 562 | LDNIB: jsr UAGETW ; get character from UART 563 | jsr UCASE ; convert to uppercase 564 | cmp #'0' 565 | bcc LDEIC 566 | cmp #'F'+1 567 | bcs LDEIC 568 | cmp #'9'+1 569 | bcc LDBYT2 570 | cmp #'A' 571 | bcc LDEIC 572 | adc #$08 573 | LDBYT2: and #$0F 574 | rts 575 | 576 | ;; MEMDUMP (M) 577 | MEMDUMP:jsr GETCHR 578 | beq MDERR ; error if CR 579 | cmp #'T' ; is it 'T' 580 | bne MD1 ; go to memory dump 581 | jmp MEMTST 582 | MD1: cmp #'S' 583 | bne MD2 584 | jmp MEMSIZ 585 | MD2: cmp #' ' 586 | bne MDERR 587 | MD3: jsr GETSE ; get start (FB/FC) and end address (FD/FE) 588 | LC3FC: ldx #$3A ; ':' 589 | jsr LC340 ; print NEWLINE followed by ':' 590 | jsr LC323 ; print address in FB/FC 591 | ldy #80-17 592 | ldx #0 593 | LC408: jsr LC34C ; output space 594 | cpy #80-9 595 | bne LC409 596 | jsr LC34C ; output space 597 | iny 598 | LC409: lda ($FB,x) 599 | jsr LC32A ; output byte as HEX 600 | lda ($FB,x) 601 | jsr LC439 ; write ASCII char of byte directly to screen 602 | bne LC408 ; repeat until end-of-line 603 | jsr PREOL ; print to end of line 604 | jsr LC45D ; check for PAUSE/STOP or end condition 605 | bcc LC3FC ; repeat until end 606 | rts 607 | 608 | ;; Colon (: - edit memory dump) 609 | COLON: jsr GETWRD ; get start addressz 610 | ldy #80-17 611 | ldx #$00 612 | LC424: cpy #80-9 613 | bne LC434 614 | iny 615 | LC434: jsr CHRIN ; get next character 616 | cmp #$20 ; was it space? 617 | beq LC424 ; skip space 618 | cmp #$0d ; was it CR? 619 | beq COLOD ; done if so 620 | dec $D3 ; go back one input char 621 | jsr GETBYT ; get hex byte 622 | sta ($FB,x) ; store byte 623 | cmp ($FB,x) ; compare (make sure it's not ROM) 624 | beq LC433 ; if match then skip 625 | MDERR: jmp ERROR ; print error 626 | LC433: jsr LC439 ; write ASCII to screen 627 | bne LC424 ; repeat until end 628 | lda #80-17 629 | jsr PRLINE 630 | COLOD: rts 631 | 632 | ;; put character into screen buffer at column Y 633 | ;; (make sure it is printable first) 634 | LC439: cmp #$20 ; character code < 32 (space) 635 | bcc LC449 ; if so, print "." 636 | cmp #$7F ; character code >= 127 637 | bcs LC449 ; if so, print "." 638 | bcc LC44F ; print character 639 | LC449: lda #$2E 640 | LC44F: sta ($D1),y 641 | lda $0286 642 | sta ($F3),y 643 | LC456: jsr LC367 644 | iny 645 | cpy #80 646 | rts 647 | 648 | ;; check stop/pause condition, return with carry set 649 | ;; if end address reached 650 | LC45D: jsr LC472 ; end-of-line wait handling 651 | jmp LC466 ; check for end address and return 652 | 653 | ;; increment address in $FB/$FC and check whether end address 654 | ;; ($FD/$FE) has been reached, if not, C is clear on return 655 | LC463: jsr LC367 ; increment address in $FB/$FC 656 | 657 | ;; check whether end address has been reached, C is clear if not 658 | LC466: lda $FB 659 | cmp $FD 660 | lda $FC 661 | sbc $FE 662 | rts 663 | 664 | ;; end-of-line wait handling: 665 | ;; - stop if STOP key pressed 666 | ;; - wait if any key pressed 667 | ;; - if SPACE pressed, immediately stop again after next line 668 | LC472: jsr LC486 ; check for STOP or keypress 669 | beq LC485 ; no key => done 670 | LC477: jsr LC486 ; check for STOP or keypress 671 | beq LC477 ; no key => wait 672 | cmp #$20 ; is SPACE? 673 | bne LC485 ; no => done 674 | sta $0277 ; put SPACE in keyboard buffer 675 | inc $C6 ; (i.e. advance just one line) 676 | LC485: rts 677 | 678 | ;; check for STOP or other keypress 679 | LC486: jsr GETIN ; get input character 680 | pha ; save char 681 | jsr STOP ; check stop key 682 | beq LC491 ; jump if pressed 683 | pla ; restore char to A 684 | LC490: rts 685 | LC491: jmp LC2D6 ; back to main loop (resets stack) 686 | 687 | ;; 688 | LC4CB: ldy #$00 689 | lda ($FB),y ; get opcode at $FB/FC 690 | bit $AA 691 | bmi LC4D5 692 | bvc LC4E1 693 | LC4D5: ldx #$1F 694 | LC4D7: cmp LC13D-1,x 695 | beq LC50B 696 | dex 697 | cpx #$15 698 | bne LC4D7 699 | LC4E1: ldx #$04 700 | LC4E3: cmp LC14A-1,x 701 | beq LC509 702 | cmp LC14E-1,x 703 | beq LC50B 704 | dex 705 | bne LC4E3 706 | ldx #$38 707 | LC4F2: cmp OPC-1,x 708 | beq LC50B 709 | dex 710 | cpx #$16 711 | bne LC4F2 712 | LC4FC: lda ($FB),y 713 | and LC0FC-1,x 714 | eor OPC-1,x 715 | beq LC50B 716 | dex 717 | bne LC4FC 718 | LC509: ldx #$00 719 | LC50B: stx $AD 720 | txa 721 | beq LC51F 722 | ldx #$11 723 | LC512: lda ($FB),y 724 | and LC0B6-1,x 725 | eor LC0C7-1,x 726 | beq LC51F 727 | dex 728 | bne LC512 729 | LC51F: lda LC0EB-1,x 730 | sta $AB 731 | lda LC0D9-1,x 732 | sta $B6 733 | ldx $AD 734 | rts 735 | 736 | LC52C: ldy #$01 737 | lda ($FB),y 738 | tax 739 | iny 740 | lda ($FB),y 741 | ldy #$10 742 | cpy $AB 743 | bne LC541 744 | jsr LC54A 745 | ldy #$03 746 | bne LC543 747 | LC541: ldy $B6 748 | LC543: stx $AE 749 | nop 750 | sta $AF 751 | nop 752 | rts 753 | 754 | LC54A: ldy #$01 755 | lda ($FB),y 756 | bpl LC551 757 | dey 758 | LC551: sec 759 | adc $FB 760 | tax 761 | inx 762 | beq LC559 763 | dey 764 | LC559: tya 765 | adc $FC 766 | LC55C: rts 767 | 768 | 769 | ; DISASS (D) 770 | DISASS: ldx #$00 771 | stx $AA 772 | jsr GETSE ; get start (FB/FC) and end address (FD/FE) 773 | LC564: jsr LC58C 774 | lda $AD 775 | cmp #$16 776 | beq LC576 777 | cmp #$30 778 | beq LC576 779 | cmp #$21 780 | bne LC586 781 | nop 782 | LC576: jsr LC351 783 | ldx #$23 784 | lda #$2D 785 | LC580: jsr CHROUT 786 | dex 787 | bne LC580 788 | LC586: jsr LC45D 789 | bcc LC564 790 | rts 791 | 792 | LC58C: ldx #$2C ; output NEWLINE followed by "," 793 | jsr LC340 794 | jsr LC323 ; output FB/FC (address) 795 | jsr LC34C ; output SPACE 796 | LC597: jsr LC675 ; erase to end of line 797 | jsr LC4CB 798 | jsr LC34C ; output SPACE 799 | LC5A0: lda ($FB),y ; get data byte 800 | jsr LC32A ; output byte in A 801 | jsr LC34C ; output SPACE 802 | iny 803 | cpy $B6 804 | bne LC5A0 805 | lda #$03 806 | sec 807 | sbc $B6 808 | tax 809 | beq LC5BE 810 | LC5B5: jsr LC349 811 | jsr LC34C 812 | dex 813 | bne LC5B5 814 | LC5BE: lda #$20 815 | jsr CHROUT 816 | ldy #$00 817 | ldx $AD 818 | LC5C7: bne LC5DA 819 | ldx #$03 820 | LC5CB: lda #$2A 821 | jsr CHROUT 822 | dex 823 | bne LC5CB 824 | bit $AA 825 | bmi LC55C 826 | jmp LC66A 827 | LC5DA: bit $AA 828 | bvc LC607 829 | lda #$08 830 | bit $AB 831 | beq LC607 832 | lda ($FB),y 833 | and #$FC 834 | sta $AD 835 | iny 836 | lda ($FB),y 837 | asl 838 | tay 839 | lda $033C,y 840 | sta $AE 841 | nop 842 | iny 843 | lda $033C,y 844 | sta $AF 845 | nop 846 | jsr LC6BE 847 | ldy $B6 848 | jsr LC693 849 | jsr LC4CB 850 | LC607: lda OPMN1-1,x 851 | jsr CHROUT 852 | lda OPMN2-1,x 853 | jsr CHROUT 854 | lda OPMN3-1,x 855 | jsr CHROUT 856 | lda #$20 857 | bit $AB 858 | beq LC622 859 | jsr LC349 860 | LC622: ldx #$20 861 | lda #$04 862 | bit $AB 863 | beq LC62C 864 | ldx #$28 865 | LC62C: txa 866 | jsr CHROUT 867 | bit $AB 868 | bvc LC639 869 | lda #$23 870 | jsr CHROUT 871 | LC639: jsr LC52C 872 | dey 873 | beq LC655 874 | lda #$08 875 | bit $AB 876 | beq LC64C 877 | lda #$4D 878 | jsr CHROUT 879 | ldy #$01 880 | LC64C: lda $AD,y 881 | jsr LC32A 882 | dey 883 | bne LC64C 884 | LC655: ldy #$03 885 | LC657: lda LC0AD-1,y 886 | bit $AB 887 | beq LC667 888 | lda LC0B0-1,y 889 | ldx LC0B3-1,y 890 | jsr LC342 891 | LC667: dey 892 | bne LC657 893 | LC66A: lda $B6 894 | LC66C: jsr LC367 895 | sec 896 | sbc #$01 897 | bne LC66C 898 | rts 899 | 900 | ;; erase screen buffer to end of line 901 | LC675: ldy $D3 902 | lda #' ' 903 | LC679: sta ($D1),y 904 | iny 905 | cpy #40 906 | bcc LC679 907 | rts 908 | 909 | LC681: cpx $AB 910 | bne LC689 911 | ora $AD 912 | sta $AD 913 | LC689: rts 914 | 915 | ;; copy $AD through $AD+y to ($FB) 916 | LC68A: lda $AD,y 917 | sta ($FB),y 918 | cmp ($FB),y 919 | bne LC697 920 | LC693: dey 921 | bpl LC68A 922 | rts 923 | 924 | LC697: pla 925 | pla 926 | rts 927 | 928 | LC69A: bne LC6B8 929 | txa 930 | ora $AB 931 | sta $AB 932 | 933 | ;; get first character that is not " $(," (max 4) 934 | LC6A1: lda #$04 935 | sta $B5 936 | LC6A5: jsr CHRIN ; get character 937 | cmp #$20 ; is it space? 938 | beq LC6B9 ; 939 | cmp #$24 ; is it "$"? 940 | beq LC6B9 941 | cmp #$28 ; is it "("? 942 | beq LC6B9 943 | cmp #$2C ; is it ","? 944 | beq LC6B9 945 | jsr UCASE ; convert to uppercase 946 | LC6B8: rts 947 | ;; character was either " ", "$", "(" or "," 948 | LC6B9: dec $B5 949 | bne LC6A5 ; get next character 950 | rts 951 | 952 | LC6BE: cpx #$18 953 | bmi LC6D0 954 | lda $AE 955 | nop 956 | sec 957 | sbc #$02 958 | sec 959 | sbc $FB 960 | sta $AE 961 | nop 962 | ldy #$40 963 | LC6D0: rts 964 | 965 | ; Assembler (A) 966 | ASSEMBLER: 967 | jsr GETWRD ; get start address 968 | sta $FD 969 | lda $FC 970 | sta $FE 971 | LC6DA: jsr LC351 ; print CR 972 | LC6DD: jsr LC6E4 ; get and assemble line 973 | bmi LC6DD 974 | bpl LC6DA 975 | 976 | LC6E4: lda #$00 977 | sta $D3 978 | jsr LC34C ; output ' ' 979 | jsr LC323 ; output address 980 | jsr LC34C ; output ' ' 981 | jsr CHRIN ; get character 982 | lda #$01 ; set input start column within line 983 | sta $D3 984 | ldx #$80 985 | bne LC701 986 | ;; entry point from "," command (assemble single line) 987 | COMMA: ldx #$80 ; set "comma" flag 988 | stx $02B1 989 | LC701: stx $AA 990 | jsr GETWRD ; get word (address) from command line 991 | lda #$25 ; set last input char (37) 992 | sta LASTCOL 993 | bit $02B1 ; skip the following if "comma" flag NOT set 994 | bpl LC717 995 | ldx #$0A ; skip 10 characters (for "," command) 996 | LC711: jsr CHRIN 997 | dex 998 | bne LC711 999 | LC717: lda #$00 1000 | sta $02B1 1001 | jsr LC6A1 ; get a character (skip " $(,") 1002 | cmp #$46 ; is it "f"? 1003 | bne LC739 ; jump if not 1004 | ;; disassemble the whole input and exit 1005 | lsr $AA 1006 | pla 1007 | pla 1008 | ldx #$02 1009 | LC729: lda $FA,x ; swap $FB/$FC and $FD/$FE 1010 | pha 1011 | lda $FC,x 1012 | sta $FA,x 1013 | pla 1014 | sta $FC,x 1015 | dex 1016 | bne LC729 1017 | jmp LC564 ; disassemble 1018 | LC739: cmp #$2E ; was character "."? 1019 | bne LC74E ; jump if not 1020 | jsr GETBYT 1021 | ldy #$00 1022 | sta ($FB),y ; store opcode 1023 | cmp ($FB),y ; compare (in case of ROM) 1024 | bne LC74C ; if different then error 1025 | jsr LC367 ; increment FB/FC pointer 1026 | iny 1027 | LC74C: dey 1028 | rts 1029 | 1030 | LC74E: ldx #$FD 1031 | cmp #$4D ; was character "M"? 1032 | bne LC76D ; jump if not 1033 | jsr GETBYT 1034 | ldy #$00 1035 | cmp #$3F 1036 | bcs LC74C 1037 | asl 1038 | tay 1039 | lda $FB 1040 | sta $033C,y 1041 | lda $FC 1042 | iny 1043 | sta $033C,y 1044 | ;; read 3 opcode characters and store in $a6-$a8 1045 | LC76A: jsr LC6A1 ; get a character 1046 | LC76D: sta $A9,x ; store character 1047 | cpx #$FD 1048 | bne LC777 1049 | lda #$07 1050 | sta $B7 1051 | LC777: inx 1052 | bne LC76A ; get more characters (total 3) 1053 | ldx #$38 1054 | ;; find mnemonic in table 1055 | LC77C: lda $A6 ; get first opcode char 1056 | cmp OPMN1-1,x ; find it in table 1057 | beq LC788 ; jump if found 1058 | LC783: dex 1059 | bne LC77C 1060 | dex 1061 | rts ; not found => error exit 1062 | LC788: lda $A7 ; get second opcode char 1063 | cmp OPMN2-1,x ; compare with expected 1064 | bne LC783 ; repeat if no match 1065 | lda $A8 ; get third opcode char 1066 | cmp OPMN3-1,x ; compare with expected 1067 | bne LC783 ; repeat if no match 1068 | ;; found mnemonic 1069 | lda OPC-1,x ; get opcode 1070 | sta $AD ; store opcode 1071 | jsr LC6A1 ; get another character 1072 | ldy #$00 1073 | cpx #$20 1074 | bpl LC7AD 1075 | cmp #$20 1076 | bne LC7B0 1077 | lda LC14E-1,x 1078 | sta $AD 1079 | LC7AD: jmp LC831 1080 | LC7B0: ldy #$08 1081 | cmp #$4D 1082 | beq LC7D6 1083 | ldy #$40 1084 | cmp #$23 1085 | beq LC7D6 1086 | jsr LC29D 1087 | sta $AE 1088 | nop 1089 | sta $AF 1090 | nop 1091 | jsr LC6A1 1092 | ldy #$20 1093 | cmp #$30 1094 | bcc LC7E9 1095 | cmp #$47 1096 | bcs LC7E9 1097 | ldy #$80 1098 | dec $D3 1099 | LC7D6: jsr LC6A1 1100 | jsr LC29D 1101 | sta $AE 1102 | nop 1103 | jsr LC6A1 1104 | cpy #$08 1105 | beq LC7E9 1106 | jsr LC6BE 1107 | LC7E9: sty $AB 1108 | ldx #$01 1109 | cmp #$58 1110 | jsr LC69A 1111 | ldx #$04 1112 | cmp #$29 1113 | jsr LC69A 1114 | ldx #$02 1115 | cmp #$59 1116 | jsr LC69A 1117 | lda $AD 1118 | and #$0D 1119 | beq LC810 1120 | ldx #$40 1121 | lda #$08 1122 | jsr LC681 1123 | lda #$18 1124 | .byte $2C ; skip next (2-byte) opcode 1125 | LC810: lda #$1C 1126 | ldx #$82 1127 | jsr LC681 1128 | ldy #$08 1129 | lda $AD 1130 | cmp #$20 1131 | beq LC828 1132 | LC81F: ldx LC204-1,y 1133 | lda LC20C-1,y 1134 | jsr LC681 1135 | LC828: dey 1136 | bne LC81F 1137 | lda $AB 1138 | bpl LC830 1139 | iny 1140 | LC830: iny 1141 | LC831: jsr LC68A ; copy opcode plus arguments 1142 | dec $B7 1143 | lda $B7 1144 | sta $D3 1145 | jmp LC597 ; disassemble 1146 | 1147 | ; ADDSUB 1148 | ADDSUB: jsr GETWRD 1149 | jsr GETCHR 1150 | eor #$02 1151 | lsr 1152 | lsr 1153 | php 1154 | jsr GETWRDX 1155 | jsr LC351 1156 | plp 1157 | bcs LC8BA 1158 | lda $FD 1159 | adc $FB 1160 | tax 1161 | lda $FE 1162 | adc $FC 1163 | LC8B7: sec 1164 | bcs LC8C3 1165 | LC8BA: lda $FB 1166 | sbc $FD 1167 | tax 1168 | lda $FC 1169 | sbc $FE 1170 | LC8C3: tay 1171 | LC8C4: txa 1172 | 1173 | ;; output 16-bit integer in A/Y as HEX, binary and decimal 1174 | LC8C5: sty $FC 1175 | sta $FB 1176 | sty $62 1177 | sta $63 1178 | php 1179 | lda #$00 1180 | sta $D3 1181 | jsr LC675 1182 | lda $FC 1183 | bne LC8E8 1184 | jsr LC349 1185 | lda $FB 1186 | jsr LC32A 1187 | lda $FB 1188 | jsr LC3D0 1189 | beq LC8EB 1190 | LC8E8: jsr LC323 1191 | LC8EB: jsr LC34C 1192 | plp 1193 | jmp PRTINT 1194 | 1195 | ; Convert Hexadecimal 1196 | BEFHEX: jsr LC28D 1197 | tax 1198 | ldy $D3 1199 | lda ($D1),y 1200 | eor #$20 1201 | beq LC8B7 1202 | txa 1203 | tay 1204 | jsr GETBYT 1205 | LC919: sec 1206 | bcs LC8C5 1207 | 1208 | ; Convert Binary 1209 | BEFBIN: jsr LC2B8 1210 | ldy #$08 1211 | LC921: pha 1212 | jsr GETCHR 1213 | cmp #$31 1214 | pla 1215 | rol 1216 | dey 1217 | bne LC921 1218 | beq LC919 1219 | 1220 | ;; Convert Decimal 1221 | BEFDEC: jsr LC2B8 1222 | ldx #$00 1223 | txa 1224 | LC934: stx $FB 1225 | sta $FC 1226 | tay 1227 | jsr CHRIN 1228 | cmp #$3A 1229 | bcs LC8C4 1230 | sbc #$2F 1231 | bcs LC948 1232 | sec 1233 | jmp LC8C4 1234 | LC948: sta $FD 1235 | asl $FB 1236 | rol $FC 1237 | lda $FC 1238 | sta $FE 1239 | lda $FB 1240 | asl 1241 | rol $FE 1242 | asl 1243 | rol $FE 1244 | clc 1245 | adc $FB 1246 | php 1247 | clc 1248 | adc $FD 1249 | tax 1250 | lda $FE 1251 | adc $FC 1252 | plp 1253 | adc #$00 1254 | jmp LC934 1255 | 1256 | ; OCCUPY (O) 1257 | OCCUPY: jsr GETDW ; get address range 1258 | jsr LC28D ; get data byte 1259 | pha 1260 | jsr LC351 ; print CR 1261 | pla 1262 | LC9C7: ldx #$00 1263 | LC9C9: sta ($FB,x) 1264 | pha 1265 | jsr LC463 1266 | pla 1267 | bcc LC9C9 1268 | rts 1269 | 1270 | ; WRITE (W) - move memory 1271 | WRITE: jsr LC25A 1272 | jsr LC351 ; print CR 1273 | LC9D6: lda $A6 1274 | bne LC9DC 1275 | dec $A7 1276 | LC9DC: dec $A6 1277 | jsr LCA30 1278 | stx $B5 1279 | ldy #$02 1280 | bcc LC9EB 1281 | ldx #$02 1282 | ldy #$00 1283 | LC9EB: clc 1284 | lda $A6 1285 | adc $AE 1286 | sta $AA 1287 | lda $A7 1288 | adc $AF 1289 | sta $AB 1290 | LC9F8: lda ($A4,x) 1291 | sta ($A8,x) 1292 | eor ($A8,x) 1293 | ora $B5 1294 | sta $B5 1295 | lda $A4 1296 | cmp $A6 1297 | lda $A5 1298 | sbc $A7 1299 | bcs LCA29 1300 | LCA0C: clc 1301 | lda $A4,x 1302 | adc LC06B,y 1303 | sta $A4,x 1304 | lda $A5,x 1305 | adc LC06B+1,y 1306 | sta $A5,x 1307 | txa 1308 | clc 1309 | adc #$04 1310 | tax 1311 | cmp #$07 1312 | bcc LCA0C 1313 | sbc #$08 1314 | tax 1315 | bcs LC9F8 1316 | LCA29: lda $B5 1317 | beq LCA3C 1318 | jmp ERROR 1319 | LCA30: sec 1320 | ldx #$FE 1321 | LCA33: lda $AA,x 1322 | sbc $A6,x 1323 | sta $B0,x 1324 | inx 1325 | bne LCA33 1326 | LCA3C: rts 1327 | 1328 | ;; Convert (C) - do V followed by W 1329 | CONVERT:jsr LCA62 ; convert addresses 1330 | jmp LC9D6 ; move memory 1331 | 1332 | ;; Variation (V) - convert addresses referencing a memory region 1333 | MOVE: jmp LCA62 1334 | 1335 | LCA46: cmp $A7 1336 | bne LCA4C 1337 | cpx $A6 1338 | LCA4C: bcs LCA61 1339 | cmp $A5 1340 | bne LCA54 1341 | cpx $A4 1342 | LCA54: bcc LCA61 1343 | sta $B4 1344 | txa 1345 | clc 1346 | adc $AE 1347 | tax 1348 | lda $B4 1349 | adc $AF 1350 | LCA61: rts 1351 | 1352 | LCA62: jsr LC25A ; get address range and destination 1353 | jsr GETDW ; get range 1354 | jsr LC351 ; print CR 1355 | LCA68: jsr LCA30 1356 | LCA6B: jsr LC4CB 1357 | iny 1358 | lda #$10 1359 | bit $AB 1360 | beq LCA9B 1361 | ldx $FB 1362 | lda $FC 1363 | jsr LCA46 1364 | stx $AA 1365 | lda ($FB),y 1366 | sta $B5 1367 | jsr LC54A 1368 | ldy #$01 1369 | jsr LCA46 1370 | dex 1371 | txa 1372 | clc 1373 | sbc $AA 1374 | sta ($FB),y 1375 | eor $B5 1376 | bpl LCAAE 1377 | jsr LC351 1378 | jsr LC323 1379 | LCA9B: bit $AB 1380 | bpl LCAAE 1381 | lda ($FB),y 1382 | tax 1383 | iny 1384 | lda ($FB),y 1385 | jsr LCA46 1386 | sta ($FB),y 1387 | txa 1388 | dey 1389 | sta ($FB),y 1390 | LCAAE: jsr LC66A 1391 | jsr LC466 1392 | bcc LCA6B 1393 | rts 1394 | 1395 | ;; KONTROLLE (K) 1396 | KONTROLLE: 1397 | jsr GETSE 1398 | LCABA: ldx #$27 1399 | jsr LC340 1400 | jsr LC323 1401 | ldy #$08 1402 | ldx #$00 1403 | jsr LC34C 1404 | LCAC9: lda ($FB,x) ; get next byte 1405 | jsr LC439 ; write ASCII char of byte directly to screen 1406 | bne LCAC9 ; repeat until end of line 1407 | jsr PREOL ; print to end of line 1408 | ldx #$00 1409 | jsr LC45D 1410 | beq LCADA 1411 | jmp LCABA 1412 | LCADA: rts 1413 | 1414 | ;; TICK (' - read ASCII chars to memory) 1415 | TICK: jsr GETWRD ; get starting address 1416 | ldy #$03 ; skip up to 3 spaces 1417 | LCAE0: jsr CHRIN 1418 | cmp #' ' ; is it a space? 1419 | bne TSTRT ; jump if not 1420 | dey 1421 | bne LCAE0 1422 | TLOOP: jsr CHRIN ; get character 1423 | TLOOP1: cmp #$0D ; is it CR? 1424 | beq TEND ; done if so 1425 | sta ($FB),y ; store character 1426 | LCAEF: iny 1427 | cpy #72 ; do we have 72 characters yet? 1428 | bcc TLOOP ; loop if not 1429 | TEND: rts 1430 | TSTRT: ldy #0 1431 | jmp TLOOP1 1432 | 1433 | EQUALS: jsr GETDW 1434 | ldx #$00 1435 | LCAFA: lda ($FB,x) 1436 | cmp ($FD,x) 1437 | bne LCB0B 1438 | jsr LC367 1439 | inc $FD 1440 | bne LCAFA 1441 | inc $FE 1442 | bne LCAFA 1443 | LCB0B: jsr LC34C 1444 | jmp LC323 1445 | 1446 | ; FIND (F) 1447 | FIND: lda #$FF ; set start and end address to $FFFF 1448 | ldx #$04 1449 | LCB15: sta $FA,x 1450 | dex 1451 | bne LCB15 1452 | jsr GETCHR ; get next character 1453 | ldx #$05 1454 | LCB1F: cmp FSCMD-1,x ; compare with sub-command char (AZIRT) 1455 | beq LCB69 ; jump if found 1456 | dex 1457 | bne LCB1F ; repeat until all checked 1458 | 1459 | ;; no sub-command found => plain "F" (find bytes) 1460 | ;; (X=0 at this point) 1461 | LCB27: stx $A9 ; store number of bytes 1462 | jsr LCBB4 ; get search data for byte (two nibbles+bit masks) 1463 | inx ; next byte 1464 | jsr CHRIN ; get next character 1465 | cmp #' ' ; is it space? 1466 | beq LCB27 ; skip if so 1467 | cmp #$2C ; is it "," 1468 | bne LCB3B ; repeat if not 1469 | jsr GETDW ; get start and end address of range 1470 | LCB3B: jsr LC351 ; print CR 1471 | LCB3E: ldy $A9 ; get number of bytes in sequence 1472 | LCB40: lda ($FB),y ; get next byte in memory 1473 | jsr LCBD6 ; compare A with byte in expected sequence 1474 | bne LCB5F ; jump if no match 1475 | dey ; next byte 1476 | bpl LCB40 ; repeat until last byte in dequence 1477 | jsr LC323 ; found a match => print current address 1478 | jsr LC34C ; print space 1479 | ldy $D3 ; get cursor coumn 1480 | cpy #76 ; compare to 76 1481 | bcc LCB5F ; jump if less 1482 | jsr LC472 ; handle PAUSE/STOP 1483 | jsr LC351 ; print CR 1484 | LCB5F: jsr LC463 ; increment current location and check end 1485 | bcc LCB3E ; repeat if end has not been reached 1486 | ldy #$27 1487 | rts 1488 | 1489 | ;; execute "find" sub-command AZIRT with index in X 1490 | LCB69: lda LC074-1,x 1491 | sta $A8 1492 | lda LC079-1,x ; get length of data item (2=word/1=byte/0=none) 1493 | sta $A9 ; store 1494 | tax ; into x 1495 | beq LCB7C ; skip getting argument if 0 1496 | LCB76: jsr LCBB4 ; get two nibbles 1497 | dex ; do we need more (i.e. word)? 1498 | bne LCB76 ; jump if so 1499 | LCB7C: jsr GETDW ; get start and end address 1500 | LCB7F: jsr LC4CB 1501 | jsr LC52C 1502 | lda $A8 1503 | bit $AB 1504 | bne LCB94 1505 | tay 1506 | bne LCBAF 1507 | lda $AD 1508 | bne LCBAF 1509 | beq LCBA1 1510 | LCB94: ldy $A9 1511 | LCB96: lda $AD,y 1512 | jsr LCBD6 1513 | bne LCBAF 1514 | dey 1515 | bne LCB96 1516 | LCBA1: sty $AA 1517 | jsr LC58C ; disassemble one opcode at current addres 1518 | jsr LC472 ; handle PAUSE/STOP 1519 | LCBA9: jsr LC466 ; check whether end address has been reached 1520 | bcc LCB7F ; repeat if not 1521 | rts 1522 | 1523 | LCBAF: jsr LC66A 1524 | beq LCBA9 1525 | 1526 | ;; get two nibbles with bit mask from command line 1527 | ;; first goes into $036C+x (bit mask in $03CC+x) 1528 | ;; second goes into $033C+x (bit mask in $039C+x) 1529 | LCBB4: jsr LCBC0 1530 | sta $03CC,x 1531 | lda $033C,x 1532 | sta $036C,x 1533 | 1534 | ;; get nibble from command line, checking for wildcard ('*') 1535 | LCBC0: jsr GETCHR ; get character 1536 | ldy #$0F ; bit mask $0F 1537 | cmp #'*' ; is it '*'? 1538 | bne LCBCB ; jump if not 1539 | ldy #$00 ; bit mask $00 1540 | LCBCB: jsr LC2AF ; convert char to nibble $0-$F 1541 | sta $033C,x ; store nibble 1542 | tya 1543 | sta $039C,x ; store bit mask 1544 | rts 1545 | 1546 | ;; compare byte in A with byte Y of expected sequence 1547 | ;; return with Z set if matching 1548 | LCBD6: sta $B4 ; temp storage 1549 | lsr ; get high nibble into low 1550 | lsr 1551 | lsr 1552 | lsr 1553 | eor $036C,y ; zero-out bits that match for high nibble 1554 | and $03CC,y ; zero-out bits according to bit mask for high nibble 1555 | and #$0F ; only bits 0-3 1556 | bne LCBF0 ; if not zero then we have a difference 1557 | lda $B4 ; get byte back 1558 | eor $033C,y ; zero-out bits that match for low nibble 1559 | and $039C,y ; zero-out bits according to bit mask for low nibble 1560 | and #$0F ; only bits 0-3 1561 | LCBF0: rts 1562 | 1563 | ;; memory size (MS) 1564 | MEMSIZ: ldx #3 1565 | MSL1: ldx #$01 ; get 00,01,FF,FF 1566 | stx $FC ; into FB-FE 1567 | dex 1568 | stx $FB 1569 | dex 1570 | stx $FD 1571 | stx $FE 1572 | jsr LC351 ; print CR 1573 | ldx #$00 1574 | MSL2: lda ($FB,x) ; save current value 1575 | tay 1576 | lda #$55 1577 | sta ($FB,x) 1578 | cmp ($FB,x) 1579 | bne MSL5 1580 | lda #$AA 1581 | sta ($FB,x) 1582 | cmp ($FB,x) 1583 | bne MSL5 1584 | MSL4: tya 1585 | sta ($FB,x) ; restore original value 1586 | jsr LC367 ; increment address 1587 | jsr LC466 ; check if we've tested the whole range 1588 | bcc MSL2 ; repeat if not 1589 | .byte $2C ; skip following 2-byte opcode 1590 | MSL5: sta ($FB,x) 1591 | jsr LC323 ; print current address 1592 | rts ; done 1593 | 1594 | ;; memory test (MT) 1595 | MEMTST: ldx #$A4 1596 | jsr GETWRDX ; get start address 1597 | jsr GETWRDX ; get end address 1598 | ldy #1 ; default: 1 repetition 1599 | jsr PEEKCH ; do we have more arguments? 1600 | beq MTL1 ; skip if not 1601 | jsr LC28D ; get number of repetitions 1602 | tay 1603 | MTL1: sty $FF ; store number of repetitions 1604 | lda $FC ; get high byte of start address 1605 | bne MTL2 ; is it greater than zero? 1606 | jmp ERROR ; no => can't test zero-page memory 1607 | MTL2: jsr LC351 ; print CR 1608 | MTL3: ldx #3 1609 | MTL4: lda $A4,x ; get start and end address back 1610 | sta $FB,x ; from temp to FB-FE 1611 | dex 1612 | bpl MTL4 1613 | ldx #0 1614 | MTL5: lda ($FB,x) ; save current value 1615 | tay 1616 | lda #$00 1617 | sta ($FB,x) 1618 | cmp ($FB,x) 1619 | bne MTL6 1620 | lda #$55 1621 | sta ($FB,x) 1622 | cmp ($FB,x) 1623 | bne MTL6 1624 | lda #$AA 1625 | sta ($FB,x) 1626 | cmp ($FB,x) 1627 | bne MTL6 1628 | lda #$FF 1629 | sta ($FB,x) 1630 | cmp ($FB,x) 1631 | beq MTL7 1632 | MTL6: jsr LC323 ; fail: output current address 1633 | jsr LC34C ; output space 1634 | MTL7: tya 1635 | sta ($FB,x) ; restore original value 1636 | jsr LC367 ; increment address 1637 | jsr LC466 ; check if we've tested the whole range 1638 | bcc MTL5 ; repeat if not 1639 | lda #'+' ; print pacifier 1640 | jsr $FFD2 1641 | dec $FF ; decrement repetition count 1642 | bne MTL3 ; go again until 0 1643 | rts 1644 | 1645 | ; TRACE (Tx) 1646 | TRACE: .if VIA == 0 1647 | jmp ERROR ; can only do trace if we have a VIA 1648 | .endif 1649 | pla 1650 | pla 1651 | jsr CHRIN 1652 | jsr UCASE 1653 | cmp #$57 1654 | bne LCBFD 1655 | jmp LCD56 ; TW command 1656 | LCBFD: cmp #$42 1657 | bne LCC04 1658 | jmp LCDD0 ; TB command 1659 | LCC04: cmp #$51 1660 | bne LCC0B 1661 | jmp LCD4F ; TQ command 1662 | LCC0B: cmp #$53 1663 | beq LCC12 ; TS command 1664 | jmp ERROR 1665 | 1666 | ;; Trace Stop (TS) 1667 | LCC12: jsr LC28D 1668 | pha 1669 | jsr LC28D 1670 | pha 1671 | jsr LC249 1672 | ldy #$00 1673 | lda ($FB),y 1674 | sta $02BC 1675 | tya 1676 | sta ($FB),y 1677 | lda #TBINT 1680 | sta BRK_HI 1681 | ldx #$FC 1682 | jmp LC3EC 1683 | 1684 | ;; entry point after breakpoint is hit 1685 | TBINT: ldx #$03 1686 | LCC38: pla 1687 | sta SRSAVE,x 1688 | dex 1689 | bpl LCC38 1690 | pla 1691 | pla 1692 | tsx 1693 | stx SPSAVE 1694 | lda PCHSAVE 1695 | sta $FC 1696 | lda PCLSAVE 1697 | sta $FB 1698 | lda $02BC 1699 | ldy #$00 1700 | sta ($FB),y 1701 | lda #SMON 1704 | sta BRK_HI 1705 | lda #$52 1706 | jmp LC2FF 1707 | LCC65: jsr LC351 1708 | RTSCMD: rts 1709 | sta AKSAVE 1710 | php 1711 | pla 1712 | and #$EF 1713 | sta SRSAVE 1714 | stx XRSAVE 1715 | sty YSAVE 1716 | pla 1717 | clc 1718 | adc #$01 1719 | sta PCLSAVE 1720 | pla 1721 | adc #$00 1722 | sta PCHSAVE 1723 | lda #$80 1724 | sta $02BC 1725 | bne LCCA5 1726 | 1727 | ;; entry point from TW after an instruction has been executed 1728 | ;; (via timer interrupt) 1729 | TWINT: lda #$40 ; clear VIA timer 1 interrupt flag 1730 | sta VIA_IFR 1731 | jsr LCDE5 ; restore IRQ vector 1732 | cld ; make sure "decimal" flag is not set 1733 | .if UART_TYPE==6522 ; if VIA is also used as UART 1734 | lda #$40 ; set T1 free run, T2 clock ?2 1735 | sta VIA_ACR ; set VIA 1 ACR 1736 | lda #$40 ; disable VIA timer 1 interrupt 1737 | sta VIA_IER ; set VIA 1 IER 1738 | lda #$90 ; enable VIA CB1 interrupt 1739 | sta VIA_IER ; set VIA 1 IER 1740 | .endif 1741 | ldx #$05 ; get registers from stack 1742 | LCC9E: pla ; (were put there when IRQ happened) 1743 | sta PCHSAVE,x ; store them in PCHSAVE area 1744 | dex 1745 | bpl LCC9E 1746 | LCCA5: lda IRQ_LO ; save IRQ pointer 1747 | sta $02BB 1748 | lda IRQ_HI 1749 | sta $02BA 1750 | tsx 1751 | stx SPSAVE ; save stack pointer 1752 | cli ; allow interrupts 1753 | 1754 | lda SRSAVE 1755 | and #$10 1756 | beq LCCC5 1757 | LCCBD: jsr LCC65 1758 | lda #$52 1759 | jmp LC2FF 1760 | LCCC5: bit $02BC 1761 | bvc LCCE9 1762 | sec 1763 | lda PCLSAVE 1764 | sbc $02BD 1765 | sta $02B1 1766 | lda PCHSAVE 1767 | sbc $02BE 1768 | ora $02B1 1769 | bne LCD46 1770 | lda $02BF 1771 | bne LCD43 1772 | lda #$80 1773 | sta $02BC 1774 | LCCE9: bmi LCCFD 1775 | lsr $02BC 1776 | bcc LCCBD 1777 | ldx SPSAVE 1778 | txs 1779 | lda #>RTSCMD 1780 | pha 1781 | lda #TWINT ; (2) 1856 | sta $02BB ; (4) 1857 | stx $02BA ; (4) 1858 | LCDA9: ldx SPSAVE ; (4) 1859 | txs ; (2) 1860 | cli ; (2) 1861 | lda $02BB ; (4) 1862 | ldx $02BA ; (4) 1863 | sta IRQ_LO ; (4) 1864 | stx IRQ_HI ; (4) 1865 | LCDBA: lda PCHSAVE ; (4) 1866 | pha ; (3) 1867 | lda PCLSAVE ; (4) 1868 | pha ; (3) 1869 | lda SRSAVE ; (4) 1870 | pha ; (3) 1871 | lda AKSAVE ; (4) 1872 | ldx XRSAVE ; (4) 1873 | ldy YSAVE ; (4) 1874 | rti ; (6) => total 75 cycles, timer expires during RTI? 1875 | 1876 | ;; Trace Break (TB) 1877 | LCDD0: jsr LC28D 1878 | sta $02BE 1879 | jsr LC28D 1880 | sta $02BD 1881 | jsr LC28D 1882 | sta $02BF 1883 | jmp LC2D6 1884 | 1885 | ;; restore IRQ vector 1886 | LCDE5: lda $02B8 1887 | ldx $02B9 1888 | sta IRQ_LO 1889 | stx IRQ_HI 1890 | rts 1891 | 1892 | ;; save IRQ vector and set BRK vector to entry point 1893 | LCDF2: lda IRQ_LO 1894 | ldx IRQ_HI 1895 | sta $02B8 1896 | stx $02B9 1897 | lda #TWINT 1900 | sta BRK_HI 1901 | rts 1902 | 1903 | ;;; ---------------------------------------------------------------------------- 1904 | ;;; --------------------------- C64 KERNAL routines ------------------------- 1905 | ;;; ---------------------------------------------------------------------------- 1906 | 1907 | LINEBUF = $0400 ; line ("screen") buffer memory start 1908 | NUMCOLS = 80 ; number of columns per row 1909 | NUMROWS = 24 ; number of rows 1910 | INPUT_UCASE = 0 ; do not automatically convert input to uppercase 1911 | SUPPRESS_NP = 0 ; do not suppress any characters on output 1912 | 1913 | ;; print 16-bit integer in $62/$63 as decimal value, adapted from: 1914 | ;; https://beebwiki.mdfs.net/Number_output_in_6502_machine_code#16-bit_decimal 1915 | PRTINT: LDY #8 ; offset to powers of ten 1916 | PRL1: LDX #$FF 1917 | SEC ; start with digit=-1 1918 | PRL2: LDA $63 1919 | SBC PRPOW+0,Y 1920 | STA $63 ; subtract current tens 1921 | LDA $62 1922 | SBC PRPOW+1,Y 1923 | STA $62 1924 | INX 1925 | BCS PRL2 ; loop until <0 1926 | LDA $63 ; add current tens back in 1927 | ADC PRPOW+0,Y 1928 | STA $63 1929 | LDA $62 1930 | ADC PRPOW+1,Y 1931 | STA $62 1932 | TXA 1933 | BEQ PRL3 ; leading zero => skip 1934 | ORA #'0' ; convert to 0-9 digit 1935 | JSR CHROUT ; output character 1936 | PRL3: DEY 1937 | DEY 1938 | BPL PRL1 ; Loop for next digit 1939 | RTS 1940 | PRPOW: .word 1, 10, 100, 1000, 10000 1941 | 1942 | .include "kernal.asm" 1943 | -------------------------------------------------------------------------------- /smon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhansel/smon6502/6b149bc3277fd9b2648fb7df281d55b3f54fcf5e/smon.bin -------------------------------------------------------------------------------- /uart_6522.asm: -------------------------------------------------------------------------------- 1 | ;;; This code was taken and adapted from the VIC-20 kernal RS232 routines, 2 | ;;; using the commented disassembly from Lee Davidson: 3 | ;;; https://www.mdawson.net/vic20chrome/vic20/docs/kernel_disassembly.txt 4 | ;;; 5 | ;;; This code assumes that the VIA interrupt output is connected to the CPU's 6 | ;;; IRQ input pin. 7 | ;;; 8 | ;;; Note that the bit timings assume a 1Mhz clock. To use a different clock 9 | ;;; speed, adapt the values in the baud rate table at the bottom of this file. 10 | ;;; 11 | 12 | ;;; if DATAPORT=0, DATABIT=x: 13 | ;;; VIA serial TX (output) pin : CA2 (39) 14 | ;;; VIA serial RX (input) pin : CA1 (40) _and_ PAx (2+x) (must connect RX signal to both pins!) 15 | ;;; if DATAPORT=1, DATABIT=x: 16 | ;;; VIA serial TX (output) pin : CB2 (19) 17 | ;;; VIA serial RX (input) pin : CB1 (18) _and_ PBx (10+x) (must connect RX signal to both pins!) 18 | DATAPORT = 0 ; 0=use port A (CA1, CA2, PAx), 1=use port B (CB1, CB2, PBx) 19 | DATABIT = 0 ; data bit (0 or 7) to use for RX input from selected port 20 | 21 | ;;; serial parameters (with a 1MHz clock, baud rates above 1200 may cause data corruption on receive) 22 | BAUDRATE = 8 ; 1=50, 2=75, 3=110, 4=134.5, 5=150, 6=300, 7=600, 8=1200, 9=1800, 10=2400, 11=3600 23 | PARITY = 0 ; 0=none, 1=odd, 3=even, 5=mark, 7=space 24 | STOPBITS = 1 ; 1 or 2 25 | DATABITS = 8 ; 5, 6, 7 or 8 26 | 27 | ;;; serial port buffer memory location and size 28 | RXBUF = $0334 ; memory location of RX buffer 29 | RXBUFLEN = 8 ; length of RX buffer (0 means 256) 30 | TXBUF = $03FC ; memory location of TX buffer 31 | TXBUFLEN = 4 ; length of TX buffer (0 means 256) 32 | 33 | ;;; pins used for serial port 34 | .if DATAPORT==1 35 | Cx1CTRL = $10 ; VIA PCR CB1 control bit (input edge control) 36 | Cx2CTRL = $20 ; VIA PCR CB2 control bit (output value control) 37 | Cx1FLAG = $10 ; VIA IER CB1 interrupt enable bit 38 | DDRxREG = VIA_DDRB ; VIA DDRB register 39 | DRxREG = VIA_DRB ; VIA DRB register 40 | .else 41 | Cx1CTRL = $01 ; VIA PCR CA1 control bit (input edge control) 42 | Cx2CTRL = $02 ; VIA PCR CA2 control bit (output value control) 43 | Cx1FLAG = $02 ; VIA IER CA1 interrupt enable bit 44 | DDRxREG = VIA_DDRA ; VIA DDRA register 45 | DRxREG = VIA_DRA ; VIA DRA register 46 | .endif 47 | 48 | .if DATABIT != 0 && DATABIT != 7 49 | .err "DATABIT must be 0 or 7!" 50 | .endif 51 | 52 | ;;; variables used in RS232 code 53 | RXBYTE = $92 ; receiver byte buffer/assembly location 54 | RXCNT = $95 ; receiver bit count in 55 | RXBIT = $96 ; receiver input bit temp storage 56 | RXSBIT = $98 ; receiver start bit check flag (inverted, 0 means start bit received) 57 | RXPBIT = $9A ; receiver parity bit storage 58 | RXBUFPTR = $A0 ; RX buffer pointer (two sequential bytes) 59 | TXBYTE = $9B ; transmitter byte buffer/disassembly location 60 | TXCNT = $9F ; transmitter bit count out 61 | TXBIT = $BF ; transmitter next bit to be sent 62 | TXPBIT = $C0 ; parity byte 63 | TXBUFPTR = $A2 ; TX buffer pointer (two sequential bytes) 64 | TMP = $97 ; temporary storage 65 | REGCTRL = $0293 ; pseudo 6551 control register 66 | REGCMD = $0294 ; pseudo 6551 command register 67 | REGSTAT = $0297 ; RS232 status register 68 | NBITS = $0298 ; number of bits to be sent/received 69 | BITTL = $0299 ; time of one bit cell low byte 70 | BITTH = $029A ; time of one bit cell high byte 71 | RXBUFEND = $029B ; index to Rx buffer end 72 | RXBUFSTART = $029C ; index to Rx buffer start 73 | TXBUFSTART = $029D ; index to Tx buffer start 74 | TXBUFEND = $029E ; index to Tx buffer end 75 | 76 | .if VIA==0 77 | .err "Need VIA to use VIA UART" 78 | .endif 79 | 80 | ;***********************************************************************************; 81 | ; 82 | ; open RS232 83 | 84 | 85 | UAINIT: ;; pseudo UART control register: 86 | ;; bit 7: stop bits: 0=1 stop bit, 1=2 stop bits 87 | ;; bits 6-5: word length: 00=8 bits, 01=7 bits, 10=6 bits, 11=5 bits 88 | ;; bit 4: not used 89 | ;; bits 3-0: baud rate: 0001=50, 0010=75, 0011=110, 0100=134.5, 0101=150, 0110=300, 0111=600 90 | ;; 1000=1200, 1001=1800, 1010=2400, 1011=3600 91 | LDA #(BAUDRATE + ((8-DATABITS)*32) + ((STOPBITS-1)*128)) 92 | STA REGCTRL ; set pseudo UART control register 93 | ;; pseudo UART command register: 94 | ;; bits 7-5: parity: xx0=none, 001=odd, 011=even, 101=mark, 111=space 95 | ;; bits 4-0: not used 96 | LDA #(PARITY*32) 97 | STA REGCMD ; set pseudo UART command register 98 | SEI ; prevent interrupts 99 | LDA #$7F ; disable all VIA interrupts 100 | STA VIA_IER ; on VIA 1 IER 101 | LDA #$40 ; set T1 free run, T2 clock ?2, SR disabled, latches disabled 102 | STA VIA_ACR ; set VIA 1 ACR 103 | LDA #~Cx1CTRL ; Cx2 high, Cx1 -ve edge 104 | STA VIA_PCR ; set VIA 1 PCR 105 | LDA DDRxREG ; get VIA 1 DDRx 106 | AND #~(1<RXBUF 143 | STA RXBUFPTR+1 144 | LDA #TXBUF 147 | STA TXBUFPTR+1 148 | LDA #UAIRQ 151 | STA $0315 152 | JSR LF05B ; prepare to receive a byte 153 | CLI ; allow interrupts 154 | RTS 155 | 156 | ;***********************************************************************************; 157 | ; 158 | ; Send byte to UART, wait until UART is ready to transmit 159 | ; A, X and Y register contents remain unchanged 160 | 161 | UAPUTW: STA TMP ; save data byte 162 | PHA 163 | TXA 164 | PHA 165 | TYA 166 | PHA 167 | LDA TMP ; get data byte back 168 | LDY TXBUFEND ; get index to Tx buffer end in Y 169 | LDX TXBUFEND ; get index to Tx buffer end in X 170 | INX ; + 1 171 | .if TXBUFLEN>0 172 | CPX #TXBUFLEN ; have we reached TXBUFLEN? 173 | BNE UAPL1 ; jump if not 174 | LDX #0 ; wrap to 0 175 | .endif 176 | UAPL1: CPX TXBUFSTART ; compare with index to Tx buffer start 177 | BEQ UAPL1 ; wait if buffer full 178 | STX TXBUFEND ; set new Tx buffer end 179 | STA (TXBUFPTR),Y ; store data byte in buffer (using previous index) 180 | SEI ; prevent interrupts 181 | BIT VIA_IER ; test VIA 1 IER 182 | BVS LF102 ; branch if T1 already enabled 183 | LDA BITTL ; get baud rate bit time low byte 184 | STA VIA_T1CL ; set VIA 1 T1C_l 185 | LDA BITTH ; get baud rate bit time high byte 186 | STA VIA_T1CH ; set VIA 1 T1C_h 187 | LDA #$C0 ; enable T1 interrupt 188 | STA VIA_IER ; set VIA 1 IER 189 | JSR LEFEE ; setup next RS232 Tx byte 190 | LF102: CLI ; allow interrupts 191 | PLA 192 | TAY 193 | PLA 194 | TAX 195 | PLA 196 | RTS 197 | 198 | ;***********************************************************************************; 199 | ; 200 | ; Get received byte from UART, result returned in A, 201 | ; returns A=0 if no character available for reading 202 | ; X and Y register contents remain unchanged 203 | 204 | UAGET: STY TMP ; save Y 205 | LDY RXBUFSTART ; get index to Rx buffer start 206 | CPY RXBUFEND ; compare with index to Rx buffer end 207 | BNE UAGW2 ; if not empty, get byte from buffer and exit 208 | LDY TMP ; restore Y 209 | LDA #$00 ; return null 210 | RTS 211 | 212 | ;***********************************************************************************; 213 | ; 214 | ; Get received byte from UART, result returned in A, 215 | ; waits until a received character is available 216 | ; X and Y register contents remain unchanged 217 | 218 | UAGETW: STY TMP ; save Y 219 | LDY RXBUFSTART ; get index to Rx buffer start 220 | UAGW1: CPY RXBUFEND ; compare with index to Rx buffer end 221 | BEQ UAGW1 ; wait if buffer empty 222 | UAGW2: LDA (RXBUFPTR),Y ; get byte from Rx buffer 223 | INY ; increment index 224 | .if RXBUFLEN>0 225 | CPY #RXBUFLEN ; have we reached RXBUFLEN? 226 | BNE UAGW3 ; jump if not 227 | LDY #0 ; wrap to 0 228 | .endif 229 | UAGW3: STY RXBUFSTART ; set new Rx buffer start 230 | LDY TMP ; restore Y 231 | RTS 232 | 233 | ;***********************************************************************************; 234 | ; 235 | ; RS232 interrupt handler 236 | 237 | UAIRQ: LDA VIA_IFR ; get VIA 1 IFR 238 | BPL LFEFF ; if no interrupt restore registers and exit 239 | AND VIA_IER ; AND with VIA 1 IER (mask out disabled interrupts) 240 | TAX ; copy to X 241 | LDA VIA_IER ; get VIA 1 IER 242 | ORA #$80 ; set enable bit, this bit should be set according to the 243 | ; Rockwell 6522 datasheet but clear acording to the MOS 244 | ; datasheet. best to assume it's not in the state required 245 | ; and set it so 246 | PHA ; save to re-enable interrupts 247 | LDA #$7F ; disable all interrupts 248 | STA VIA_IER ; set VIA 1 IER 249 | TXA ; get active interrupts back 250 | AND #$40 ; mask T1 interrupt 251 | BEQ LFF02 ; branch if not T1 interrupt 252 | 253 | ;; handle VIA T1 interrupt (TX) 254 | LDA #~(Cx1CTRL|Cx2CTRL) ; Cx2 low, Cx1 -ve edge 255 | ORA TXBIT ; OR RS232 next bit to send, sets Cx2 high if set 256 | STA VIA_PCR ; set VIA 1 PCR 257 | LDA VIA_T1CL ; get VIA 1 T1C_l 258 | PLA ; restore interrupt enable byte to restore previously enabled interrupts 259 | STA VIA_IER ; set VIA 1 IER 260 | JSR LEFA3 ; call RS232 Tx routine 261 | LFEFF: JMP LFF56 ; restore registers and exit interrupt 262 | 263 | LFF02: TXA ; get active interrupts back 264 | AND #$20 ; mask T2 interrupt 265 | BEQ LFF2C ; branch if not T2 interrupt 266 | 267 | ;; handle VIA T2 interrupt (RX) 268 | LDA DRxREG ; get VIA 1 DRx 269 | AND #(1<0 378 | CPY #TXBUFLEN ; have we reached TXBUFLEN? 379 | BNE LEFFC ; jump if not 380 | LDY #0 ; wrap to 0 381 | .endif 382 | LEFFC: STY TXBUFSTART ; set new Tx buffer start 383 | RTS 384 | 385 | ;; done sending 386 | LF021: LDA #$40 ; disable T1 interrupt 387 | STA VIA_IER ; set VIA 1 IER 388 | RTS 389 | 390 | ;***********************************************************************************; 391 | ; 392 | ; RS232 RX timer interrupt subroutine 393 | 394 | LF036: LDX RXSBIT ; get start bit check flag 395 | BNE LF068 ; branch if no start bit received yet 396 | DEC RXCNT ; decrement receiver bit count in 397 | BEQ LF06F ; branch if complete byte was received 398 | BMI LF04D ; branch if this is a stop bit 399 | LDA RXBIT ; get received bit 400 | EOR RXPBIT ; exclusive or with parity bit 401 | STA RXPBIT ; store as new parity bit 402 | .if DATABIT==7 403 | ASL RXBIT ; shift received bit into carry 404 | .else 405 | LSR RXBIT ; shift received bit into carry 406 | .endif 407 | ROR RXBYTE ; shift carry into received byte 408 | LF04A: RTS 409 | 410 | ;; no start bit received (yet) 411 | LF068: LDA RXBIT ; get received bit 412 | BNE LF05B ; if bit was 1 (no start bit) then go idle 413 | STA RXSBIT ; set start bit flag (start bit received) 414 | LDA #$00 ; clear received parity bit 415 | STA RXPBIT 416 | RTS 417 | 418 | ;; complete byte received (received bit is bit AFTER last data bit) 419 | ;; if receiving less than 8 data bits, shift received byte accordingly 420 | LF06F: LDA RXBYTE ; get assembled byte 421 | LDX NBITS ; NBITS is (number of data bits)+1 422 | LF081: CPX #$09 ; have we shifted enough yet? 423 | BEQ LF089 ; branch if so 424 | LSR ; else shift byte 425 | INX ; increment bit count 426 | BNE LF081 ; loop, branch always 427 | LF089: LDY RXBUFEND ; get index into Y 428 | LDX RXBUFEND ; get index into X 429 | INX ; increment index 430 | .if RXBUFLEN>0 431 | CPX #RXBUFLEN ; have we reached RXBUFLEN? 432 | BNE LF070 ; jump if not 433 | LDX #0 ; wrap to 0 434 | .endif 435 | LF070: CPX RXBUFSTART ; compare with index to Rx buffer start 436 | BEQ LF0A2 ; if buffer full, go do Rx overrun error 437 | STX RXBUFEND ; set new Rx buffer end 438 | STA (RXBUFPTR),Y ; save received byte to Rx buffer (using previous index) 439 | LDA #$20 ; mask 00x0 0000, parity enable bit 440 | BIT REGCMD ; test pseudo 6551 command register 441 | BEQ LF04B ; jump if parity is disabled 442 | BMI LF04A ; done (ok) if MARK or SPACE parity 443 | LDA RXBIT ; get received bit (parity) 444 | EOR RXPBIT ; exclusive or with computed parity bit 445 | BNE LF09D ; branch if computed parity is odd 446 | BVS LF04A ; branch (ok) if EVEN parity expected 447 | .byte $2C ; skip next opcode (fall through into parity error) 448 | LF09D: BVC LF04A ; branch (ok) if ODD parity expected 449 | 450 | ;; error codes 451 | LDA #$01 ; set Rx parity error 452 | .byte $2C ; skip next 2-byte opcode 453 | LF0A2: LDA #$04 ; set Rx overrun error 454 | .byte $2C ; skip next 2-byte opcode 455 | LF0A5: LDA #$80 ; set Rx break condition 456 | .byte $2C ; skip next 2-byte opcode 457 | LF0A8: LDA #$02 ; set Rx framing error 458 | ORA REGSTAT ; OR with RS232 status byte 459 | STA REGSTAT ; save RS232 status byte 460 | 461 | ;; prepare to receive next byte 462 | LF05B: LDA #$80|Cx1FLAG ; enable Cx1 interrupt 463 | STA VIA_IER ; set VIA 1 IER 464 | STA RXSBIT ; set start bit check flag (no start bit received) 465 | LDA #$20 ; disable T2 interrupt 466 | STA VIA_IER ; set VIA 1 IER 467 | STA RXBYTE ; zero-out received byte 468 | RTS 469 | 470 | ;; received bit is expected to be a stop bit (1) 471 | LF04B: DEC RXCNT ; decrement receiver bit count in 472 | LF04D: LDA RXBIT ; get received bit 473 | BNE LF05B ; if bit was 1 then prepare for next byte 474 | LF0B3: LDA RXBYTE ; get assembled byte 475 | BNE LF0A8 ; if non-zero then do frame error 476 | BEQ LF0A5 ; else do break error (branch always) 477 | 478 | 479 | ;***********************************************************************************; 480 | ; 481 | ; baud rate word is calculated from .. 482 | ; (system clock / 2 / baud rate) - 100 483 | 484 | ; baud rate table 485 | BRTAB: .word (CPU_CLOCK_RATE/2/50)-100 ; 50 baud 486 | .word (CPU_CLOCK_RATE/2/75)-100 ; 75 baud 487 | .word (CPU_CLOCK_RATE/2/110)-100 ; 110 baud 488 | .word (CPU_CLOCK_RATE /269)-100 ; 134.5 baud 489 | .word (CPU_CLOCK_RATE/2/150)-100 ; 150 baud 490 | .word (CPU_CLOCK_RATE/2/300)-100 ; 300 baud 491 | .word (CPU_CLOCK_RATE/2/600)-100 ; 600 baud 492 | .word (CPU_CLOCK_RATE/2/1200)-100 ; 1200 baud 493 | .word (CPU_CLOCK_RATE/2/1800)-100 ; 1800 baud 494 | .word (CPU_CLOCK_RATE/2/2400)-100 ; 2400 baud 495 | .word (CPU_CLOCK_RATE/2/3600)-100 ; 3600 baud 496 | -------------------------------------------------------------------------------- /uart_6551.asm: -------------------------------------------------------------------------------- 1 | ;============================================================================ 2 | ; 3 | ; 6551 Asynchronous Communication Interface Adapter driver for 6502 4 | ; Based on config and xmit delay code from the excellent videos by Adrien Kohlbecker 5 | ; 6 | ; Written by Chris McBrien and David Hansel 7 | ; 8 | ;============================================================================ 9 | 10 | ; The 65C51 ACIA has some serious bugs (from the datasheet errata): 11 | ; 12 | ; Transmitter Parity 13 | ; The transmitter of this part functions differently than previous 6551/65C51 devices. For 14 | ; all Parity Mode Control (PMC) settings (Bits 7, 6 of the Command Register), the 15 | ; transmitter will transmit a MARK (1) for Parity (When enabled with Bit 5 of the 16 | ; Command Register set to 1 ). Previous versions would transmit Even, Odd, Mark or 17 | ; Space parity depending on the PMC bits. 18 | ; 19 | ; Transmitter Data Register Empty 20 | ; The W65C51N will not properly set Bit 4 of the Status Register to indicate the 21 | ; Transmitter Data Register is empty. Determining when to send the next byte would 22 | ; need to be done by using the transmit interrupt or having a software delay loop based 23 | ; on the baud rate used. 24 | ; 25 | ; Also see: 26 | ; http://forum.6502.org/viewtopic.php?f=4&t=2543&sid=6c50db0270c03a2ca487dec97666d1f8&start=15#p28935 27 | ; 28 | ; For this driver those bugs mean the following: 29 | ; 1) Only "no parity" setting is supported 30 | ; 2) When transmitting we cannot query the ACIA whether it is ready but instead 31 | ; have to use a timed loop to wait until the character is sent 32 | 33 | 34 | ; Base memory address of the 6551 ACIA 35 | ACIA_ADDRESS = $5000 36 | 37 | ; serial parameters 38 | BAUD_RATE_CTRL = ACIA_CONTROL_BAUD_RATE_9600 39 | BAUD_RATE = 9600 ; must match the ACIA_CONTROL_BAUD_RATE setting above 40 | DATABITS = 8 ; 5, 6, 7 or 8 41 | STOPBITS = 1 ; 1 or 2 42 | 43 | 44 | ACIA_CONTROL_BAUD_RATE_50 = 0b0001 45 | ACIA_CONTROL_BAUD_RATE_75 = 0b0010 46 | ACIA_CONTROL_BAUD_RATE_109_92 = 0b0011 47 | ACIA_CONTROL_BAUD_RATE_134_58 = 0b0100 48 | ACIA_CONTROL_BAUD_RATE_150 = 0b0101 49 | ACIA_CONTROL_BAUD_RATE_300 = 0b0110 50 | ACIA_CONTROL_BAUD_RATE_600 = 0b0111 51 | ACIA_CONTROL_BAUD_RATE_1200 = 0b1000 52 | ACIA_CONTROL_BAUD_RATE_1800 = 0b1001 53 | ACIA_CONTROL_BAUD_RATE_2400 = 0b1010 54 | ACIA_CONTROL_BAUD_RATE_3600 = 0b1011 55 | ACIA_CONTROL_BAUD_RATE_4800 = 0b1100 56 | ACIA_CONTROL_BAUD_RATE_7200 = 0b1101 57 | ACIA_CONTROL_BAUD_RATE_9600 = 0b1110 58 | ACIA_CONTROL_BAUD_RATE_19200 = 0b1111 59 | ACIA_CONTROL_BAUD_RATE_115200 = 0b0000 60 | 61 | ACIA_COMMAND_DATA_TERMINAL_READY_DEASSERT = 0b0 << 0 62 | ACIA_COMMAND_DATA_TERMINAL_READY_ASSERT = 0b1 << 0 63 | ACIA_COMMAND_RECEIVER_ECHO_ENABLED = 0b1 << 4 64 | ACIA_COMMAND_RECEIVER_IRQ_DISABLED = 0b1 << 1 65 | ACIA_COMMAND_TRANSMITTER_CONTROL_REQUEST_TO_SEND_ASSERT_INTERRUPT_DISABLED = 0b10 << 2 66 | 67 | ACIA_STATUS_FRAMING_ERROR_DETECTED = 0b1 << 1 68 | ACIA_STATUS_OVERRUN_HAS_OCCURRED = 0b1 << 2 69 | ACIA_STATUS_RECEIVER_DATA_REGISTER_FULL = 0b1 << 3 70 | ACIA_STATUS_DATA_CARRIER_DETECT_HIGH = 0b1 << 5 71 | ACIA_STATUS_DATA_SET_READY_HIGH = 0b1 << 6 72 | ACIA_STATUS_INTERRUPT_OCCURRED = 0b1 << 7 73 | 74 | ; Memory mapped registers 75 | ACIA_REG_DATA = ACIA_ADDRESS+0 76 | ACIA_REG_STATUS = ACIA_ADDRESS+1 77 | ACIA_REG_COMMAND = ACIA_ADDRESS+2 78 | ACIA_REG_CONTROL = ACIA_ADDRESS+3 79 | 80 | ; Transmit delay 81 | ACIA_CHAR_CYCLES = ((DATABITS+STOPBITS+1)*CPU_CLOCK_RATE)/BAUD_RATE 82 | 83 | 84 | ;================================================================================ 85 | ; 86 | ; ACIA__init - initializes the serial port 87 | ; 88 | ; Preparatory Ops: none 89 | ; Returned Values: none 90 | ; 91 | ; Destroys: .A, .X, .Y 92 | ; 93 | ;================================================================================ 94 | ACIA__init: 95 | UAINIT: 96 | ; programmatically reset the chip by writing the status register 97 | sta ACIA_REG_STATUS 98 | 99 | ; set up the ACIA with baud rate, word length and stop bits defined above 100 | lda #(BAUD_RATE_CTRL + ((8-DATABITS)*32) + ((STOPBITS-1)*128)) 101 | sta ACIA_REG_CONTROL 102 | 103 | ; further set up the ACIA with 104 | ; - /DTR and /RTS both low 105 | ; - Receiver and transmitter IRQ off 106 | ; - Echo mode disabled 107 | ; - Parity disabled 108 | lda #(ACIA_COMMAND_DATA_TERMINAL_READY_ASSERT | ACIA_COMMAND_RECEIVER_IRQ_DISABLED | ACIA_COMMAND_TRANSMITTER_CONTROL_REQUEST_TO_SEND_ASSERT_INTERRUPT_DISABLED) 109 | sta ACIA_REG_COMMAND 110 | rts 111 | 112 | 113 | ;================================================================================ 114 | ; 115 | ; Send a single character to the serial port blocking until character sent 116 | ; 117 | ; Preparatory Ops: A. contains the character to send 118 | ; Returned Values: none 119 | ; Destroys: none 120 | ; 121 | ;================================================================================ 122 | 123 | ; because of the 65C51 ACIA TX bug (see top of this file) we must use 124 | ; a timed loop to wait until the 65C51 is finished sending the current character 125 | ; (instead of waiting until the ACIA reports that the send register is empty) 126 | UAPUTW: 127 | sta ACIA_REG_DATA ; transmit data byte 128 | 129 | ; wait until ACIA is done sending the byte 130 | pha ; save registers 131 | txa 132 | pha 133 | tya 134 | ldx #<(ACIA_CHAR_CYCLES/9)+1 135 | ldy #>(ACIA_CHAR_CYCLES/9)+1 136 | L1: nop ; these NOPs are here to even out the timing 137 | nop ; for the inner and outer loop (9 cycles each) 138 | L2: dex 139 | bne L1 140 | dey 141 | bne L2 142 | tay ; restore registers 143 | pla 144 | tax 145 | pla 146 | 147 | rts 148 | 149 | 150 | ;================================================================================ 151 | ; 152 | ; Get a single character from the serial port blocking until character received 153 | ; 154 | ; Preparatory Ops: none 155 | ; Returned Values: A. Received character 156 | ; Destroys: .A 157 | ; 158 | ;================================================================================ 159 | ACIA__getchar_wait: 160 | UAGETW: 161 | ; wait until a byte is available 162 | lda #ACIA_STATUS_RECEIVER_DATA_REGISTER_FULL 163 | .get_char_poll: 164 | bit ACIA_REG_STATUS 165 | beq .get_char_poll 166 | ; get received byte and return 167 | lda ACIA_REG_DATA 168 | rts 169 | 170 | 171 | ;================================================================================ 172 | ; 173 | ; Get a single character from the serial port non-blocking return 0 is none available 174 | ; 175 | ; Preparatory Ops: none 176 | ; Returned Values: A. Received character, or 0 177 | ; Destroys: A. 178 | ; 179 | ;================================================================================ 180 | ACIA__getchar: 181 | UAGET: 182 | ; check if byte is available 183 | lda ACIA_REG_STATUS 184 | and #ACIA_STATUS_RECEIVER_DATA_REGISTER_FULL 185 | beq .done 186 | ; get received byte and return 187 | lda ACIA_REG_DATA 188 | .done 189 | rts 190 | -------------------------------------------------------------------------------- /uart_6850.asm: -------------------------------------------------------------------------------- 1 | ;;; ---------------------------------------------------------------------------- 2 | ;;; ---------------------- UART communication functions ----------------------- 3 | ;;; ---------------------------------------------------------------------------- 4 | 5 | UART = $8200 6 | UARTS = UART+0 7 | UARTD = UART+1 8 | 9 | ;; initialize UART 10 | UAINIT: lda #$03 ; reset UART 11 | sta UARTS 12 | lda #$15 ; set 8N1 serial parameter 13 | sta UARTS 14 | rts 15 | 16 | ;; write character to UART, wait until UART is ready to transmit 17 | ;; A, X and Y registers must remain unchanged 18 | UAPUTW: PHA ; save character 19 | UAPUTL: LDA UARTS ; check UART status 20 | AND #$02 ; can write? 21 | BEQ UAPUTL ; wait if not 22 | PLA ; restore character 23 | STA UARTD ; write character 24 | RTS 25 | 26 | ;; get character from UART, return result in A, 27 | ;; return A=0 if no character available for reading 28 | ;; X and Y registers must remain unchanged 29 | UAGET: LDA UARTS ; check UART status 30 | AND #$01 ; can read? 31 | BEQ UAGRET ; if not, return with Z flag set 32 | LDA UARTD ; read UART data 33 | UAGRET: RTS 34 | 35 | ;; get character from UART, wait if none, return result in A 36 | ;; X and Y registers must remain unchanged 37 | UAGETW: JSR UAGET 38 | BEQ UAGETW 39 | RTS 40 | --------------------------------------------------------------------------------