Assembler for 6502 | 7 August 2005 21:07:03 | ||||||
Line | Hex | Source | |||||
0001 | 0000 | TANEX | EQU | 0 | // False, basic board | ||
0002 | |||||||
0003 | // | ||||||
0004 | // MICROTAN 65 - TANBUG | ||||||
0005 | // | ||||||
0006 | // The TANBUG monitor program is located in 1K bytes of read only memory | ||||||
0007 | // (ROM) at the top of the 6502 microprocessor 64K byte address space. | ||||||
0008 | // | ||||||
0009 | // TANBUG will only operate in the memory map of the microtan system, it is | ||||||
0010 | // not a general purpose 6502 software and has been specifically written for | ||||||
0011 | // Microtan. | ||||||
0012 | // | ||||||
0013 | // Locations F7F7, F7F8 and F7F9 are reserved for a jump to an expansion | ||||||
0014 | // monitor ROM which is positioned on the expansion board. | ||||||
0015 | // Locations $200 - $3FF are the visual display memory. TANBUG writes to these | ||||||
0016 | // locations whenever a command is typed to the monitor. | ||||||
0017 | // Locations $100 - $1FF are used as the stack by the microprocessor. | ||||||
0018 | // | ||||||
0019 | |||||||
0020 | |||||||
0021 | 0000 | ORG | $0 | // Zero system page variables | |||
0022 | |||||||
0023 | 0000 | NULL: | RMB | 1 | // Reserved for bpt use | ||
0024 | 0001 | ICHAR: | RMB | 1 | // ASCII character | ||
0025 | 0002 | OCHAR: | RMB | 1 | // Temp char store | ||
0026 | 0003 | VDUIND: | RMB | 1 | // Display index | ||
0027 | 0004 | INTFS1: | RMB | 3 | // Fast interrupt link | ||
0028 | 0007 | NMIJP: | RMB | 3 | // NMI link | ||
0029 | 000A | ICURS: | RMB | 2 | // Cursor index | ||
0030 | 000C | RUNIND: | RMB | 1 | // Zero if in user mode | ||
0031 | 000D | SINGLE: | RMB | 1 | // Nonzero if single instruction mode | ||
0032 | 000E | PROCED: | RMB | 1 | // Proceed count (single instr to execute) | ||
0033 | 000F | SIMCOM: | RMB | 1 | // Keypad (simple) /ASCII (complex) keyboard | ||
0034 | 0010 | INTSL1: | RMB | 3 | // Slow interrupt link | ||
0035 | 0013 | HXPKL: | RMB | 1 | // Hexpack store | ||
0036 | 0014 | HXPKH: | RMB | 1 | |||
0037 | |||||||
0038 | // Pseudo registers | ||||||
0039 | |||||||
0040 | 0015 | PCLBCK: | RMB | 1 | // PCL | ||
0041 | 0016 | PCHBCK: | RMB | 1 | // PCH | ||
0042 | 0017 | PSWBCK: | RMB | 1 | // PSW | ||
0043 | 0018 | SPBCK: | RMB | 1 | // SP | ||
0044 | 0019 | XBCK: | RMB | 1 | // IX | ||
0045 | 001A | YBCK: | RMB | 1 | // IY | ||
0046 | 001B | ABCK: | RMB | 1 | // A | ||
0047 | |||||||
0048 | // Temporary stores | ||||||
0049 | |||||||
0050 | 001C | MODADL: | RMB | 1 | |||
0051 | 001D | MODADH: | RMB | 1 | |||
0052 | 001E | COPL: | RMB | 1 | |||
0053 | 001F | COPH: | RMB | 1 | |||
0054 | |||||||
0055 | // Breakpoint status table and code store | ||||||
0056 | |||||||
0057 | 0020 | BPTLO: | RMB | 1 | |||
0058 | 0021 | BPTHI: | RMB | 15 | |||
0059 | 0030 | BPTCOD: | RMB | 16 | |||
0060 | |||||||
0061 | // Stack base | ||||||
0062 | |||||||
0063 | 0100 | STKBSE: | EQU | $100 | |||
0064 | |||||||
0065 | // Display scroll labels | ||||||
0066 | |||||||
0067 | 0200 | VDUSTT: | EQU | $200 | |||
0068 | 0220 | VDUFST: | EQU | $220 | |||
0069 | 0300 | VDUMID: | EQU | $300 | |||
0070 | 0320 | VDUTOP: | EQU | $320 | |||
0071 | 03E0 | LINBOT: | EQU | $3E0 | |||
0072 | |||||||
0073 | // I/O Ports | ||||||
0074 | |||||||
0075 | BFF0 | SGRAPH: | EQU | $BFF0 | |||
0076 | BFF0 | KBINCL: | EQU | $BFF0 | // Alternative to SGRAPH | ||
0077 | BFF1 | SNMI: | EQU | $BFF1 | |||
0078 | BFF2 | KBWRIT: | EQU | $BFF2 | |||
0079 | BFF3 | KBREAD: | EQU | $BFF3 | |||
0080 | BFF3 | STEXT: | EQU | $BFF3 | // Write to set text mode | ||
0081 | |||||||
0082 | F7F7 | INPERR: | EQU | $F7F7 | // Error exit | ||
0083 | |||||||
0084 | |||||||
0085 | #if | TANEX | |||||
0086 | |||||||
0087 | ORG | $F800 | |||||
0088 | |||||||
0089 | JMP | $F951 | // Jump table to utility routines | ||||
0090 | JMP | $F9B2 | |||||
0091 | JMP | $F99B | |||||
0092 | JMP | OPCHR1 | |||||
0093 | LDA | #13 | |||||
0094 | JMP | OPCHR | |||||
0095 | JMP | $FAE9 | |||||
0096 | JMP | $FB0C | |||||
0097 | JMP | HEXPCK | |||||
0098 | JMP | HEXPNT | |||||
0099 | JMP | POLLKB | |||||
0100 | |||||||
0101 | LDX | #$FF | |||||
0102 | TXS | ||||||
0103 | JMP | MONTOR | |||||
0104 | |||||||
0105 | JMP | $FB16 | |||||
0106 | JMP | $FB23 | |||||
0107 | JMP | WASKB | |||||
0108 | FDB | $FCF8 | |||||
0109 | |||||||
0110 | SETUP: | JMP | KBINT | ||||
0111 | JMP | NMNT | |||||
0112 | FDB | LINBOT | // ICURS setting | ||||
0113 | FCB | 1 | // RUNIND | ||||
0114 | FCB | 0 | // SINGLE | ||||
0115 | FCB | 0 | // PROCED | ||||
0116 | FCB | 0 | // SIMCOM | ||||
0117 | FCB | $40 | // Slow Interrupt (RTI instruction) | ||||
0118 | |||||||
0119 | BIT | $0 | |||||
0120 | |||||||
0121 | |||||||
0122 | #endif | ||||||
0123 | |||||||
0124 | |||||||
0125 | // Start of ROM code for Microtan 65 TANBUG | ||||||
0126 | |||||||
0127 | FC00 | ORG | $FC00 | ||||
0128 | |||||||
0129 | // TANBUG starts here on reset | ||||||
0130 | |||||||
0131 | #if | TANEX | |||||
0132 | START: | JMP | $F83E | ||||
0133 | #else | ||||||
0134 | FC00 A2 FF | START: | LDX | #$FF | |||
0135 | FC02 9A | TXS | // Set stack pointer to top of the stack | ||||
0136 | #endif | ||||||
0137 | FC03 E8 | INX | // | ||||
0138 | FC04 86 17 | STX | PSWBCK | // Clear breakpoint store as their values will be | |||
0139 | |||||||
0140 | FC06 20 B7 FF | JSR | BPTCLR | // Clear breakpoints | |||
0141 | FC09 8D F3 BF | STA | STEXT | // Set text mode | |||
0142 | |||||||
0143 | // Use table in ROM to initialise parameters (note order of table must | ||||||
0144 | // correspond with the order of INTFS1 to ICURSH in RAM definitions) | ||||||
0145 | |||||||
0146 | #if | TANEX | |||||
0147 | LDX | #12 | |||||
0148 | SETUP1: | LDA | SETUP,X | ||||
0149 | #else | ||||||
0150 | FC0C A2 0E | LDX | #14 | ||||
0151 | FC0E BD DF FF | SETUP1: | LDA | SETUP,X | // SETUP holds parameter table | ||
0152 | #endif | ||||||
0153 | FC11 95 04 | STA | INTFS1,X | // Store in zero page RAM | |||
0154 | FC13 CA | DEX | |||||
0155 | FC14 10 F8 | BPL | SETUP1 | ||||
0156 | |||||||
0157 | // Determine keyboard type and set flag, note IX = $FF | ||||||
0158 | |||||||
0159 | FC16 E8 | INX | |||||
0160 | FC17 8E F2 BF | TSFIV: | STX | KBWRIT | // Clear keyboard write latch | ||
0161 | FC1A 8D F0 BF | STA | KBINCL | // Clear keyboard interrupt flag | |||
0162 | FC1D CA | DEX | |||||
0163 | FC1E 8E F2 BF | STX | KBWRIT | // Write to keyboard lines | |||
0164 | FC21 E8 | INX | // Reset IX | ||||
0165 | FC22 AD F3 BF | LDA | KBREAD | // Read it back | |||
0166 | FC25 10 02 | BPL | KPCPLX | // If plus not set - alphanumeric | |||
0167 | FC27 E6 0F | INC | SIMCOM | // If set - must be keypad | |||
0168 | #if | TANEX | |||||
0169 | KPCPLX: | JSR | $FADB | ||||
0170 | #else | ||||||
0171 | FC29 8D F0 BF | KPCPLX: | STA | KBINCL | // Clear keyboard interrupt | ||
0172 | #endif | ||||||
0173 | FC2C BD EC FF | TBMS: | LDA | HDR,X | // Display TANBUG message | ||
0174 | FC2F F0 06 | BEQ | MONTOR | // Output chars until a 0 | |||
0175 | FC31 20 75 FE | JSR | OPCHR | ||||
0176 | FC34 E8 | INX | |||||
0177 | FC35 D0 F5 | BNE | TBMS | ||||
0178 | |||||||
0179 | |||||||
0180 | |||||||
0181 | // MAIN LOOP - monitor user input and act accordingly | ||||||
0182 | |||||||
0183 | FC37 D8 | MONTOR: | CLD | // Set binary mode | |||
0184 | FC38 58 | CLI | |||||
0185 | FC39 20 FA FD | JSR | POLLKB | // Look at keyboard | |||
0186 | FC3C A5 01 | LDA | ICHAR | // Get char | |||
0187 | FC3E C9 21 | CMP | #$21 | // Less than a space - term | |||
0188 | FC40 30 06 | BMI | MONCH1 | // Else output char | |||
0189 | FC42 20 75 FE | ISTERM: | JSR | OPCHR | |||
0190 | FC45 4C 37 FC | JMP | MONTOR | ||||
0191 | |||||||
0192 | FC48 20 4F FC | MONCH1: | JSR | MONEN2 | // Call string process | ||
0193 | FC4B A9 0D | RC1: | LDA | #$0D | // Set up CR | ||
0194 | FC4D D0 F3 | BNE | ISTERM | // Uncond. branch loop | |||
0195 | |||||||
0196 | FC4F A0 00 | MONEN2: | LDY | #0 | |||
0197 | FC51 B1 0A | LDA | (ICURS),Y | // Pick up command | |||
0198 | FC53 AA | TAX | |||||
0199 | FC54 C8 | INY | |||||
0200 | FC55 B1 0A | LDA | (ICURS),Y | // Peek at next char | |||
0201 | FC57 10 36 | BPL | MULTI | // If not -ve (cursor) must be parameter | |||
0202 | FC59 A9 00 | LDA | #0 | // Else set A to zero | |||
0203 | |||||||
0204 | |||||||
0205 | |||||||
0206 | // S - SINGLE INSTRUCTION MODE COMMAND | ||||||
0207 | // | ||||||
0208 | // This command switches single instruction mode ON. | ||||||
0209 | // Single instruction mode is a very powerful debugging aid. When set | ||||||
0210 | // TANBUG executes the user program one instruction at a time, re-entering | ||||||
0211 | // the monitor between each instruction and printing out the status of all | ||||||
0212 | // of the microprocessor's internal registers as they were after the last | ||||||
0213 | // instruction executed in the user program. | ||||||
0214 | // The S command is used in conjunction with the proceed command P and the | ||||||
0215 | // normal mode command N. | ||||||
0216 | |||||||
0217 | FC5B E0 53 | TRYS: | CPX | #$53 | // Was it S? | ||
0218 | FC5D D0 03 | BNE | TRYN | ||||
0219 | FC5F 86 0D | STX | SINGLE | // Yes - set single step mode | |||
0220 | FC61 60 | RTS | |||||
0221 | |||||||
0222 | |||||||
0223 | |||||||
0224 | // N - NORMAL MODE COMMAND | ||||||
0225 | // | ||||||
0226 | // The N command is the complement of the S command and is used to cancel | ||||||
0227 | // the S command so that the microprocessor executes the user program in | ||||||
0228 | // the normal manner without returning to the monitor between each instruction. | ||||||
0229 | // Reset automatically sets the normal mode of operation. | ||||||
0230 | |||||||
0231 | FC62 E0 4E | TRYN: | CPX | #$4E | // Command N? | ||
0232 | FC64 D0 03 | BNE | TRYP | ||||
0233 | FC66 85 0D | STA | SINGLE | // else clear single instruction mode (ACC=0) | |||
0234 | FC68 60 | RTS | |||||
0235 | |||||||
0236 | |||||||
0237 | |||||||
0238 | // P - PROCEED COMMAND (with no argument) | ||||||
0239 | // | ||||||
0240 | // This command is used to execute the next instruction when in single | ||||||
0241 | // instruction mode (after the program has been started with a G command). | ||||||
0242 | // The pseudo registers are reloaded and the next instruction executed. | ||||||
0243 | // After execution, the microprocessor status is displayed as follows: | ||||||
0244 | // ADDR PSW SP IX IY ACC | ||||||
0245 | // With no parameters entered, only the next instruction is executed | ||||||
0246 | |||||||
0247 | FC69 E0 50 | TRYP: | CPX | #$50 | // Command P with no arg? | ||
0248 | FC6B D0 04 | BNE | TRYR | ||||
0249 | FC6D 85 0E | STA | PROCED | // Clear P count (A=0) | |||
0250 | FC6F F0 56 | BEQ | PROC1 | // Uncond. branch proc | |||
0251 | |||||||
0252 | |||||||
0253 | |||||||
0254 | // R - REGISTER MODIFY / EXAMINE COMMAND | ||||||
0255 | // | ||||||
0256 | // This command is used to view / set the pseudo registers prior to running | ||||||
0257 | // a program with the G command. It effectively executes a M15 command | ||||||
0258 | // to examine the pseudo registers in locations $15 to $1B | ||||||
0259 | |||||||
0260 | FC71 E0 52 | TRYR: | CPX | #$52 | // Command R? | ||
0261 | FC73 D0 09 | BNE | TRYB | ||||
0262 | FC75 85 1D | STA | MODADH | // Note A=0 | |||
0263 | FC77 A9 15 | LDA | #$15 | // Set pseudo reg | |||
0264 | FC79 85 1C | STA | MODADL | ||||
0265 | FC7B 4C E5 FD | JMP | REOPEN | // Jump mod memory | |||
0266 | |||||||
0267 | |||||||
0268 | |||||||
0269 | // B - BREAKPOINT COMMAND (no parameters) | ||||||
0270 | // | ||||||
0271 | // A breakpoint is a complementary debugging aid to single instruction mode. | ||||||
0272 | // Instead of stepping singly through all instructions in a program, the | ||||||
0273 | // breakpoint facility allows the user to specify the address at which he | ||||||
0274 | // requires the monitor to be re-entered from his/her program. A breakpoint | ||||||
0275 | // can be set just previous to where the fault is suspected to exist and the | ||||||
0276 | // program started with the G command. Normal execution occurs until the | ||||||
0277 | // breakpoint is reached, then the monitor is re-entered with the same status | ||||||
0278 | // print-out as for single instruction mode. Any monitor commands can then be | ||||||
0279 | // used and the program continued. | ||||||
0280 | // | ||||||
0281 | // With no parameters, the B command removes all breakpoints | ||||||
0282 | |||||||
0283 | FC7E E0 42 | TRYB: | CPX | #$42 | // Command B? | ||
0284 | FC80 D0 04 | BNE | ERRQ | // No - then error | |||
0285 | FC82 20 B7 FF | JSR | BPTCLR | // Else clear breakpoints | |||
0286 | FC85 60 | RTS | |||||
0287 | |||||||
0288 | |||||||
0289 | |||||||
0290 | // With no TANEX FFF7 will respond to F7F7 | ||||||
0291 | // With TANEX, this monitor can be expanded since FFF7 jumps back to here | ||||||
0292 | |||||||
0293 | #if | TANEX | |||||
0294 | ERRQ: | JMP | $FA75 | ||||
0295 | #else | ||||||
0296 | FC86 4C F7 F7 | ERRQ: | JMP | INPERR | |||
0297 | #endif | ||||||
0298 | |||||||
0299 | FC89 A9 3F | RETERR: | LDA | #$3F | |||
0300 | FC8B 20 75 FE | JSR | OPCHR | // Display question mark | |||
0301 | FC8E 60 | RTS | |||||
0302 | |||||||
0303 | |||||||
0304 | |||||||
0305 | // If we get here command expects parameters too | ||||||
0306 | |||||||
0307 | FC8F 88 | MULTI: | DEY | ||||
0308 | FC90 8A | TXA | // Save cmd on stack | ||||
0309 | FC91 48 | PHA | |||||
0310 | FC92 20 28 FF | JSR | HEXPCK | // Pack its argument | |||
0311 | FC95 D0 54 | BNE | MOREY | // Any more data? | |||
0312 | FC97 68 | PLA | // Restore command | ||||
0313 | FC98 50 EC | BVC | ERRQ | // Error if no arg | |||
0314 | |||||||
0315 | |||||||
0316 | |||||||
0317 | // G - GO COMMAND | ||||||
0318 | // | ||||||
0319 | // Parameter is the address of the first instruction to run | ||||||
0320 | // When executed the cursor disappears, and is restored on completion | ||||||
0321 | // The program counter is initialised to the parameter address, and the | ||||||
0322 | // stack pointer to $1FF (top of stack). The other registers// A, X, Y, PSW | ||||||
0323 | // are loaded from the pseudo registers in the zero page ($15 - $1B) | ||||||
0324 | |||||||
0325 | FC9A C9 47 | CMP | #$47 | // Is it a G? | |||
0326 | FC9C D0 21 | BNE | TRYPL | // No - skip | |||
0327 | FC9E A2 00 | LDX | #0 | ||||
0328 | FCA0 86 0E | STX | PROCED | // Clear proceed count | |||
0329 | FCA2 CA | DEX | // Set IX to $FF | ||||
0330 | FCA3 9A | GOEND: | TXS | // Reload it | |||
0331 | FCA4 A5 14 | LDA | HXPKH | // Push PC high | |||
0332 | FCA6 48 | PHA | |||||
0333 | FCA7 A5 13 | LDA | HXPKL | // Push PC low | |||
0334 | FCA9 48 | PHA | |||||
0335 | FCAA A5 17 | LDA | PSWBCK | ||||
0336 | FCAC 48 | PHA | |||||
0337 | FCAD C6 0C | DEC | RUNIND | // Clear run flag | |||
0338 | FCAF A9 20 | LDA | #$20 | ||||
0339 | FCB1 A4 03 | LDY | VDUIND | ||||
0340 | FCB3 91 0A | STA | (ICURS),Y | // Obliterate cursor | |||
0341 | FCB5 A6 19 | LDX | XBCK | ||||
0342 | FCB7 A4 1A | LDY | YBCK | ||||
0343 | FCB9 A5 1B | SRET: | LDA | ABCK | // Set users Acc | ||
0344 | FCBB 8D F1 BF | STA | SNMI | // Set NMI for next | |||
0345 | FCBE 40 | RTI | // Goto user prog | ||||
0346 | |||||||
0347 | |||||||
0348 | |||||||
0349 | // P - PROCEED COMMAND (with argument) | ||||||
0350 | // | ||||||
0351 | // This command is used to execute the next instruction when in single | ||||||
0352 | // instruction mode (after the program has been started with a G command). | ||||||
0353 | // The pseudo registers are reloaded and the next instruction executed. | ||||||
0354 | // After execution, the microprocessor status is displayed as follows: | ||||||
0355 | // ADDR PSW SP IX IY ACC | ||||||
0356 | // If a parameter less than or equal to $FF is entered, then this number | ||||||
0357 | // of instructions are executed before returning to the monitor | ||||||
0358 | |||||||
0359 | FCBF C9 50 | TRYPL: | CMP | #$50 | // Command P with arg? | ||
0360 | FCC1 D0 11 | BNE | TRYM | ||||
0361 | FCC3 A5 13 | LDA | HXPKL | // Set P count | |||
0362 | FCC5 85 0E | STA | PROCED | ||||
0363 | FCC7 A5 16 | PROC1: | LDA | PCHBCK | // Restore users PC | ||
0364 | FCC9 85 14 | PNOARG: | STA | HXPKH | |||
0365 | FCCB A5 15 | LDA | PCLBCK | ||||
0366 | FCCD 85 13 | STA | HXPKL | ||||
0367 | FCCF A6 18 | LDX | SPBCK | // Set IX to users SP | |||
0368 | FCD1 4C A3 FC | JMP | GOEND | // Then back to user | |||
0369 | |||||||
0370 | |||||||
0371 | |||||||
0372 | // M - MODIFY/EXAMINE MEMORY COMMAND | ||||||
0373 | // | ||||||
0374 | // Parameter is the memory address to be examined / modified | ||||||
0375 | // TANBUG shows memory address and location, and awaits user input: | ||||||
0376 | // - any terminator, location not altered and closes command | ||||||
0377 | // - value followed by terminator, modifies location with value, if terminator is | ||||||
0378 | // CR, closes command | ||||||
0379 | // SPACE, shows same location | ||||||
0380 | // LF, shows next memory location | ||||||
0381 | // ESC, shows previous memory location | ||||||
0382 | |||||||
0383 | FCD4 C9 4D | TRYM: | CMP | #$4D | // Command M address? | ||
0384 | FCD6 D0 AE | BNE | ERRQ | // No - error | |||
0385 | FCD8 A9 2C | EQPT: | LDA | #$2C | |||
0386 | FCDA 20 75 FE | JSR | OPCHR | // Output a comma | |||
0387 | FCDD A0 00 | LDY | #0 | ||||
0388 | FCDF B1 13 | LDA | (HXPKL),Y | // Pick up value | |||
0389 | FCE1 20 0B FF | JSR | HEXPNT | // and display it | |||
0390 | FCE4 68 | PLA | // Pop stack return | ||||
0391 | FCE5 68 | PLA | |||||
0392 | FCE6 A9 2C | LDA | #$2C | // Load comma | |||
0393 | FCE8 4C 42 FC | JMP | ISTERM | // and back to monitor | |||
0394 | |||||||
0395 | |||||||
0396 | |||||||
0397 | // If here then there is a second parameter | ||||||
0398 | |||||||
0399 | FCEB E0 2C | MOREY: | CPX | #$2C | // Was term a comma? | ||
0400 | FCED F0 04 | BEQ | GETPT2 | // Yes - continue | |||
0401 | FCEF 68 | LINKPH: | PLA | // Else pull command | |||
0402 | FCF0 4C 86 FC | LINKR: | JMP | ERRQ | // and give error | ||
0403 | |||||||
0404 | FCF3 A5 13 | GETPT2: | LDA | HXPKL | // No comma - store previous | ||
0405 | FCF5 85 1C | STA | MODADL | // in MODADL & MODADH | |||
0406 | FCF7 A5 14 | LDA | HXPKH | ||||
0407 | FCF9 85 1D | STA | MODADH | ||||
0408 | FCFB 20 28 FF | JSR | HEXPCK | // Pack next value | |||
0409 | FCFE D0 7C | BNE | MOREY1 | // Not cursor - more yet | |||
0410 | FD00 68 | PLA | // Else pull command | ||||
0411 | FD01 50 ED | BVC | LINKR | // No argument? - error | |||
0412 | |||||||
0413 | |||||||
0414 | |||||||
0415 | // L - LIST COMMAND (see LISTIT routine below) | ||||||
0416 | |||||||
0417 | FD03 C9 4C | CMP | #$4C | // Command L? | |||
0418 | FD05 F0 42 | BEQ | LISTIT | // Yes - list it | |||
0419 | |||||||
0420 | |||||||
0421 | |||||||
0422 | // O - OFFSET COMMAND | ||||||
0423 | // | ||||||
0424 | // The offset command is a program writing aid. It calculates branch offsets | ||||||
0425 | // for the user for incorporation as arguments in branch instructions. | ||||||
0426 | // Parameters are the address of the branch opcode, and the address of the | ||||||
0427 | // destination. The result is the value to be used as the argument for the | ||||||
0428 | // branch. | ||||||
0429 | // Note that the maximum branch is $7F forwards, or backwards | ||||||
0430 | |||||||
0431 | FD07 C9 4F | CMP | #$4F | // Command O? | |||
0432 | FD09 D0 27 | BNE | TRYBPT | ||||
0433 | FD0B A5 13 | LDA | HXPKL | // Get branch dest | |||
0434 | FD0D 38 | SEC | |||||
0435 | FD0E E9 02 | SBC | #2 | // Adjust for branch code | |||
0436 | FD10 B0 02 | BCS | NOTOPO | ||||
0437 | FD12 C6 14 | DEC | HXPKH | ||||
0438 | FD14 38 | NOTOPO: | SEC | ||||
0439 | FD15 E5 1C | SBC | MODADL | // Subtract source | |||
0440 | FD17 AA | TAX | // Hold result in IX | ||||
0441 | FD18 A5 14 | LDA | HXPKH | // Subtract high byte | |||
0442 | FD1A E5 1D | SBC | MODADH | ||||
0443 | FD1C A8 | TAY | // Store in IY | ||||
0444 | FD1D 8A | TXA | // Get low byte | ||||
0445 | FD1E 30 05 | BMI | RNGNG | // If -ve branch | |||
0446 | FD20 98 | TYA | // If +ve look at high | ||||
0447 | FD21 D0 CD | BNE | LINKR | // Not 0 - then error | |||
0448 | FD23 F0 03 | BEQ | PNTITO | // If ok continue | |||
0449 | |||||||
0450 | FD25 C8 | RNGNG: | INY | // If -ve, then high is $FF | |||
0451 | FD26 D0 C8 | BNE | LINKR | ||||
0452 | FD28 A9 3D | PNTITO: | LDA | #$3D | |||
0453 | FD2A 20 75 FE | JSR | OPCHR | // Ok - display equals sign | |||
0454 | FD2D 8A | TXA | |||||
0455 | FD2E 20 0B FF | JSR | HEXPNT | // ... and the value | |||
0456 | FD31 60 | RTS | |||||
0457 | |||||||
0458 | |||||||
0459 | |||||||
0460 | // B - BREAKPOINT COMMAND (with parameters) | ||||||
0461 | // | ||||||
0462 | // As described above. | ||||||
0463 | // Parameters are the address of any opcode instruction, and the number of the | ||||||
0464 | // breakpoint to be set (0 to 7) | ||||||
0465 | |||||||
0466 | FD32 C9 42 | TRYBPT: | CMP | #$42 | // Command B? | ||
0467 | FD34 D0 BA | LINK1: | BNE | LINKR | // No - error | ||
0468 | FD36 A5 13 | LDA | HXPKL | // Maximum breakpoint code is 7 | |||
0469 | FD38 30 B6 | BMI | LINKR | ||||
0470 | FD3A C9 08 | CMP | #8 | // If greater - then error | |||
0471 | FD3C 10 B2 | BPL | LINKR | ||||
0472 | FD3E 0A | ASL | A | // Double A | |||
0473 | FD3F AA | TAX | // Set IX for indexed addressing | ||||
0474 | FD40 A5 1C | LDA | MODADL | // Store breakpoint address | |||
0475 | FD42 95 20 | STA | BPTLO,X | ||||
0476 | FD44 A5 1D | LDA | MODADH | ||||
0477 | FD46 95 21 | STA | BPTHI,X | ||||
0478 | FD48 60 | JPRTRN: | RTS | ||||
0479 | |||||||
0480 | |||||||
0481 | |||||||
0482 | // L - LIST MEMORY COMMAND | ||||||
0483 | // | ||||||
0484 | // Parameters are start memory address, and number of lines of 8 consecutive | ||||||
0485 | // memory locations to show | ||||||
0486 | // If 0 lines are requested, 256 lines will be shown | ||||||
0487 | // TANBUG pauses between each line to permit the user to read the output | ||||||
0488 | |||||||
0489 | FD49 20 73 FE | LISTIT: | JSR | OUTPCR | // Output carriage return | ||
0490 | FD4C A0 00 | NXLI: | LDY | #0 | |||
0491 | FD4E A5 1D | LDA | MODADH | // Display address | |||
0492 | FD50 20 0B FF | JSR | HEXPNT | // High byte ... | |||
0493 | FD53 A5 1C | LDA | MODADL | ||||
0494 | FD55 20 0B FF | NXLIST: | JSR | HEXPNT | // Output low byte | ||
0495 | FD58 A9 20 | LDA | #$20 | ||||
0496 | FD5A 20 75 FE | JSR | OPCHR | // Output a space | |||
0497 | FD5D B1 1C | LDA | (MODADL),Y | // Display memory locations | |||
0498 | FD5F C8 | INY | |||||
0499 | FD60 C0 09 | CPY | #9 | // For eight memory locations | |||
0500 | FD62 30 F1 | BMI | NXLIST | ||||
0501 | FD64 C6 13 | DEC | HXPKL | // Decrement line count | |||
0502 | FD66 F0 E0 | BEQ | JPRTRN | // O? Return via CR (note requesting 0 lines gives 256) | |||
0503 | |||||||
0504 | #if | TANEX | |||||
0505 | DELX1: | NOP | |||||
0506 | NOP | ||||||
0507 | NOP | ||||||
0508 | NOP | ||||||
0509 | NOP | ||||||
0510 | NOP | ||||||
0511 | #else | ||||||
0512 | FD68 88 | DELX1: | DEY | // Time delay | |||
0513 | FD69 D0 FD | BNE | DELX1 | ||||
0514 | FD6B CA | DEX | |||||
0515 | FD6C D0 FA | BNE | DELX1 | ||||
0516 | #endif | ||||||
0517 | |||||||
0518 | FD6E A5 1C | LDA | MODADL | // Now adjust the address, for next 8 locations | |||
0519 | FD70 18 | CLC | |||||
0520 | FD71 69 08 | ADC | #8 | ||||
0521 | FD73 85 1C | STA | MODADL | ||||
0522 | FD75 90 D2 | BCC | LISTIT | // If Carry set | |||
0523 | FD77 E6 1D | INC | MODADH | // then increment high byte | |||
0524 | FD79 4C 49 FD | JMP | LISTIT | ||||
0525 | |||||||
0526 | |||||||
0527 | |||||||
0528 | // If we get here there is a third parameter | ||||||
0529 | |||||||
0530 | FD7C E0 2C | MOREY1: | CPX | #$2C | // Comma? | ||
0531 | FD7E F0 03 | BEQ | TERMOK | ||||
0532 | FD80 4C EF FC | ERJUM2: | JMP | LINKPH | // No - then error | ||
0533 | |||||||
0534 | FD83 A5 13 | TERMOK: | LDA | HXPKL | // Else store parameter | ||
0535 | FD85 85 1E | STA | COPL | ||||
0536 | FD87 A5 14 | LDA | HXPKH | ||||
0537 | FD89 85 1F | STA | COPH | ||||
0538 | FD8B 20 28 FF | JSR | HEXPCK | // then pack new para | |||
0539 | FD8E D0 F0 | BNE | ERJUM2 | // error not term | |||
0540 | FD90 68 | PLA | |||||
0541 | |||||||
0542 | |||||||
0543 | // M - MEMORY MODIFY / EXAMINE (modify location) | ||||||
0544 | // | ||||||
0545 | // If user has entered a value to be entered into the momeory location | ||||||
0546 | // then this routine processes it | ||||||
0547 | |||||||
0548 | FD91 C9 4D | CMP | #$4D | // Command M? | |||
0549 | FD93 F0 27 | BEQ | MEM100 | // Yes - modify memory | |||
0550 | |||||||
0551 | |||||||
0552 | |||||||
0553 | // C - COPY COMMAND | ||||||
0554 | // | ||||||
0555 | // The copy command allows copying of the contents of one block of memory to | ||||||
0556 | // another. The parameters are start address source, end address source and | ||||||
0557 | // start address destination. These are copied to MODADL, COPL, and HXPKL | ||||||
0558 | // respectively. | ||||||
0559 | |||||||
0560 | FD95 C9 43 | CMP | #$43 | // Command C? | |||
0561 | FD97 D0 9B | BNE | LINK1 | // No - then error | |||
0562 | FD99 50 99 | BVC | LINK1 | // Argument? Error if not | |||
0563 | FD9B A0 00 | LDY | #0 | ||||
0564 | FD9D B1 1C | NXCOP: | LDA | (MODADL),Y | // Copy from source start address | ||
0565 | FD9F 91 13 | STA | (HXPKL),Y | // to destination | |||
0566 | FDA1 A5 1F | LDA | COPH | // Check if we've reached end address | |||
0567 | FDA3 C5 1D | CMP | MODADH | ||||
0568 | FDA5 D0 06 | BNE | ICMCOP | ||||
0569 | FDA7 A5 1E | LDA | COPL | ||||
0570 | FDA9 C5 1C | CMP | MODADL | ||||
0571 | FDAB F0 5B | BEQ | ENDLS | ||||
0572 | FDAD E6 1C | ICMCOP: | INC | MODADL | // No, then increment source | ||
0573 | FDAF D0 02 | BNE | NOHIH1 | ||||
0574 | FDB1 E6 1D | INC | MODADH | ||||
0575 | FDB3 E6 13 | NOHIH1: | INC | HXPKL | // and increment destination | ||
0576 | FDB5 D0 E6 | BNE | NXCOP | ||||
0577 | FDB7 E6 14 | INC | HXPKH | ||||
0578 | FDB9 D0 E2 | BNE | NXCOP | // Destination can not roll over top of memory | |||
0579 | FDBB 60 | RTS | |||||
0580 | |||||||
0581 | |||||||
0582 | |||||||
0583 | // Modify memory location (M command above) | ||||||
0584 | |||||||
0585 | FDBC A6 01 | MEM100: | LDX | ICHAR | // Get input character in IX | ||
0586 | FDBE E0 20 | CPX | #$20 | // Was it a space? | |||
0587 | FDC0 F0 23 | BEQ | REOPEN | // Yes - reopen | |||
0588 | FDC2 50 06 | BVC | NOENT | // Branch if nothing | |||
0589 | FDC4 A5 13 | LDA | HXPKL | // Else enter data | |||
0590 | FDC6 A0 00 | LDY | #0 | ||||
0591 | FDC8 91 1C | STA | (MODADL),Y | ||||
0592 | |||||||
0593 | FDCA E0 0A | NOENT: | CPX | #$0A | // Was LF typed? | ||
0594 | FDCC F0 11 | BEQ | WASLF | // Yes - then process it | |||
0595 | |||||||
0596 | FDCE E0 1B | CPX | #$1B | // Was it ESC? | |||
0597 | FDD0 D0 36 | BNE | ENDLS | // No - then return | |||
0598 | |||||||
0599 | FDD2 C6 1C | ESCIT: | DEC | MODADL | // Decrement memory modify address | ||
0600 | FDD4 A5 1C | LDA | MODADL | ||||
0601 | FDD6 C9 FF | CMP | #$FF | ||||
0602 | FDD8 D0 0B | BNE | REOPEN | ||||
0603 | FDDA C6 1D | DEC | MODADH | ||||
0604 | FDDC 4C E5 FD | JMP | REOPEN | ||||
0605 | |||||||
0606 | FDDF E6 1C | WASLF: | INC | MODADL | // Increment memory address | ||
0607 | FDE1 D0 02 | BNE | REOPEN | ||||
0608 | FDE3 E6 1D | INC | MODADH | // and high byte, if required | |||
0609 | |||||||
0610 | FDE5 20 73 FE | REOPEN: | JSR | OUTPCR | // Output carriage return | ||
0611 | FDE8 A9 4D | LDA | #$4D | ||||
0612 | FDEA 20 75 FE | JSR | OPCHR | // Display 'M' | |||
0613 | FDED A5 1D | LDA | MODADH | // and address | |||
0614 | FDEF 20 0B FF | JSR | HEXPNT | ||||
0615 | FDF2 A5 1C | LDA | MODADL | ||||
0616 | FDF4 20 0B FF | JSR | HEXPNT | ||||
0617 | FDF7 4C 4F FC | JMP | MONEN2 | // Check next command | |||
0618 | |||||||
0619 | |||||||
0620 | |||||||
0621 | // POLL KEYBOARD | ||||||
0622 | // | ||||||
0623 | // Gets a character from either the simple keypad or ASCII keyboard. Key | ||||||
0624 | // value is stored in ICHAR ($01) | ||||||
0625 | |||||||
0626 | FDFA A9 00 | POLLKB: | LDA | #0 | |||
0627 | FDFC 48 | PHA | // Push 0 - shift indicator | ||||
0628 | FDFD 85 01 | PLKB1: | STA | ICHAR | // Set ICHAR to zero | ||
0629 | FDFF C5 0F | CMP | SIMCOM | // Check if keypad | |||
0630 | FE01 D0 06 | BNE | SIMPLE | ||||
0631 | |||||||
0632 | // ASCII keyboard routine | ||||||
0633 | |||||||
0634 | FE03 C5 01 | WAIT1: | CMP | ICHAR | // Else wait for interrupt | ||
0635 | FE05 F0 FC | BEQ | WAIT1 | ||||
0636 | FE07 68 | PLKEND: | PLA | // Pop indicator | |||
0637 | FE08 60 | ENDLS: | RTS | ||||
0638 | |||||||
0639 | // Simple keypad routine | ||||||
0640 | |||||||
0641 | FE09 A9 0F | SIMPLE: | LDA | #$0F | |||
0642 | FE0B 8D F2 BF | STA | KBWRIT | // Enable all keyboard lines | |||
0643 | FE0E AD F3 BF | LDA | KBREAD | // Look at keyboard lines | |||
0644 | FE11 D0 F6 | BNE | SIMPLE | // Key down? - wait till up | |||
0645 | |||||||
0646 | FE13 A2 40 | LDX | #$40 | // Debounce it | |||
0647 | FE15 88 | DEBOUN: | DEY | ||||
0648 | FE16 D0 FD | BNE | DEBOUN | ||||
0649 | FE18 CA | DEX | |||||
0650 | FE19 D0 FA | BNE | DEBOUN | ||||
0651 | |||||||
0652 | FE1B A0 FF | PLK1: | LDY | #$FF | // Now poll the keypad properly | ||
0653 | FE1D 68 | PLA | // Peek at shift indicator | ||||
0654 | FE1E 48 | PHA | |||||
0655 | FE1F F0 02 | BEQ | NOSHIF | // If shift set modify IY | |||
0656 | FE21 A0 13 | LDY | #$13 | ||||
0657 | FE23 A2 08 | NOSHIF: | LDX | #8 | // Set IX - keyboard drive | ||
0658 | FE25 8E F2 BF | PLK2: | STX | KBWRIT | // Drive keyboard lines | ||
0659 | FE28 AD F3 BF | LDA | KBREAD | // Get result | |||
0660 | FE2B D0 0C | BNE | ACHAR | // Not 0 - a char - so skip | |||
0661 | FE2D C8 | INY | // Else adjust IY | ||||
0662 | FE2E C8 | INY | |||||
0663 | FE2F C8 | INY | |||||
0664 | FE30 C8 | INY | |||||
0665 | FE31 C8 | INY | |||||
0666 | FE32 8A | TXA | |||||
0667 | FE33 4A | LSR | A | // Shift IX right | |||
0668 | FE34 AA | TAX | |||||
0669 | FE35 F0 E4 | BEQ | PLK1 | // If zero repeat | |||
0670 | FE37 D0 EC | BNE | PLK2 | // Else next line | |||
0671 | |||||||
0672 | // If we get here a key has been pressed | ||||||
0673 | |||||||
0674 | FE39 C8 | ACHAR: | INY | ||||
0675 | FE3A 4A | LSR | A | // Which key of 5? | |||
0676 | FE3B 90 FC | BCC | ACHAR | // C set? That's the key | |||
0677 | FE3D B9 4B FE | LDA | CHRTBL,Y | // Get ASCII equivalent | |||
0678 | FE40 85 01 | STA | ICHAR | // And put in ICHAR | |||
0679 | FE42 D0 C3 | BNE | PLKEND | // If zero - shift | |||
0680 | FE44 68 | PLA | // Pull shift | ||||
0681 | FE45 49 FF | EOR | #$FF | // Change shift state | |||
0682 | FE47 48 | PHA | // Push shift | ||||
0683 | FE48 4C 09 FE | JMP | SIMPLE | // ... and continue | |||
0684 | |||||||
0685 | // Character look up table for ASCII equivalent | ||||||
0686 | |||||||
0687 | FE4B 33 37 42 | CHRTBL: | FCB | $33, $37, $42 | |||
0688 | FE4E 46 3F | FCB | $46, $3F | ||||
0689 | FE50 32 36 41 | FCB | $32, $36, $41 | ||||
0690 | FE53 45 0D | FCB | $45, $0D | ||||
0691 | FE55 31 35 39 | FCB | $31, $35, $39 | ||||
0692 | FE58 44 0A | FCB | $44, $0A | ||||
0693 | FE5A 30 34 38 | FCB | $30, $34, $38 | ||||
0694 | FE5D 43 00 | FCB | $43, $00 | ||||
0695 | FE5F 2C 52 4C | FCB | $2C, $52, $4C | ||||
0696 | FE62 4E 3F | FCB | $4E, $3F | ||||
0697 | FE64 32 43 49 | FCB | $32, $43, $49 | ||||
0698 | FE67 53 20 | FCB | $53, $20 | ||||
0699 | FE69 31 4F 1B | FCB | $31, $4F, $1B | ||||
0700 | FE6C 47 7F | FCB | $47, $7F | ||||
0701 | FE6E 30 34 50 | FCB | $30, $34, $50 | ||||
0702 | FE71 4D 00 | FCB | $4D, $00 | ||||
0703 | |||||||
0704 | |||||||
0705 | |||||||
0706 | // OUTPUT A CARRIAGE RETURN | ||||||
0707 | // | ||||||
0708 | // This subroutine causes the display to scroll up one line by outputting | ||||||
0709 | // a carriage return to the screen. It also reinstates the cursor when a | ||||||
0710 | // user program is run with the G command | ||||||
0711 | // ACC is corrupted, IX and IY are preserved | ||||||
0712 | |||||||
0713 | FE73 A9 0D | OUTPCR: | LDA | #$0D | // Output a CR | ||
0714 | |||||||
0715 | // OUTPUT A CHARACTER | ||||||
0716 | // | ||||||
0717 | // Displays the character in the ACC on the screen | ||||||
0718 | // ACC is corrupted, IX and IY are preserved | ||||||
0719 | |||||||
0720 | #if | TANEX | |||||
0721 | OPCHR: | JMP | $F87C | ||||
0722 | NOP | ||||||
0723 | OPCHR1: | STA | OCHAR | ||||
0724 | LDY | VDUIND | // Get cursor position | ||||
0725 | LDA | #$20 | |||||
0726 | STA | (ICURS),Y | // and erase cursor | ||||
0727 | LDX | OCHAR | // Get char in IX | ||||
0728 | CPX | #12 | |||||
0729 | BNE | TRYDEL | |||||
0730 | JSR | $FA23 | |||||
0731 | DODEL: | LDA | #$FF | ||||
0732 | STA | (ICURS),Y | // Display cursor | ||||
0733 | STY | VDUIND | // and save index | ||||
0734 | RTS | ||||||
0735 | |||||||
0736 | TRYDEL: | CPX | #$7F | // Is it delete? | |||
0737 | BNE | TRYCR | |||||
0738 | JSR | $FA09 | |||||
0739 | BPL | DODEL | |||||
0740 | |||||||
0741 | TRYCR: | CPX | #$0D | // Is it a CR? | |||
0742 | BEQ | NXLINE | |||||
0743 | TXA | // No, then output character | |||||
0744 | STA | (ICURS),Y | |||||
0745 | INY | // Increment vdu index | |||||
0746 | CPY | #32 | // End of line? | ||||
0747 | BNE | DODEL | |||||
0748 | NXLINE: | LDA | #32 | ||||
0749 | CLC | ||||||
0750 | ADC | ICURS | |||||
0751 | STA | ICURS | |||||
0752 | LDA | ICURS+1 | |||||
0753 | ADC | #0 | |||||
0754 | STA | ICURS+1 | |||||
0755 | LDY | #0 | |||||
0756 | CMP | #4 | |||||
0757 | BNE | DODEL | |||||
0758 | JSR | $FA38 | |||||
0759 | BEQ | DODEL | |||||
0760 | NOP | ||||||
0761 | NOP | ||||||
0762 | NOP | ||||||
0763 | NOP | ||||||
0764 | NOP | ||||||
0765 | |||||||
0766 | #else | ||||||
0767 | FE75 85 02 | OPCHR: | STA | OCHAR | // Save the character | ||
0768 | FE77 8A | TXA | // Save IX and IY | ||||
0769 | FE78 48 | PHA | |||||
0770 | FE79 98 | TYA | |||||
0771 | FE7A 48 | PHA | |||||
0772 | FE7B A4 03 | LDY | VDUIND | // Get cursor position | |||
0773 | FE7D A9 20 | LDA | #$20 | ||||
0774 | FE7F 91 0A | STA | (ICURS),Y | // and erase cursor | |||
0775 | FE81 A6 02 | LDX | OCHAR | // Get char in IX | |||
0776 | FE83 E0 7F | CPX | #$7F | // Is it delete? | |||
0777 | FE85 D0 10 | BNE | TRYCR | ||||
0778 | FE87 88 | DEY | // Decrement vdu index | ||||
0779 | FE88 10 02 | BPL | DODEL | ||||
0780 | FE8A A0 00 | ZERCUR: | LDY | #0 | // If negative set zero | ||
0781 | FE8C A9 FF | DODEL: | LDA | #$FF | |||
0782 | FE8E 91 0A | STA | (ICURS),Y | // Display cursor | |||
0783 | FE90 84 03 | STY | VDUIND | // and save index | |||
0784 | FE92 68 | PLA | // Restore registers and exit | ||||
0785 | FE93 A8 | TAY | |||||
0786 | FE94 68 | PLA | |||||
0787 | FE95 AA | TAX | |||||
0788 | FE96 60 | RTS | |||||
0789 | |||||||
0790 | FE97 E0 0D | TRYCR: | CPX | #13 | // Is it a CR? | ||
0791 | FE99 F0 08 | BEQ | DOCR | ||||
0792 | FE9B 8A | TXA | // No, then output character | ||||
0793 | FE9C 91 0A | STA | (ICURS),Y | ||||
0794 | FE9E C8 | INY | // Increment vdu index | ||||
0795 | FE9F C0 20 | CPY | #32 | // End of line? | |||
0796 | FEA1 30 E9 | BMI | DODEL | // No - then tidy up and exit | |||
0797 | FEA3 A2 00 | DOCR: | LDX | #0 | // Scroll line | ||
0798 | FEA5 BD 20 02 | LOWBLK: | LDA | VDUFST,X | // Do in two blocks | ||
0799 | FEA8 9D 00 02 | STA | VDUSTT,X | ||||
0800 | FEAB E8 | INX | |||||
0801 | FEAC D0 F7 | BNE | LOWBLK | ||||
0802 | FEAE BD 20 03 | HIBLK: | LDA | VDUTOP,X | |||
0803 | FEB1 9D 00 03 | STA | VDUMID,X | ||||
0804 | FEB4 E8 | INX | |||||
0805 | FEB5 E0 E0 | CPX | #$E0 | ||||
0806 | FEB7 D0 F5 | BNE | HIBLK | ||||
0807 | |||||||
0808 | FEB9 A9 20 | LDA | #$20 | ||||
0809 | FEBB A8 | TAY | |||||
0810 | FEBC 88 | MORSP: | DEY | // Fill line with spaces | |||
0811 | FEBD 91 0A | STA | (ICURS),Y | ||||
0812 | FEBF D0 FB | BNE | MORSP | ||||
0813 | FEC1 F0 C7 | BEQ | ZERCUR | // When done, tidy up | |||
0814 | #endif | ||||||
0815 | |||||||
0816 | |||||||
0817 | |||||||
0818 | // KEYBOARD INTERRUPT | ||||||
0819 | // | ||||||
0820 | // Note this is entered via jump instruction stored in RAM location INTFS1 | ||||||
0821 | // so that user can access interrupts quickly. | ||||||
0822 | // A reset will always initiate INTFS1 | ||||||
0823 | |||||||
0824 | FEC3 48 | KBINT: | PHA | // Save accumulator | |||
0825 | FEC4 D8 | CLD | // Set binary mode | ||||
0826 | FEC5 8A | TXA | // Save IX | ||||
0827 | FEC6 48 | PHA | |||||
0828 | FEC7 BA | TSX | // Get SP in IX | ||||
0829 | FEC8 E8 | INX | // Point IX to old PSW | ||||
0830 | FEC9 E8 | INX | |||||
0831 | FECA E8 | INX | |||||
0832 | FECB BD 00 01 | LDA | STKBSE,X | // and get the PSW | |||
0833 | FECE 29 10 | AND | #$10 | // Was it a break? | |||
0834 | FED0 D0 1E | BNE | BRKP | // Yes - then process it | |||
0835 | FED2 68 | PLA | // Else restore IX | ||||
0836 | FED3 AA | TAX | |||||
0837 | #if | TANEX | |||||
0838 | JSR | $FAA3 | |||||
0839 | #else | ||||||
0840 | FED4 AD F3 BF | LDA | KBREAD | // Read keyboard | |||
0841 | #endif | ||||||
0842 | FED7 30 04 | BMI | WASKB | // If -ve, then was keyboard | |||
0843 | FED9 68 | USER: | PLA | // Else restore A | |||
0844 | FEDA 4C 10 00 | JMP | INTSL1 | // and check the slow interrupt | |||
0845 | |||||||
0846 | |||||||
0847 | |||||||
0848 | FEDD 29 7F | WASKB: | AND | #$7F | // Mask top bit | ||
0849 | FEDF 85 01 | STA | ICHAR | // and store in ICHAR | |||
0850 | #if | TANEX | |||||
0851 | JSR | $F911 | |||||
0852 | #else | ||||||
0853 | FEE1 8D F0 BF | STA | KBINCL | // Clear keyboard interrupt flip-flop | |||
0854 | #endif | ||||||
0855 | FEE4 C9 1B | CMP | #$1B | // Was key ESC? | |||
0856 | FEE6 D0 F1 | BNE | USER | // No - then normal return | |||
0857 | FEE8 A5 0C | LDA | RUNIND | // Else - check if user program running? | |||
0858 | FEEA D0 ED | BNE | USER | // No - then normal return | |||
0859 | FEEC 85 0E | STA | PROCED | // Else clear proceed count | |||
0860 | FEEE F0 12 | BEQ | ACTBP | // and unconditionally branch to break | |||
0861 | |||||||
0862 | |||||||
0863 | |||||||
0864 | // BREAK PROCESSING | ||||||
0865 | // | ||||||
0866 | // Note the user should not set a break at own break or in this interrupt routine | ||||||
0867 | // else crashes. Adjust PC to return to instr must subtract 3 | ||||||
0868 | |||||||
0869 | FEF0 E8 | BRKP: | INX | // address PC L | |||
0870 | FEF1 38 | SEC | // set C | ||||
0871 | FEF2 BD 00 01 | LDA | STKBSE,X | // get PCL | |||
0872 | FEF5 E9 02 | SBC | #2 | // subtract 3 | |||
0873 | FEF7 9D 00 01 | STA | STKBSE,X | // put it back | |||
0874 | FEFA B0 04 | BCS | NOROLL | // C set? NOHI byte | |||
0875 | FEFC E8 | INX | // else address PCH | ||||
0876 | FEFD DE 00 01 | DEC | STKBSE,X | // dec PCH | |||
0877 | FF00 68 | NOROLL: | PLA | // pull IX | |||
0878 | FF01 AA | TAX | // restore it | ||||
0879 | FF02 68 | ACTBP: | PLA | // pull accumulator | |||
0880 | FF03 85 1B | STA | ABCK | // back it up | |||
0881 | FF05 20 C1 FF | JSR | BPTREM | // restore user code | |||
0882 | FF08 4C 75 FF | NOROL: | JMP | NMNT1 | // service break | ||
0883 | |||||||
0884 | |||||||
0885 | |||||||
0886 | // DISPLAY HEX VALUES | ||||||
0887 | // | ||||||
0888 | // Takes a hex value stored in accumulator and displays as two hex characters | ||||||
0889 | // Registers ACC and IX are corrupted | ||||||
0890 | |||||||
0891 | FF0B 48 | HEXPNT: | PHA | // Save value of char | |||
0892 | FF0C A2 01 | LDX | #1 | ||||
0893 | FF0E 4A | LSR | A | // Get top part by multiple shifts | |||
0894 | FF0F 4A | LSR | A | ||||
0895 | FF10 4A | LSR | A | ||||
0896 | FF11 4A | LSR | A | ||||
0897 | FF12 18 | PNT2: | CLC | ||||
0898 | FF13 69 30 | ADC | #$30 | // Add hex 30 | |||
0899 | FF15 C9 3A | CMP | #$3A | // More than 9? | |||
0900 | FF17 30 03 | BMI | PNT1 | // No - then display it | |||
0901 | FF19 18 | CLC | |||||
0902 | FF1A 69 07 | ADC | #7 | // Adjust again | |||
0903 | FF1C 20 75 FE | PNT1: | JSR | OPCHR | // and display it | ||
0904 | FF1F CA | DEX | |||||
0905 | FF20 10 01 | BPL | MOR1 | // -ve? - end else low bit | |||
0906 | FF22 60 | RTS | |||||
0907 | |||||||
0908 | FF23 68 | MOR1: | PLA | // Recover character | |||
0909 | FF24 29 0F | AND | #$0F | // Clear unwanted bits | |||
0910 | FF26 10 EA | BPL | PNT2 | // and branch unconditionally | |||
0911 | |||||||
0912 | |||||||
0913 | |||||||
0914 | // PACK HEX CHARACTERS | ||||||
0915 | // | ||||||
0916 | // This subroutine reads hex characters from the bottom line of the display | ||||||
0917 | // and packs them up into two eight bit binary values. | ||||||
0918 | // On exit, caused by any non-hex character, HXPKL and HXPKH contain a two | ||||||
0919 | // byte number. | ||||||
0920 | // Registers are not saved. On exit IY points to the last character. The zero flag | ||||||
0921 | // is clear if the terminating character was the cursor, else set. The overflow | ||||||
0922 | // flag is set if this subroutine encountered some hex data. | ||||||
0923 | |||||||
0924 | FF28 A9 00 | HEXPCK: | LDA | #0 | // Clear accumulator | ||
0925 | FF2A 48 | PHA | // Push as PSW | ||||
0926 | FF2B 85 13 | STA | HXPKL | // Clear parameters | |||
0927 | FF2D 85 14 | STA | HXPKH | ||||
0928 | FF2F C8 | NXHX: | INY | ||||
0929 | FF30 B1 0A | LDA | (ICURS),Y | // Get character from display | |||
0930 | FF32 AA | TAX | // Save in IX | ||||
0931 | FF33 38 | SEC | |||||
0932 | FF34 E9 30 | SBC | #$30 | // Subtract hex 30 to give 0 to 9 | |||
0933 | FF36 30 10 | BMI | ENDTS | ||||
0934 | FF38 C9 0A | HX1: | CMP | #$0A | // Is it 0 to 9? | ||
0935 | FF3A 30 10 | BMI | HX2 | // Yes - then pack it | |||
0936 | FF3C 38 | SEC | // Else adjust by hex 11 | ||||
0937 | FF3D E9 11 | SBC | #$11 | ||||
0938 | FF3F 30 07 | BMI | ENDTS | // Goto carry setup | |||
0939 | FF41 18 | HX3: | CLC | // Else add 9 | |||
0940 | FF42 69 0A | ADC | #$0A | ||||
0941 | FF44 C9 10 | CMP | #$10 | // If more than 15, then exit | |||
0942 | FF46 30 04 | BMI | HX2 | ||||
0943 | FF48 28 | ENDTS: | PLP | // Deal with V flag | |||
0944 | FF49 E0 FF | CPX | #$FF | // Check if cursor | |||
0945 | FF4B 60 | RTS | |||||
0946 | |||||||
0947 | // Note character is in IX on exit, return does not affect zero flag | ||||||
0948 | |||||||
0949 | FF4C A2 04 | HX2: | LDX | #4 | |||
0950 | FF4E 06 14 | HX5: | ASL | HXPKH | // Shift result left 4 bits | ||
0951 | FF50 06 13 | ASL | HXPKL | ||||
0952 | FF52 90 02 | BCC | HX4 | ||||
0953 | FF54 E6 14 | INC | HXPKH | ||||
0954 | FF56 CA | HX4: | DEX | // Until IX zero (4 times) | |||
0955 | FF57 D0 F5 | BNE | HX5 | ||||
0956 | FF59 18 | CLC | |||||
0957 | FF5A 65 13 | ADC | HXPKL | // Add in character | |||
0958 | FF5C 85 13 | STA | HXPKL | ||||
0959 | FF5E 68 | PLA | // Get pseudo PSW | ||||
0960 | FF5F A9 40 | LDA | #$40 | // Set V bit | |||
0961 | FF61 48 | PHA | // and push it | ||||
0962 | FF62 D0 CB | BNE | NXHX | // Next ... | |||
0963 | |||||||
0964 | |||||||
0965 | |||||||
0966 | // NON-MASKABLE INTERRUPT | ||||||
0967 | // | ||||||
0968 | // This routine handles single instruction mode | ||||||
0969 | |||||||
0970 | FF64 85 1B | NMNT: | STA | ABCK | // Save accumulator | ||
0971 | FF66 D8 | CLD | // Set binary mode | ||||
0972 | FF67 A5 0D | LDA | SINGLE | // Test single instruction mode | |||
0973 | FF69 D0 0A | BNE | NMNT1 | ||||
0974 | FF6B 8A | TXA | // If not save IX | ||||
0975 | FF6C 48 | PHA | |||||
0976 | FF6D 20 D0 FF | JSR | BPSET | // Set breakpoints | |||
0977 | FF70 68 | PLA | // Restore IX | ||||
0978 | FF71 AA | TAX | |||||
0979 | FF72 A5 1B | LDA | ABCK | // Restore accumulator | |||
0980 | FF74 40 | RTI | |||||
0981 | |||||||
0982 | FF75 A5 0E | NMNT1: | LDA | PROCED | // Get proceed count | ||
0983 | FF77 F0 05 | BEQ | ZERBCK | // If zero, then break | |||
0984 | FF79 C6 0E | DEC | PROCED | // else decrement count | |||
0985 | FF7B 4C B9 FC | JMP | SRET | // RTS via single test | |||
0986 | |||||||
0987 | FF7E E6 0C | ZERBCK: | INC | RUNIND | // Set not running | ||
0988 | FF80 68 | PLA | // Pop breakpoint PSW to Acc | ||||
0989 | FF81 85 17 | STA | PSWBCK | // and back it up | |||
0990 | FF83 68 | PLA | |||||
0991 | FF84 85 15 | STA | PCLBCK | // Ditto PCL | |||
0992 | FF86 68 | PLA | |||||
0993 | FF87 85 16 | STA | PCHBCK | // Ditto PCH | |||
0994 | FF89 86 19 | STX | XBCK | // Save IX | |||
0995 | FF8B 84 1A | STY | YBCK | // and IY | |||
0996 | FF8D BA | TSX | |||||
0997 | FF8E 86 18 | STX | SPBCK | // and operators SP | |||
0998 | FF90 20 73 FE | PSEUD: | JSR | OUTPCR | |||
0999 | FF93 A5 16 | LDA | PCHBCK | ||||
1000 | FF95 20 0B FF | JSR | HEXPNT | // Display PC | |||
1001 | FF98 A5 15 | LDA | PCLBCK | ||||
1002 | FF9A 20 0B FF | JSR | HEXPNT | ||||
1003 | FF9D A0 00 | LDY | #0 | ||||
1004 | FF9F A9 20 | PSNX: | LDA | #$20 | // Display two spaces | ||
1005 | FFA1 48 | PHA | |||||
1006 | FFA2 20 75 FE | JSR | OPCHR | ||||
1007 | FFA5 68 | PLA | |||||
1008 | FFA6 20 75 FE | JSR | OPCHR | ||||
1009 | FFA9 B9 17 00 | LDA | PSWBCK,Y | // Then display all registers | |||
1010 | FFAC 20 0B FF | JSR | HEXPNT | ||||
1011 | FFAF C8 | INY | |||||
1012 | FFB0 C0 05 | CPY | #5 | ||||
1013 | FFB2 30 EB | BMI | PSNX | ||||
1014 | FFB4 4C 4B FC | JMP | RC1 | ||||
1015 | |||||||
1016 | |||||||
1017 | |||||||
1018 | // CLEAR BREAKPOINTS | ||||||
1019 | // | ||||||
1020 | // Sets all breakpoint addresses to zero | ||||||
1021 | |||||||
1022 | FFB7 A2 1F | BPTCLR: | LDX | #$1F | // Set count for 8 breakpoints | ||
1023 | FFB9 A9 00 | LDA | #0 | ||||
1024 | FFBB 95 20 | BPTCL1: | STA | BPTLO,X | // Set to zero | ||
1025 | FFBD CA | DEX | |||||
1026 | FFBE 10 FB | BPL | BPTCL1 | // For all locations | |||
1027 | FFC0 60 | RTS | |||||
1028 | |||||||
1029 | |||||||
1030 | |||||||
1031 | // REMOVE BREAKPOINTS | ||||||
1032 | // | ||||||
1033 | // Writes back the user's original code | ||||||
1034 | |||||||
1035 | FFC1 8A | BPTREM: | TXA | ||||
1036 | FFC2 48 | PHA | |||||
1037 | FFC3 A2 0E | LDX | #$0E | // Set count for 8 breakpoints | |||
1038 | BPTRM1: | // | |||||
1039 | #if | TANEX | |||||
1040 | LDA | BPTLO,X | |||||
1041 | ORA | BPTHI,X | |||||
1042 | BEQ | BPTRM2 | |||||
1043 | #endif | ||||||
1044 | FFC5 B5 30 | LDA | BPTCOD,X | // Load saved old instruction | |||
1045 | FFC7 81 20 | STA | (BPTLO,X) | // Write to program memory | |||
1046 | FFC9 CA | BPTRM2: | DEX | ||||
1047 | FFCA CA | DEX | |||||
1048 | FFCB 10 F8 | BPL | BPTRM1 | // For all locations | |||
1049 | FFCD 68 | PLA | |||||
1050 | FFCE AA | TAX | |||||
1051 | FFCF 60 | RTS | |||||
1052 | |||||||
1053 | |||||||
1054 | |||||||
1055 | // SET BREAKPOINTS | ||||||
1056 | // | ||||||
1057 | // Examines entered breakpoint addresses, stores the present instruction | ||||||
1058 | // and writes BRK opcode to program memory | ||||||
1059 | |||||||
1060 | FFD0 A2 0E | BPSET: | LDX | #$0E | // Set count for 8 breakpoints | ||
1061 | BPS1: | // | |||||
1062 | #if | TANEX | |||||
1063 | LDA | BPTHI,X | |||||
1064 | ORA | BPTLO,X | |||||
1065 | BEQ | BPS2 | |||||
1066 | #endif | ||||||
1067 | FFD2 A1 20 | LDA | (BPTLO,X) | // Get user's instruction | |||
1068 | FFD4 95 30 | STA | BPTCOD,X | // Store it | |||
1069 | FFD6 A9 00 | LDA | #0 | ||||
1070 | FFD8 81 20 | STA | (BPTLO,X) | // Set BRK instruction... | |||
1071 | FFDA CA | BPS2: | DEX | ||||
1072 | FFDB CA | DEX | |||||
1073 | FFDC 10 F4 | BPL | BPS1 | // Repeat until done | |||
1074 | FFDE 60 | RTS | |||||
1075 | |||||||
1076 | |||||||
1077 | #if | TANEX | |||||
1078 | // Setup table in low ROM | ||||||
1079 | |||||||
1080 | #else | ||||||
1081 | |||||||
1082 | // SETUP TABLE | ||||||
1083 | // | ||||||
1084 | // Copy in ROM of the initial settings for zero page variables | ||||||
1085 | |||||||
1086 | FFDF 4C C3 FE | SETUP: | JMP | KBINT | |||
1087 | FFE2 4C 64 FF | JMP | NMNT | ||||
1088 | FFE5 E0 03 | FDB | LINBOT | // ICURS setting | |||
1089 | FFE7 01 | FCB | 1 | // RUNIND | |||
1090 | FFE8 00 | FCB | 0 | // SINGLE | |||
1091 | FFE9 00 | FCB | 0 | // PROCED | |||
1092 | FFEA 00 | FCB | 0 | // SIMCOM | |||
1093 | FFEB 40 | FCB | $40 | // Slow Interrupt (RTI instruction) | |||
1094 | |||||||
1095 | #endif | ||||||
1096 | |||||||
1097 | |||||||
1098 | // Header message | ||||||
1099 | |||||||
1100 | FFEC 0D | HDR: | FCB | 13 | // CR | ||
1101 | FFED 54 41 4E | FCC | 'TANBUG' | ||||
1102 | FFF3 0D 00 | FCB | 13, 0 | // CR, end of line terminator | |||
1103 | |||||||
1104 | #if | TANEX | |||||
1105 | NOP | ||||||
1106 | NOP | ||||||
1107 | NOP | ||||||
1108 | #else | ||||||
1109 | FFF5 00 00 | FCB | 0, 0 | // Padding | |||
1110 | #endif | ||||||
1111 | |||||||
1112 | |||||||
1113 | |||||||
1114 | // RESET / INTERRUPT VECTORS | ||||||
1115 | // | ||||||
1116 | // These vectors must appear at the top of the ROM space | ||||||
1117 | |||||||
1118 | FFF7 4C 89 FC | JMP | RETERR | // $FFF7, also mapped to $F7F7 | |||
1119 | FFFA 07 00 | FDB | NMIJP | // Non Maskable Interrupt vector | |||
1120 | FFFC 00 FC | FDB | START | // Reset vector | |||
1121 | FFFE 04 00 | FDB | INTFS1 | // Interrupt vector | |||
1122 | |||||||
1123 | END | ||||||
1124 |
Assembly generated 0 errors
Assembly generated 0 warnings
DEBUG:
Assembly processed in 62 ms
Number of opcodes & directives is: 76