A.N.A.L.O.G. ISSUE 39 / FEBRUARY 1986 / PAGE 53
Debug+ is a screen-oriented machine language debugging utility. It contains a program tracer that can step through almost any machine language program in three different ways. Debug+ also has a complete scrolling disassembler and memory “dumper.” It allows user program execution and can perform binary SAVEs and LOADs, plus many, many more functions. Sound too good to be true for a magazine program? Well, it’s not. Read on!
Before you start typing anything, examine the listings accompanying this article. Listing 1 is the main data and data checking routine, written in Atari BASIC. This program will create a file called DEBUG.COM. Follow the instructions below to create the DEBUG.COM file.
To LOAD Debug+ from Atari DOS 2.0S, go to DOS and type:
L DEBUG.COM
Debug+ will LOAD and RUN automatically.
For those interested in assembly language, the OSS MAC/65 source code for Debug+ is available on the ANALOG Computing TCS and is included on the disk version of this issue.
Remember, you must have the BASIC cartridge removed for Debug+ to LOAD. For XL owners, this means you must boot up while holding dawn the OPTION key.
The program resides in cartridge slot A memory locations ($A100–$C0FF) and uses addresses $BE00–$C0FF as screen memory. The program supports eighteen commands, which are listed below:
Key Function * Address Set D Display Toggle Q Quit DEBUG+, go to DOS G Go at address T Trace program P Print Disassembly E Erase Memory C Change 1 byte of RAM N Change Register Value R Display Registers B Set/Reset Break Point S Save a binary file L Load a binary file F Find a string in memory H High Speed Display " Dec/Hex, Hex/Dec convert - Scroll up in memory = Scroll down in memory
Before I explain all the functions, I’d like to tell you about the prompts that Debug+ uses. There are three basic prompts: *, ? and (opt1,opt2,opt3)?
When the * appears, in the input window, Debug+ expects a number This number may be entered in either hexadecimal or decimal. To enter a decimal number, the digits in the number must be preceded by a decimal point (a period). If the number is not preceded by a period, Debug+ will interpret it as hexadecimal. If there are any “illegal” digits in the number, Debug+ will respond with a short tone, and the command will be aborted.
When the ? appears. Debug+ expects a string of characters, a filename, for example, with a maximum of twelve characters. When you reach the maximum input length, all extra characters (except DELETE, SHIFT-DELETE and RETURN) will overwrite the previous twelfth character. (I know that’s hard to understand. Try it; you’ll see what I mean.)
The final general prompt is (opt1,opt2,opt3)? When this appears in the input window. Debug+ wants you to press one of the keys separated by commas inside the parentheses. An example of this is (D,P)? This asks you what device you want to use, the disk or printer. Pressing D specifies disk, and so on.
Debug+ has two memory display modes: disassembly and memory dump.
A disassembled line looks like this:
ADDR OP B1 B1 xMNE
where ADDR is the address, OP is the op code, B1 and B2 are the operands, and xMNE is the mnemonics. The X indicates the direction of a relative instruction (branch instruction). If the arrow points up, it’s a backwards branch; and if the arrow points down, it’s a forward branch.
A memory dumped line looks like this:
ADDR B1 B2 B3 B4 B5 B6 123456
where ADDR is the address, B1-B6 are the values in the locations, and 1-6 are the ATASCII character representations of the values.
To use one of the commands in the table printed at left, just press the key on the keyboard which corresponds to the character listed under “key.” For instance, to update the register display line, just press the R key.
Address set (*). This is how you tell Debug+ where your disassembly or memory dump will begin. After entering your address, Debug+ will display the contents of the specified location.
Display toggle (D). This command will flip the screen between disassembly and memory dump, and vice versa.
Quit DEBUG+ (Q). This command returns you to DOS. To re-enter Debug+ from DOS, do a RUN AT ADDRESS, with the address being A100. To do this from OSS OS/A+, type RUN A100 and press RETURN. From Atari DOS 2.0S, type M, hit RETURN, then type A100 and hit RETURN.
Go at address (G). When this command is entered, the 6502 registers are loaded with the contents of the user registers, then program execution begins at the address specified.
The user program will continue to execute until it is stopped by a 6502 BRK instruction, one of the break points, or by your pressing CTRL-ESC (the CONTROL and ESCape keys at the same time).
If one of these events occurs, your program will be interrupted, the 6502 registers will be saved in the user registers, and Debug+ will take control. Then the location where the program was stopped will be disassembled or dumped on the screen, and the register line will be updated with the contents of the user registers.
Trace program (T). When trace is activated, Debug+ will ask for the starting address, then begin executing the code at the given location, one instruction at a time. You’ll be asked to specify the speed of the trace in the prompt (F,S,O)? If you press F, then the trace will be as fast as possible; the S key will pause one-quarter of a second between each instruction; and the O key will cause the trace to be stepped by pressing the OPTION key
A trace will be aborted if the tracer finds: (1) a 6502 BRK instruction, (2) a break point, (3) an illegal instruction, and (4) by pressing the ESC key. Note: if you’re using the stepped mode, you must hold down OPTION and press ESC to abort. The trace can be paused by pressing the SPACE BAR.
The tracer does have some limitations. First, it cannot trace itself, so never try to trace Debug+. Second, any attempt to trace the realtime I/O routines (such as disk or cassette access) will almost certainly fail.
During a trace, the user register line will be updated before and after the execution of each instruction, so you can examine the register contents at any time.
Print disassembly (P). When this command is executed, you’re asked what device the output will go to (disk or printer) and what the starting address is. If disk output is chosen, a filename will be asked for, then disassembly will begin. During the process, the address just sent out to the device is displayed on the STAT line. To abort this command during execution, press any key.
If you choose the disk as the output device, Debug+ will create a text file of the disassembly. You can then load this into a word processor or other text editor, and edit the disassembly.
Erase memory (E). When this command is executed, you’ll be asked for a starting and ending address of the erase. After this, the memory between and including those addresses will be erased. Debug+ will fill all those addresses with zeroes (the 6502 BRK instruction). If the end address is smaller than the start address, you’ll be given an ADDRESS RANGE ERROR, and the command will be aborted.
Change one byte of RAM (C). When you enter this command, you’ll be asked what address to change and what to change it to. At this point the contents of that memory location are changed. This is similar to the BASIC POKE statement.
Make sure that you don’t change any of the memory that Debug+ uses. Also, careless choice of a change address may wipe out vital system data and cause a complete system lock-up. Take care.
Change register value (N). When this command is entered, you’ll be asked what register to change. To choose the register, simply press one of the following keys: A for Accumulator, X for X-Register, Y for Y Register, S for Stack Pointer, or P for Processor Status.
Next, you’ll be asked the new value. Enter this, and the register contents will be changed. Notice that the register line on the screen has been updated to reflect the new value.
A note about the register line. If you examine the line on the screen, you’ll see five small boxes and one large box, labelled NV_BDIZC. Under the label, there will be eight binary digits. This is the processor status, broken down into its flags. The following table tells you what each flag is:
N = Negative number flag. V = Overflow flag. _ = Unused (always shown as set). B = BRK instruction flag. D = Decimal flag. I = Interrupt flag. Z = Zero flag. C = Carry flag.
If a 1 appears under one of these flags, it indicates a “set” or “true” condition. So, if the I bit is 1, then an interrupt is occurring.
Display registers (R). All this command does is update the register line. It will display the current values of the user registers.
Set/Reset a break point (B). A break point will stop the execution (or trace) of a user program. When you enter this command, a B will appear in the input window, indicating that you must either set or reset a break point.
Setting a break point is easy. Simply type the break point number (a single digit between 1 and 6), followed by a comma, then the address where you wish the break point to be. A typical line would look like this: B1,0600[RETURN]. This tells Debug+ to set break point number 1 at location $0600 (or 1536 decimal). If break point number 1 is already set, you’ll be given an error. If location $0600 contains a BRK instruction, you will also get an error. All 6502 BRK instructions are considered break points.
When you disassemble the address where a break point is set, the mnemonics will be shown in inverse video. This is how Debug+ graphically shows the user where break points are. If you’re in memory dump mode, the value for the address where the break point is set is also in inverse video.
Resetting a break point is easier than setting one. At the B prompt, simply enter the break point number you want to reset, followed by a RETURN. An example would be B1[RETURN]. This will reset break point number 1. If it was not set, you’ll get an error.
When a break point is reset, the old opcode is restored at the break point address, and the address for the break point is reset to $0000. If you look at the break point line at the bottom of the screen when you load Debug+, you’ll notice that the addresses of all the break points are 0, and that there are six free break points.
Save a binary file (S). This command allows you to save a single-stage binary file to disk. You’ll be prompted to enter a filename, followed by the starting and ending addresses of the save. Once again, if the ending address is less than the starting address, you’ll be given an error. The file created with this function can be loaded from DOS. You cannot specify a run address for the file from Debug+, so you may want to append one to the file from BASIC or DOS.
Load a binary file (L). This will load any binary file into memory. Debug+ will not run this file. After you enter the load filename, Debug+ will load the file into memory, then the initial load address will be displayed on the STAT line.
Find a string in memory (F). This command will locate all matches of any string—up to twelve characters in length—in memory. You’ll be asked to enter the string you want to find and press RETURN. Debug+ will clear the screen, and every match of what you typed in will be displayed on the screen, in this format:
FIND # nn Hexadr Decadr
where nn is the find number, and Hexadr and Decadr are the hex and decimal address of the find. The search will continue until the end of memory is reached (address $FFFF or 65535 decimal).
You may find it useful to begin the find at a specific address. To do this, terminate your string with a comma. Debug+ will ask you what address to start from, and the search will begin as described above.
Debug+ has certain “reserved” characters that cannot be entered into your input and consequently can’t be searched for. They are: (1) RETURN (ATASCII 155), (2) DELETE (ATASCII 126), (3) SHIFT-DELETE or DELETE LINE (ATASCII 156), and (4) ESC (ATASCII 27).
All these characters are used by Debug+ as either delimiters or cursor controls. However, all other control characters and alpha-numerics are at your disposal. One other thing: if you wish to search for a character that you usually generate by pressing ESC, then the key (such as clear screen—CTRL-CLEAR), enter it without pressing ESC. So, to enter the clear screen character, just press CTRL-CLEAR.
High speed display (H). This command will continually scroll the display through memory. You’ll be asked what direction to scroll in—up or down—then the scrolling will begin. Use this command if you want to get somewhere very fast, since the screen will move at blinding speed. To pause the scroll, press SPACE; to abort scrolling, press ESC.
Decimal/Hex and Hex/Decimal conversions (.). This command will convert one number base to the other and display the results on the STAT Hue. If a hexadecimal number is entered, a decimal number will be generated, and vice versa. After the number to be converted has been entered, the STAT line will look like this: nnnn = xxxx, where nnnn is what you typed, and xxxx is its converted form.
Scroll up in memory (-). When you press the hyphen key, Debug+ will move the display window up 1 byte in memory. If you’re in memory dump, Debug+ will move the window up 6 bytes in memory.
You may notice that it will usually take several keypresses to scroll up one instruction in memory. This is because Debug+ has no idea where the previous instruction starts, or how many bytes long it is. When this command is executed, the addresses will get lower.
Scroll down in memory (=). This command will move the display window down one full instruction in memory (or 6 bytes in dump mode). When scrolling down. Debug+ knows where the next instruction starts. That’s why it can move down one full instruction. When using this command, addresses in the display window will get higher.
Well, that’s about everything you can do with Debug+. Now let me tell you what you can’t do.
Well, that’s it. Debug+ will run as advertised, unless you break one of the rules I’ve outlined above. It should prove to be an invaluable aid to you in debugging machine language programs.
10 REM *** DEBUG+ *** 20 DIM ML$(151),DAT$(91),BIN$(45):BIN$(45)=" ":TOTAL=0:PASS=TOTAL:LINE=990:? ".CHECKING DATA":POKE 752,1 30 FOR X=1 TO 135:READ N:ML$(X)=CHR$(N ):NEXT X:ML$(136)="0123456789ABCDEF":X =ADR(ML$)+135:N=INT(X/256) 40 ML$(42,42)=CHR$(N):N=X−N*256:ML$(41 ,41)=CHR$(N):RESTORE 1000 50 TRAP 110:LINE=LINE+10:POSITION 2,2: ? "LINE: ";LINE:READ DAT$:IF LEN(DAT$) <>90 THEN 160 60 DATLIN=PEEK(183)+PEEK(184)*256:IF D ATLIN<>LINE THEN ? "LINE ";LINE;" MISS ING!":POKE 752,0:END 70 TOTAL=USR(ADR(ML$),ADR(DAT$),ADR(BI N$),LEN(DAT$),TOTAL):IF TOTAL=65535 TH EN 160 80 IF PASS=2 THEN ? #1;BIN$;:READ CHKS UM:GOTO 50 90 READ CHKSUM:IF TOTAL=CHKSUM THEN 50 100 GOTO 160 110 IF PEEK(195)<>6 THEN 160 120 IF PASS=2 THEN PUT #1,224:PUT #1,2 :PUT #1,225:PUT #1,2:PUT #1,Z:PUT #1,1 61:CLOSE #1:POKE 752,Z:END 130 ? "INSERT DISK WITH DOS, PRESS RET URN":INPUT #16,DAT$:OPEN #1,8,Z,"D:DEB UG.COM" 140 PUT #1,255:PUT #1,255:PUT #1,Z:PUT #1,161:PUT #1,51:PUT #1,184 150 ? ".WRITING FILE":PASS=2:LINE=990: RESTORE 1000:TRAP 110:GOTO 50 160 READ CHKSUM:? :? "BAD DATA":? :? L INE;" DATA ";DAT$;",";CHKSUM:POKE 752, 0:END 170 DATA 104,104,133,204,104,133,203 180 DATA 104,133,206,104,133,205,104 190 DATA 104,133,207,104,133,213,104 200 DATA 133,212,216,160,0,132,210 210 DATA 162,1,134,208,202,134,209,177 220 DATA 203,162,15,221,0,0,240,5,202 230 DATA 16,248,48,75,6,209,6,209,6 240 DATA 209,6,209,138,5,209,133,209 250 DATA 200,198,208,16,224,132,208 260 DATA 164,210,165,209,145,205,164 270 DATA 208,230,210,165,212,24,101 280 DATA 209,133,212,144,2,230,213 290 DATA 165,213,201,4,176,10,201,3 300 DATA 144,19,165,212,201,232,144 310 DATA 13,165,212,56,233,232,133,212 320 DATA 165,213,233,3,133,213,196,207 330 DATA 208,161,96,9,128,145,203,169 340 DATA 255,133,212,133,213,96 1000 DATA D8A50C8D16A2A50D8D17A2AD0802 8D5EB2AD09028D5FB2AD06028D55B2AD07028D 56B2A579057AF00AA5798D9F,837 1010 DATA A9A57A8DA0A9D8A2008E57B28E44 02868D8E0ED486B1E886B286B6BA8EB9B3A9E0 8DF402A9A0856A78A9EB8D06,285 1020 DATA 02A9A68D0702A9598D0802A9A78D 0902A915850CA9A2850D58A200B5009D5AB8BD 00019D5AB9BD00029D5ABAE8,821 1030 DATA D0EC201BA2ADBBB385D4ADBCB385 D520F4A3A9408D0ED42045AE208BA7203AAE20 31AE2029AD2080A92089A929,381 1040 DATA 7FA211DDD8B1F009CA10F82070A2 4CA4A18A0AAABDEAB18DDEA1BDEBB18DDFA120 E5A8204CAC2080A920FFFF4C,947 1050 DATA A4A1A907A062A2E4205CE4AD55B2 8D0602AD56B28D0702AD16A2850CAD17A2850D 78AD5EB28D0802AD5FB28D09,938 1060 DATA 025868686C0A0020FFFF4C33A1A9 008DC602A90A8DC502A9928DC802203DA8A96C 8D3002A9B28D3102A9218D2F,529 1070 DATA 02A907A016A2A74C5CE4A220A90C 9D42034C56E4A90085D485D56085A484A5201E A9A000B1A4C99BF008201DA8,720 1080 DATA 91A2C8D0F2E65460A9648D00D2A9 AA8D01D2A9008514A514C905D0FAA2008E01D2 8E00D2602031AE203AAEA90A,230 1090 DATA 8D1EB3204FA89003686860A000A2 008690B923B8C92ED005E690C8D03D204FA285 88B923B8C99BD00160A20FDD,622 1100 DATA 7BB4F008CA10F868684C70A206D4 26D506D426D506D426D506D426D58A05D485D4 E688A588C905B0DEC84CB7A2,665 1110 DATA 204FA28588B923B8C99BD022A900 85F28489A98085F3A90585F4A688A99B9D8005 2000D8B01220D2D9B00DA489,553 1120 DATA 60A209DD7BB4F008CA10F868684C 70A2C8A6889D8005E6884CF4A2A2008690E886 8420E0A6A58585D4A58685D5,904 1130 DATA A2002060A6A99B8D41B8A0008489 204FA2A8B18585832051A9A58385D4A489C99B F003993AB820B6A6A59EF00D,692 1140 DATA A001B9820509809982058810F5A4 89BE28B2AD82059D23B8AD83059D24B820BBA4 C8C006D0B960208DA2A5D485,189 1150 DATA 8AA5D5858B208DA2A5D4A000918A 60208DA26868A5D48DBBB3A5D58DBCB378A200 BD5AB89500BD5AB99D0001BD,246 1160 DATA 5ABA9D0002E8D0EC58AEB9B39AAD BAB348AEB7B3ACB8B3ADB6B3EE57B2286CBBB3 208DA2A5D4858585A6A5D585,157 1170 DATA 8685A7A90085542076A9201EA9A0 1EB923B8C99BD002A920201DA891A28810EFE6 54A554C901D008A58585A8A5,560 1180 DATA 8685A9A554C90ED0D160A00084A1 8490B18585832051A9A583A000D95CB6F005C8 C097D0F684B020E0A6A58585,908 1190 DATA D4A58685D5A2002060A6204FA2A5 8385D4A2062060A6A4B0BEF3B6A000BDB1B599 35B8E8C8C003D0F4A0018484,153 1200 DATA B1858581C8B1858582A4B0B98BB7 0AA8B90EB28DA1A4B90FB28DA2A420FFFFA027 B923B8C920D0038810F6A99B,522 1210 DATA 9924B8A59EF00320C9A4A5851865 848585A5866900858660A012B923B849809923 B8C8C015D0F36020CAA5A923,164 1220 DATA 8D39B8A9008582A58185D4A58285 D5A2174C60A620CAA54CE1A420CAA520E1A4A0 01E8B9A5B49D24B8CA8810F6,365 1230 DATA 6020CAA520D8A54CE5A4200CA54C FEA4200CA5A92C9D24B8A9599D25B860A90085 8220CAA520E6A5E8A002D0C8,36 1240 DATA A900858220CAA520E6A5A002B9A8 B49D24B8E88810F660A9418D39B86020CAA5E6 84204FA2E6A1A91D8D34B8A5,969 1250 DATA 811012CE34B8297F497F18690185 9B38E9024C7CA5859BA5811010A58538E59B85 D4A586E90085D54C9BA51865,112 1260 DATA 8585D4A586690085D5A9021865D4 85D4859FA5D5690085D585A020EDA4C6846020 CAA520D8A520E6A5A9299D24,108 1270 DATA B86020CAA520E1A44C1EA5E68420 4FA2A58185D4A20A4C60A6E684204FA2A58285 D4A20E4C60A6A9288D39B84C,719 1280 DATA E5A4204FA284D484AD2070A220E0 A620AAD920E6D8A0FFA2FFC8E8B1F39D23B810 F7297F9D23B8A99B9D24B886,361 1290 DATA 87A211BDFFB3C5ADF005CA10F630 2A8A0AAABD12B48582BD11B48581A0FFA687A9 2C9D24B8E8C8E8B1819D24B8,736 1300 DATA 10F7297F9D24B8A99B9D25B8A90E 855420E5A8A923A0B84C56A2CA868CA590F019 20AAD920E6D8A68CA0FFC8E8,47 1310 DATA B1F39D23B810F7297F9D23B86020 B6A6A68CE8F01EE014B00EAD82059D23B8E8AD 83059D23B860A9249D23B8E8,878 1320 DATA A584C902F0E6A000B980059D23B8 E8C8C004D0F4CA60A000A2018691A9F035D44A 4A4A4AAABD7BB4998005C8A6,966 1330 DATA 91A90F35D4AABD7BB4998005C8A6 91CA10DB60A920A2279D23B8CA10FA60AD57B2 D0026840D88EB7B38CB8B368,37 1340 DATA 8DB6B3688DBAB36838E9028DBBB3 68E9008DBCB3BA8EB9B3584C4AA7EE6EB8D008 EE6DB8D003EE6CB8A5B2D020,596 1350 DATA AD2B02F008A93F85B4A93C85B3A5 B4C6B3D008A01E84B3493F85B4A4879920B34C 62E408AA6829EF4828A9008D,85 1360 DATA 57B24C33A1AD57B2F02AAD09D2C9 9CD0238CB8B38EB7B3A9FF8DFC02688DB6B368 8DBAB3688DBBB3688DBCB3BA,801 1370 DATA 8EB9B3584C4AA76C5EB2A0008489 204FA2B9B6B385D420B6A6A489BE50B2AD8205 38E9209DF6B2AD830538E920,654 1380 DATA 9DF7B2C8C004D0D7ADBBB385D4AD BCB385D520B6A6A003B9800538E92099F6B288 10F4A211A007ADBAB339C7B3,299 1390 DATA F004A911D002A9109DF6B2E88810 EBA9118D09B360A007B949B4991EB38810F720 89A9A004D962B4F0058810F8,943 1400 DATA 30F1980AA8B9BDB385D4B9BEB385 D520A0A34C8BA7202FA81DCFB3A6AA60202FA8 1DD3B3A6AA60482A2A2A2A29,570 1410 DATA 0386AAAA68299F60A900AA9D00BD 9D00BE9D00BFE8D0F4855460A900858785B220 3AAE20E0A62089A9C91BD004,36 1420 DATA E6B23860A48DD010A028D976B4F0 098810F82070A24C5BA8C97ED024C6871007A9 0085872070A220DAA8A587F0,758 1430 DATA CBA487C00CD00188A9009920B399 21B34C5BA8C99CF0A9A4879923B8C99BF01920 1DA8C00CD001889920B3C8C0,634 1440 DATA 0D900188848720DAA84C5BA8AD23 B8C99BF080A900858D9920B3E6B21860A587D0 068D20B38D21B360A017A900,66 1450 DATA 993EB38810FA60A909A2209D4203 A9239D4403A9B89D4503A9289D4803A9009D49 03AD3AB8100320C9A42056E4,590 1460 DATA 30016068684C45A2A5540AAABD2E B285A2BD2FB285A360A5B1490185B1D008A901 85B6A921D006A90685B6A930,743 1470 DATA 8D13B3A5A685D4A5A785D54CF4A3 A900859EA005A586D9DDB3D014A585D9D7B3D0 0DB9E9B3F008B9E3B38583E6,748 1480 DATA 9E608810E260A5B1D0034C34A44C 37A3A90085B9A94085BA60ADFC02C9FFF0F9A2 FF8EFC0285B7A8C0C09002A0,109 1490 DATA 9AB9FEFE85B8C980F0E2C981D009 A5B9498085B94C89A9C982D009A5BA494085BA 4C89A9C983D006A94085BAD0,909 1500 DATA BEC984D006A98085BAD0B4C985F0 B0A5B7C940B013A5B8C961900DC97BB009A5BA F00505B74C97A9A20FBDEFB3,485 1510 DATA C5B8F003CA10F6F006A5B845B985 B860A9008514A514C90FD0FA60AEB9B3E8BD5A B98585E8BD5AB985868EB9B3,81 1520 DATA 4CBBA4A58538E90148A586E900AE B9B39D5AB9CA689D5AB9CA8EB9B3A001B1AE85 85C8B1AE858660208DA2A5D4,520 1530 DATA 8585A5D58586203AAEA007B941B4 991EB38810F784802089A9C946D004E680F00C C953F008C94FD0EDA9018580,432 1540 DATA 203DA8203AAE2031AEA5858DBBB3 85AEA5868DBCB385AF2034A420F7ACA002A9EA 99A5AB8810FA2007AD208BA7,144 1550 DATA AD35B8100A20F2ACA967A0B44C56 A2C93FD005A0974CEEA5A583C960D0062012AA 4CF3ABC940D01EAEB9B3EEB9,210 1560 DATA B3BD5AB98DBAB3E8BD5AB98585E8 BD5AB985868EB9B34CF3ABC94CD0062040AA4C F3ABC920D0062027AA4CF3AB,705 1570 DATA C96CD0132040AAA000B18548C8B1 8585866885854CF3ABA5A1F02FA583A003D960 B2F01BD964B2F0038810F3AD,822 1580 DATA BAB33968B2F008A59F8585A5A085 864CF3ABADBAB33968B2F0ED4CF3ABA000B1AE 99A5ABC8C484D0F6A9008D0E,596 1590 DATA D478A200B500A8BD5AB89500989D 5AB8BD0001A8BD5AB99D0001989D5AB9BD0002 A8BD5ABA9D0002989D5ABAE8,998 1600 DATA D0D5BA8AAEB9B39A8DB9B3ACB8B3 AEB7B3ADBAB348ADB6B328EAEAEA088DB6B368 8DBAB38EB7B38CB8B3BA8AAE,522 1610 DATA B9B39A8DB9B378A200B500A8BD5A B89500989D5AB8BD0001A8BD5AB99D0001989D 5AB9BD0002A8BD5ABA9D0002,918 1620 DATA 989D5ABAE8D0D558A9408D0ED420 8BA7A5803013F014A2088E1FD0AD1FD0C903D0 F98E1FD0D0032007AA4C87AA,608 1630 DATA A90085A4A9BD85A5A5A418692085 81A5A569008582A200A01FB18191A48810F9A5 8285A5A58185A41869208581,156 1640 DATA A58269008582E8E00ED0DF60A017 A900995EB38810FA60A59085B0A9038584208D A2A9209923B89925B8A93DC8,859 1650 DATA 9923B8C884AAA59049018590A21C 2060A68687A21CA4AABD23B89924B8E487F004 E8C8D0F2A99B9925B820F2AC,84 1660 DATA A5B085904C59A6208DA2A5D48592 A5D58593208DA2A000A5D5C5939023D008A5D4 C592901BF015989192E692D0,473 1670 DATA 02E693A5D5C593D0F1A5D4C592D0 EB98919260A0994CEEA585818482A000B18199 1EB3C91FF003C8D0F460A90F,276 1680 DATA 855460A554C90ED0072013ACA90D 85544C59A6ADFC02C9FFF01B2029ADC91CF012 C921D0102029ADADFC02C921,469 1690 DATA F006C91CD0F5686848A9FF8DFC02 6860A93BA0B420DFAC2089A9C955D006A90185 BBD008C944D0EFA90085BB20,472 1700 DATA 31AE203AAE2007ADA5BBF0062021 AE4C53AD20D1AD4C53AD201DB1208DA2A90820 F2B0A5D48585A5D585862034,658 1710 DATA A4A9208D34B8AD35B8100320C9A4 20F0A8204CAC20F2ACA99B8D29B82059A6ADFC 02C9FFF0D82029AD204CAC4C,310 1720 DATA 45A2203AAEA935A0B420DFAC2089 A9C91BD0056868686860A001D951B4F0098810 F82070A24CB4AD60A2008A0A,514 1730 DATA A8B92EB2858EB92FB2858FA000B1 8EF030E8E00ED0E82076A920FDACA201BD00BD 2026A8C920F0069D22B8E8D0,578 1740 DATA F0A99B9D22B8A00020B2A2A5D485 A6A5D585A760A5A885D4A5A985D54CF4A3A5A6 38E5B685D4A5A7E90085D54C,470 1750 DATA F4A3A9008D1EB38D1FB360A014A9 009920B38810FA60A00084B58489B9D7B385D4 B9DDB385D520B6A6A489BE58,610 1760 DATA B2A000B9800538E9209D96B3E8C8 C004D0F1A489B9E9B3D002E6B5C8C006D0CDA5 B51869108DB5B3602031AEA9,992 1770 DATA 228D1EB3204FA8900160AD23B838 E931AAC906B024C9009020AD24B8C99BF034A0 02868C20A2A2A68CA000B1D4,280 1780 DATA F005BDE9B3F008A0984CEEA54C70 A2A5D49DD7B3A5D59DDDB3B1D49DE3B39891D4 FEE9B34C45AE2031AEA000BD,428 1790 DATA E9B3F01CBDD7B38581BDDDB38582 BDE3B39181989DE9B39DD7B39DDDB34C45AEA0 964CEEA52031AEA91F8D1EB3,416 1800 DATA 858D204FA8900160A000B923B8C9 9BF00CC92CF008994BB8C8C00CD0ED8480C92C D014208DA2A5D438E9018592,150 1810 DATA A5D5E9008593A0FFD006A0FF8492 8493C8849C84948495203DA8A5921869018592 A59369008593C9B8D00EA592,287 1820 DATA C923D008A95A8592A9BB8593A59C F007A5920593D00160A001849C88B192D94BB8 D0CAC8C480D0F420E0A6A205,608 1830 DATA BD9FB49D23B8CA10F7A59285D4A5 9385D520B6A6A003A211B980059D23B8CA8810 F6A9249D23B8A99B8D35B8E6,820 1840 DATA 94D002E695A59485D4A59585D5A2 0786902060A62007AD20F7AC4C57AFA9442020 B1A9008580A907859DA90420,196 1850 DATA F2B02077B0300EAD4EB2C9FFD005 CD4FB2F00CA09584892045A2A4894CEEA52077 B0A580D00CAD4EB285D4AD4F,302 1860 DATA B285D5E68020D6B020C0B02077B0 20CBB020A5B020E7B030034C10B098482045A2 68C988D02F20E0A6A006B9AB,2 1870 DATA B49923B88810F720B6A6A003A20C B980059D23B8CA8810F6A9249D23B8A99B8D30 B820F2AC4C59A6A84CEEA5A9,835 1880 DATA 4E8592A9B28593A9008599A90285 98A220A59D9D4203A5929D4403A5939D4503A5 989D4803A5999D49034C56E4,42 1890 DATA A59638E5948598A597E5958599A5 981869018598A5996900859960AD4EB28594AD 4FB2859560AD4EB28596AD4F,74 1900 DATA B2859760AE4EB2E8F00160AE4FB2 E8F001604C77B0A5948592A59585934C87B085 9C2045A2A59CA2209D4A03A9,45 1910 DATA 009D4B03A9039D4203A9539D4403 A9B49D45032056E430016068684CEEA520AAAD 488D53B4A99B8D55B468C944,868 1920 DATA F001602031AEA91F8D1EB3204FA8 9003686860A202A000B923B8C92CF014C99BF0 109D53B4C8E8E012D0ECA0A5,448 1930 DATA 68684CEEA5A99B9D53B460A94420 20B1A90B859D208DA2A5D48594A5D58595208D A2A5D48596A5D58597C59590,723 1940 DATA 45F002D006A596C594903BA90820 F2B0A9FF8D4EB28D4FB22077B0302BA5948D4E B2A5958D4FB22077B0301CA5,365 1950 DATA 968D4EB2A5978D4FB22077B0300D 20A5B020E7B030054C45A2A09998482045A268 A84CEEA55144524E2A43474C,302 1960 DATA 5342542D3D4650482E45E3A12DA9 8BA7F0A7F1A39DA3B2A3E1AF64B185AE4CAA21 AED1AD08AF66AD31AD57ACA1,277 1970 DATA ACD9A4F2A4F8A40CA515A51BA529 A538A54FA555A5B1A5B2A5C1A505080B0E1114 01BD21BD41BD61BD81BDA1BD,862 1980 DATA C1BDE1BD01BE21BE41BE61BE81BE A1BE3EB35EB3000005080B0E1100000000050A 0F14190000105090D03070B0,712 1990 DATA F0804001027070704296B2000220 4200BD020202020202020202020202022042D6 B20200020002000200020241,759 2000 DATA 6CB28080A4A5A2B5A78B80808080 E2F99A80A2F2F9E1EE80B3E3E8E1F0F0E5EC80 8080A1A4A4B28080A2918080,470 2010 DATA A2928080A2938080ADAEA5ADAFAE A9A3B3808080808080B0A3FC80A1FC80B8FC80 B9FCB3B0FCAEB6BFA2A4A9BA,8 2020 DATA A3FCADAFA4A58080000000007C00 007C00007C00007C00007C0000000000000000 7C24293321000080A9AEB0B5,89 2030 DATA B49A000000000000000000000000 0000000000000000000000000080A5B2B2AFB2 9A0000000000000000000000,579 2040 DATA 0000000000000000000000000000 8080B3B4A1B49A000000000000000000000000 000000000000000000000000,689 2050 DATA 00A2B2AB91FCA2B2AB92FCA2B2AB 93FCA2B2AB94FCA2B2AB95FCA2B2AB96FCA6B2 000000007C000000007C0000,744 2060 DATA 00007C000000007C000000007C00 0000007C101000000000000000B6B3B7B3B8B3 B9B3BAB30102040810204080,342 2070 DATA 4000206020400060000000000000 000000000000000000000000000000000000FF FEFD9F9E9D9C9B7F7E7D1F1E,712 2080 DATA 1D1C1B8082898A8B9092A2A4A5A7 A9AA9596979899B2B4C1B4D2B4E2B4F0B4FAB4 09B51AB523B534B541B54CB5,236 2090 DATA 5AB568B577B587B595B5A2B50824 0C30091F08350C24091F08330C260C2F091F08 2138393330091F4450203A20,145 2100 DATA 20202020202020202020209B4158 59535042524B20504F494E5420464F554E449B 9C7E2C2E3031323334353637,57 2110 DATA 38394142434445464748494A4B4C 4D4E4F505152535455565758595A46494E4420 232C5829592C294C4F414420,208 2120 DATA 4154425245414B204B4559204142 4F52D44E4F204445564943452048414E444C45 D25452554E43415445442052,602 2130 DATA 45434F52C4444556494345205449 4D454F55D4444556494345204E41CB57524954 452050524F5445435445C446,355 2140 DATA 554E4354494F4E204E4F5420444F 4EC54449534B2046554CCC46494C45204E554D 204D49534D415443C8424144,909 2150 DATA 2046494C45204E414DC546494C45 204C4F434B45C44449524543544F5259204655 4CCC46494C45204E4F542046,383 2160 DATA 4F554EC446494C45204E4F542042 494E4152D94E4F205345542042524B20504F49 4ED4494E56414C4944204F50,939 2170 DATA 434F44C542524B20504F494E5420 5345D44144522052414E4745204552524FD241 4443414E4441534C42434342,462 2180 DATA 4353424551424954424D49424E45 42504CC2D2CB425643425653434C43434C4443 4C49434C56434D5043505843,155 2190 DATA 5059444543444558444559454F52 494E43494E58494E594A4D504A53524C44414C 44584C44594C53524E4F504F,607 2200 DATA 5241504841504850504C41504C50 524F4C524F5252544952545353424353454353 454453454953544153545853,78 2210 DATA 5459544158544159545358545841 5458535459413F3F3F6965756D7D7961712925 352D3D3921310A06160E1E90,390 2220 DATA B0F0242C30D01000507018D858B8 C9C5D5CDDDD9C1D1E0E4ECC0C4CCC6D6CEDECA 884945554D5D594151E6F6EE,322 2230 DATA FEE8C84C6C20A9A5B5ADBDB9A1B1 A2A6B6AEBEA0A4B4ACBC4A46564E5EEA090515 0D1D190111480868282A2636,476 2240 DATA 2E3E6A66766E7E4060E9E5F5EDFD F9E1F138F87885958D9D99819186968E84948C AAA8BA8A9A98000000000000,463 2250 DATA 0000030303030303030306060606 06090C0F121215181B1E2124272A2D30333333 33333333333636363939393C,735 2260 DATA 3C3C3C3F42454545454545454548 4848484B4E51515457575757575757575A5A5A 5A5A5D5D5D5D5D6060606060,374 2270 DATA 636666666666666666696C6F7275 7575757578787878787B7E8181818181818181 84878A8D8D8D8D8D8D8D9090,873 2280 DATA 9093939396999C9FA2A5A8000102 03040506070001020304050607080102030409 090901030909090A09090A0A,751 2290 DATA 0A0A000102030405060700010300 0103010203040A0A0001020304050607010203 040A0A030B03000102030405,927 2300 DATA 060700010C030500010203040801 0203040A00010203040506070A0A0A0A080102 030408010203040A0A000102,126 2310 DATA 03040506070A0A0A010203040506 07010C030102030A0A0A0A0A0A0A0000000000 000000000000000000000000,301 2320 REM * 5940 BYTES
; DEBUG+ ; ;This is an all machine ;language disassembler and ;program tracer written with ;OSS MAC/65. ; ;Written by: Bryan Schappel ; ;COMMANDS: ; ;D = display toggle ;C = change memory ;* = display address set ;Q = go to DOS ;G = run at address ;R = display registers ;N = change registers ;S = save binary file ;L = load binary file ;T = trace program ;U = un-used break points ;H = high speed display ;. = hex/dec, dec/hex convert ;B = set break point ;O = restore break point ;- = scroll up in memory ;= = scroll down in memory ;P = disassemble to device ;E = erase memory ;F = find memory ; ;** EQUATES ** ; CIOV = $E456 ;Central I/O ICCOM = $0342 ;commamd ICBAL = $0344 ;buf adr lo ICBAH = $0345 ;buf adr hi ICBLL = $0348 ;buf len lo ICBLH = $0349 ;buf len hi AUX1 = $034A ;aux byte 1 AUX2 = $034B ;aux byte 2 COLPF2 = $02C6 ;bkgrnd COLPF1 = $02C5 ;text RAMTOP = $6A ;top of RAM CONSOL = $D01F ;consol keys LBUFF = $0580 ;I/O buffer PUTRC = $09 ;put rec com EOL = $9B ;end of line DOSVEC = $0A ;DOS jmp vec FR0 = $D4 ;float point AFP = $D800 ;asc to fp FASC = $D8E6 ;fp to asc IFP = $D9AA ;int to fp AUDF1 = $D200 ;so. chan 0 AUDC1 = $D201 ;distortion RTCLOK = $14 ;jiffy clock INBUFF = $F3 ;fp result CIX = $F2 ;fp offset FPI = $D9D2 ;fp to int SETVBV = $E45C ;set vblank XITVBV = $E462 ;xit vblank NMIEN = $D40E ;interupt go VBRK = $0206 ;BRK vector ZPAGE = $00 ;zero page STACK = $0100 ;hardware stack PAGE2 = $0200 ;page 2 ROWCRS = $54 ;y-pos CH = $02FC ;key press SDLSTL = $0230 ;display list SRTIMR = $022B ;key debounce SDMCTL = $022F ;DMA control DOSINI = $0C ;dos init vec COLDST = $0244 ;cold start flag VKEYBD = $0208 ;keyboard vector KBCODE = $D209 ;key code KEYDEF = $79 ;key code>ascii CHBAS = $02F4 ;character base DDEV = $20 ;D: ; ;** PROGRAM EQUATES ** ; *= $80 SLFS .DS 1 ;slow or fast INDR .DS 2 ;addr of mne OP .DS 1 ;opcode NBYTE .DS 1 ;command bytes ADDR .DS 2 ;disa address CEND .DS 1 ;command end GDIGS .DS 1 ;# of digits SAVEY .DS 1 ;temp save SMEM .DS 2 ;temp addr CNTLO .DS 1 ;nbyte count NCHK .DS 1 ;check keys? TEMP .DS 2 ;temp store HXDC .DS 1 ;hex/dec flag SAVEX .DS 1 ;temp X save SL .DS 2 ;buffer address STL .DS 2 ;start address ENL .DS 2 ;end address BLL .DS 2 ;buffer length DINS .DS 2 ;2 byte arg DISKC .DS 1 ;disk command DISKC2 .DS 1 ;read/write? BSET .DS 1 ;break point BRAN .DS 2 ;branch adr BRAFLG .DS 1 ;branck flag SCR .DS 2 ;scr mem IND2 .DS 2 ;indr 2 TOPADR .DS 2 ;top disa adr LN2 .DS 2 ;2nd disa adr SAVX2 .DS 1 ;temp X IND3 .DS 2 ;temp addr save ERRNUM .DS 1 ;I/O error # SAVD .DS 2 ;trace save adr SAVY2 .DS 1 ;temp Y 2 DTYPE .DS 1 ;display type IPUT .DS 1 ;input flag BLINK .DS 1 ;blink rate CSHAPE .DS 1 ;cursor shape FREN .DS 1 ;free brk pnts BBCK .DS 1 ;bytes back OLDC .DS 1 ;old key press OLDAC .DS 1 ;old asc convert INVS .DS 1 ;inverse flag CAPS .DS 1 ;caps flag PGWAY .DS 1 ;scroll dir ; *= $A100 ;Cartridge ; ;------------ ;DISASSEMBLER ;------------ DISA CLD ;no decimal. LDA DOSINI ;save DOS INIT STA MYINIT+1 LDA DOSINI+1 STA MYINIT+2 LDA VKEYBD ;copy keybrd adr STA TKEY ;to hold LDA VKEYBD+1 STA TKEY+1 LDA VBRK ;copy VBRK vec STA BRKS ;to hold area LDA VBRK+1 STA BRKS+1 LDA KEYDEF ;test 800 or XL? ORA KEYDEF+1 BEQ REINIT ;have 800 LDA KEYDEF ;copy keycode to STA K1+1 ;ascii table adr LDA KEYDEF+1 ;to my program STA K1+2 ; REINIT CLD LDX #0 ;get 0 STX EXEC ;no run. STX COLDST STX NCHK ;check keys STX NMIEN ;no interupts. STX DTYPE ;display type INX STX IPUT STX BBCK TSX ;get stk pntr STX USRS ;save. LDA #$E0 ;restore char STA CHBAS ;set LDA #$A0 ;set RAMTOP on STA RAMTOP ;my program SEI LDA #<BRKER ;point BRK hand STA VBRK ;to my routine. LDA #>BRKER STA VBRK+1 LDA #<MKEYV ;replace keybrd STA VKEYBD ;interrupt with LDA #>MKEYV ;mine STA VKEYBD+1 LDA #<MYINIT ;point RESET STA DOSINI ;vec to my prog. LDA #>MYINIT STA DOSINI+1 CLI LDX #0 C123 LDA ZPAGE,X ;now copy the STA MYZPG,X ;first 3 pages LDA STACK,X ;of RAM to my STA MYPG1,X ;buffers. LDA PAGE2,X ;(For TRACER) STA MYPG2,X INX BNE C123 JSR OPSCR ;open screen LDA USRPC ;now disa from STA FR0 ;the users PC LDA USRPC+1 STA FR0+1 JSR TOEDEV LDA #$40 ;interupts on. STA NMIEN JSR FREBRK ;sho BRK points JSR DOREGS ;and registers. ; ;Wait here for command ; GETCOM JSR CLRWIN ;clear com JSR CLRCMD ;and prompt JSR CLRKEY JSR SETKEY ;set keys JSR GETKEY ;get a key AND #$7F ;no inverse LDX #17 ;scan 18 coms GC2 CMP CMDTXT,X ;is it a com? BEQ HAVCOM ;yes. DEX ;no. BPL GC2 ;18 coms yet? JSR GOTERR ;sorry error. JMP GETCOM ;go again. HAVCOM TXA ASL A ;mult * 2 TAX LDA CMDADR,X ;get command STA CMDJSR+1 ;address from LDA CMDADR+1,X ;the table STA CMDJSR+2 ;put in JSR JSR CLRERR ;erase error. JSR ERASTAT ;and status. JSR SETKEY CMDJSR JSR $FFFF ;go command! JMP GETCOM ;get next one. ; ;This is the go DOS command ; DOSCMD LDA #7 ;kill VBLANK LDY #<XITVBV LDX #>XITVBV JSR SETVBV LDA BRKS ;restore the STA VBRK ;BRK vector. LDA BRKS+1 STA VBRK+1 LDA MYINIT+1 ;restore RESET STA DOSINI ;vector LDA MYINIT+2 STA DOSINI+1 SEI LDA TKEY ;restore key- STA VKEYBD ;board interrupt LDA TKEY+1 STA VKEYBD+1 CLI PLA ;pull off RTS PLA JMP (DOSVEC) ;go DOS ; ;Re-init prog after RESET ; MYINIT JSR $FFFF ;changed JMP REINIT ; ;Open new screen ; OPSCR LDA #0 ;black STA COLPF2 ;background LDA #10 ;white text STA COLPF1 LDA #146 ;blue borders STA COLPF2+2 JSR CLRSCR ;clear screen LDA #<DLIST ;install my STA SDLSTL ;Display List LDA #>DLIST STA SDLSTL+1 LDA #33 ;screen on STA SDMCTL LDA #7 ;def. mode LDY #<VBI ;point to my VBI LDX #>VBI JMP SETVBV ;set it! ; ;This routine closes IOCB two. ;(Device IOCB.) ; DCLOSE LDX #DDEV ;Device LDA #12 ;close command STA ICCOM,X ;store it JMP CIOV ;close it. ; ;Zero FR0 ; ZFR LDA #0 ;zero floating STA FR0 ;point regs. STA FR0+1 RTS ; ;General use print routine ; EPRINT STA IND2 ;address of mem STY IND2+1 ;to 'print'. JSR CLCLN ;get line adr LDY #0 ;zero loop. PRL LDA (IND2),Y ;get char CMP #EOL ;is EOL? BEQ PRD ;yes. finished. JSR ASC2IC ;no. make icode STA (SCR),Y ;on screen INY ;up loop. BNE PRL ;go again. PRD INC ROWCRS ;up y-pos. RTS ;bye. ; ;Error routine ; GOTERR LDA #100 ;nice tone. STA AUDF1 LDA #$AA ;no distortion STA AUDC1 LDA #0 ;leave it on STA RTCLOK ;for 5 jiffies. TONE LDA RTCLOK CMP #5 BNE TONE LDX #0 ;turn it off. STX AUDC1 STX AUDF1 RTS ;bye. ; ;Fetch address ; GADR JSR CLRCMD ;clear prompt JSR CLRWIN ;and window LDA #10 ;a '*' STA COMND JSR INPUT ;get INPUT BCC GDNM ;good input PLA ;pull off RTS PLA RTS ;next command GDNM LDY #0 GTDR LDX #0 STX HXDC ;signal hex # LDA MYBUF,Y ;first char. CMP #'. ;a '.'? BNE GET4 ;no. in hex INC HXDC ;signal dec # INY BNE GNUM ;get decimal ; ;Pull out a 4 byte hex address ; GET4 JSR ZFR ;zero fp regs STA GDIGS G4LOOP LDA MYBUF,Y ;pull char CMP #EOL ;at end? BNE TESTIT ;no. RTS ;bye. TESTIT LDX #$0F ;do 16 digits. G4SCAN CMP HEXDIG,X ;is it in BEQ GOTG4D ;the Hex table? DEX ;no. try next. BPL G4SCAN ;go again. G4ERR PLA ;Not in table, PLA ;we have an JMP GOTERR ;error. Sorry. GOTG4D ASL FR0 ;multiply # ROL FR0+1 ;by a factor ASL FR0 ;of 16. ROL FR0+1 ASL FR0 ROL FR0+1 ASL FR0 ROL FR0+1 TXA ;add digit ORA FR0 ;to the STA FR0 ;current addr INC GDIGS ;up digs done LDA GDIGS ;get it. CMP #5 ;more than 4 BCS G4ERR ;yes. error. INY ;do next one JMP G4LOOP ;do again. ; ;Get out a decimal number ; GNUM JSR ZFR ;zero fp regs STA GDIGS DONUM LDA MYBUF,Y ;pull char CMP #EOL ;EOL? BNE GTEST ;no. LDA #0 ;index to str STA CIX ;is zero STY SAVEY LDA #<LBUFF ;point INBUFF STA INBUFF ;to LBUFF LDA #>LBUFF STA INBUFF+1 LDX GDIGS ;install EOL LDA #EOL ;for safety STA LBUFF,X JSR AFP ;to fp BCS GNERR ;error? JSR FPI ;to integer BCS GNERR ;error? LDY SAVEY ;restore Y RTS ;bye. GTEST LDX #9 ;scan 10 digs. GNSCAN CMP HEXDIG,X ;in table BEQ GOTGN ;have digit DEX ;try next BPL GNSCAN GNERR PLA ;error PLA ;bad digit JMP GOTERR GOTGN INY ;up char index LDX GDIGS ;save char in STA LBUFF,X ;LBUFF. INC GDIGS ;next digit JMP DONUM ;go again ; ;Show memory contents ; SHOMEM LDX #0 ;pos. 2,0 STX HXDC INX STX NBYTE JSR ZBUF ;blank buffer LDA ADDR ;in fp for STA FR0 ;hex convert LDA ADDR+1 STA FR0+1 LDX #0 ;at pos 0 JSR COPYNUM ;copy number LDA #EOL ;insert EOL STA MYBUF+30 LDY #0 ;Y = 0 COPY2 STY SAVEY ;save y JSR ZFR ;Zero FR0 TAY ;Y = 0 LDA (ADDR),Y ;number STA OP ;make digit JSR FNDBRK ;BRK point? LDA OP ;put op in FR0 STA FR0 LDY SAVEY ;restore index CMP #EOL ;have EOL? BEQ GOL ;yes. leave it. STA MYBUF+23,Y ;save char GOL JSR BIN2HEX ;make it hex LDA BSET ;is this BRK? BEQ NN1 ;point? no. LDY #1 ;yes. make # NN0 LDA LBUFF+2,Y ;inverse ORA #$80 ;video. STA LBUFF+2,Y DEY BPL NN0 NN1 LDY SAVEY ;insert in buf. LDX STRPOS,Y ;get position LDA LBUFF+2 ;first digit STA MYBUF,X ;in buffer LDA LBUFF+3 ;second digit STA MYBUF+1,X ;in buff. JSR NSET ;add 1 to addr INY ;up count CPY #6 ;done 6? BNE COPY2 ;no. RTS ;bye. ; ;Handle Change memory ; CHGMEM JSR GADR CREG LDA FR0 ;copy fp to STA SMEM ;zpage for LDA FR0+1 ;lookup STA SMEM+1 JSR GADR ;get number LDA FR0 ;take LSB LDY #0 STA (SMEM),Y ;poke it in RTS ; ;Go memory routine ; GMEM JSR GADR ;run address PLA PLA LDA FR0 ;copy RUN addr STA USRPC ;for later LDA FR0+1 STA USRPC+1 SEI ;kill interrupts LDX #0 C321 LDA MYZPG,X ;copy USER RAM STA ZPAGE,X ;back for the LDA MYPG1,X ;run. STA STACK,X LDA MYPG2,X STA PAGE2,X INX BNE C321 CLI LDX USRS ;restore user TXS ;registers LDA USRP PHA LDX USRX ;restore X LDY USRY ;and Y LDA USRA ;and Acc INC EXEC ;set RUN flag PLP ;restore status JMP (USRPC) ;RUN! ; ;Disassemble Memory ; DISMEM JSR GADR ;get adr TOEDEV LDA FR0 ;move in addr STA ADDR STA TOPADR ;top line LDA FR0+1 ;hi byte STA ADDR+1 STA TOPADR+1 LDA #0 ;pos.0 STA ROWCRS DMEM JSR FINLIN ;disa it JSR CLCLN ;screen line LDY #30 DM3 LDA MYBUF,Y CMP #EOL ;make EOL space BNE CON2 LDA #32 CON2 JSR ASC2IC ;make icode STA (SCR),Y ;on screen DEY BPL DM3 ;do next INC ROWCRS ;up ypos. LDA ROWCRS ;get it CMP #1 ;second line? BNE SECLN ;no. LDA ADDR ;set LN2 pntr STA LN2 LDA ADDR+1 STA LN2+1 SECLN LDA ROWCRS ;done 14 yet? CMP #14 BNE DMEM ;no. RTS ;yes. ; ;Memory disassembler ; DISAMEM LDY #0 ;zero Y STY BRAFLG ;no branch STY HXDC ;in hex LDA (ADDR),Y ;get opcode STA OP ;and save JSR FNDBRK ;BRK point? LDA OP ;get op LDY #0 ;zero Y FNDOP CMP OPCODE,Y ;is op in BEQ HAVOP ;the opcode INY ;table? CPY #151 ;151 yet? BNE FNDOP ;no. HAVOP STY SAVY2 ;save Y JSR ZBUF ;clear buffer LDA ADDR ;copy addr STA FR0 ;to FP LDA ADDR+1 STA FR0+1 LDX #0 ;pos. 0 JSR COPYNUM ;copy it JSR ZFR ;clear FP LDA OP ;get op STA FR0 ;in FP LDX #6 ;pos 8 JSR COPYNUM ;copy it LDY SAVY2 ;get Y LDX OFFSET,Y ;MNE offset LDY #0 ;copy out the ADMNE LDA MNE,X ;Mnemonic and STA MYBUF+18,Y ;put in INX ;buffer. INY CPY #3 ;3 chars? BNE ADMNE ;no. LDY #1 ;Y = 1 STY NBYTE ;1 byte instr LDA (ADDR),Y ;copy next 2 STA INDR ;possible INY ;instruction LDA (ADDR),Y ;bytes to temp STA INDR+1 ;hold address. LDY SAVY2 ;restore Y LDA ITYPE,Y ;get Itype ASL A ;times 2 TAY ;in Y LDA DCOMT,Y ;look up the STA DJSR+1 ;routine addr LDA DCOMT+1,Y ;an put in STA DJSR+2 ;JSR DJSR JSR $FFFF ;go command! LDY #39 ;now insert the AEOL3 LDA MYBUF,Y ;the EOL CMP #32 ;character BNE AEOL2 DEY BPL AEOL3 AEOL2 LDA #EOL STA MYBUF+1,Y LDA BSET ;brk point? BEQ NSET ;no. JSR INV2 ;inverse it NSET LDA ADDR ;now add the CLC ;number of ADC NBYTE ;byte to the STA ADDR ;adr pointer LDA ADDR+1 ;to get next ADC #0 ;instr addr. STA ADDR+1 RTS ;bye. ; ;Inverse Mnemonics ; INV2 LDY #18 ;start w/ 18th INVL LDA MYBUF,Y ;get char EOR #$80 ;flip bit 7 STA MYBUF,Y ;store in buff INY ;up index CPY #21 ;21st yet? BNE INVL ;not done RTS ;done. ; ;Immediate Mode ; IMMED JSR LOBYTE ;insert LSB LDA #'# ;a '#' STA MYBUF+22 ;in buffer NUMBR LDA #0 ;zero MSB STA INDR+1 NUMBR2 LDA INDR ;put in FR0 STA FR0 LDA INDR+1 STA FR0+1 NUMBR3 LDX #23 ;put in arg JMP COPYNUM ; ;Zero page ; ZPAG JSR LOBYTE ;do LSB JMP NUMBR ;add arg ; ;Zero page,X ; ZPAGX JSR LOBYTE ;LSB JSR NUMBR ;add arg ADDX2 LDY #1 ;just ,X ADDX INX ;up X ADDX3 LDA COMMAX,Y ;copy the STA MYBUF+1,X ;,X into DEX ;the buffer DEY BPL ADDX3 RTS ;done. ; ;Absolute ; ABSOL JSR LOBYTE ;LSB JSR HIBYTE ;MSB JMP NUMBR2 ;add arg ; ;Absolute ,X ; ABSOLX JSR ABSOL ;set up absol JMP ADDX2 ;copy in ,X ; ;Absolute ,Y ; ABSOLY JSR ABSOL ;do absol ACY LDA #$2C ;a comma STA MYBUF+1,X ;in buf LDA #89 ;a Y STA MYBUF+2,X ;in buf RTS ;done ; ;Indirect X ; INDX LDA #0 ;no MSB STA INDR+1 JSR LOBYTE ;do LSB JSR OPENP ;add open '(' INX ;up X LDY #2 ;3 bytes BNE ADDX ;copy ',X)' ; ;Indirect Y ; INDY LDA #0 ;no MSB STA INDR+1 JSR LOBYTE ;do LSB JSR OPENP ;left ( LDY #2 ;copy in the ADDY LDA COMMAY,Y ;'),Y' STA MYBUF+1,X INX DEY BPL ADDY RTS ;done ; ;Accumulator Mode ; ACCUM LDA #65 ;an 'A' STA MYBUF+22 ;in buffer RTS ;done ; ;Branch instructions ; RELA JSR LOBYTE ;put LSB INC NBYTE ;make 3 byte JSR ZFR ;zero FR0 INC BRAFLG ;have branch. LDA #29 ;add arrow STA MYBUF+17 ;in buffer. LDA INDR ;get operand BPL NOBACK ;not inverse DEC MYBUF+17 ;make up arrow AND #$7F ;mask inverse EOR #$7F ;flip it CLC ;add a 1 ADC #1 STA DINS+1 ;save it SEC ;and subtract SBC #2 ;two. JMP TOFP ;done NOBACK STA DINS+1 TOFP LDA INDR ;operand BPL FORWARD ;bran forward LDA ADDR ;now subtract SEC ;from addr SBC DINS+1 ;to find out STA FR0 ;where this LDA ADDR+1 ;branch goes. SBC #0 STA FR0+1 JMP BACK ;done. FORWARD CLC ;add # to ADC ADDR ;addr to calc STA FR0 ;forward branch LDA ADDR+1 ADC #0 STA FR0+1 BACK LDA #2 ;now add a 2 CLC ;to skip the ADC FR0 ;instruction STA FR0 ;address STA BRAN ;and save LDA FR0+1 ;the branch ADC #0 ;addr for the STA FR0+1 ;tracer. STA BRAN+1 JSR NUMBR3 ;add number DEC NBYTE ;make 2 bytes ; ;Implied Mode ; IMP RTS ;do nothing ; ;Indirect instructions ; INDI JSR LOBYTE ;copy in LSB JSR HIBYTE ;and MSB JSR OPENP ;do open ( LDA #') ;and add STA MYBUF+1,X ;closing one RTS ;leave. ; ;Zero page ,Y ; ZPAGY JSR LOBYTE ;do LSB JSR NUMBR ;add arg JMP ACY ;copy ,Y ; ;Insert LSB ; LOBYTE INC NBYTE ;up bytes JSR ZFR ;zero FR0 LDA INDR ;do lobyte STA FR0 LDX #10 ;at pos. 10 JMP COPYNUM ;do it! ; ;Insert MSB ; HIBYTE INC NBYTE ;3 byter JSR ZFR ;no FR0 LDA INDR+1 ;hibyte STA FR0 ;in FP LDX #14 ;at pos. 14 JMP COPYNUM ;copy it. ; ;Add Open ( ; OPENP LDA #'( ;open ( STA MYBUF+22 ;in buffer JMP NUMBR2 ;add number ; ;Handle I/O error ; IOERR JSR ZFR ;save errnum STY FR0 STY ERRNUM JSR GOTERR ;beep! JSR ZBUF ;no buffer JSR IFP ;Int to FP JSR FASC ;con to asc LDY #$FF LDX #$FF ;copy to buf IOLP INY INX LDA (INBUFF),Y STA MYBUF,X BPL IOLP AND #$7F STA MYBUF,X ;in err buf LDA #EOL STA MYBUF+1,X STX CEND LDX #17 ;search the ERRLP1 LDA ERRS,X ;errors CMP ERRNUM ;we have in BEQ GERR1 ;english DEX BPL ERRLP1 BMI IOL5 GERR1 TXA ;we have one. ASL A ;* 2 TAX ;get address LDA ERRTAB+1,X STA INDR+1 LDA ERRTAB,X STA INDR LDY #$FF ;and copy it LDX CEND ;to mybuf. LDA #', STA MYBUF+1,X INX IOL4 INY INX LDA (INDR),Y STA MYBUF+1,X BPL IOL4 AND #$7F STA MYBUF+1,X LDA #EOL ;add EOL. STA MYBUF+2,X IOL5 LDA #14 ;on error line STA ROWCRS JSR CLRERR ;clear it IOL3 LDA #<MYBUF ;and print LDY #>MYBUF JMP EPRINT ; ;Copy number to string ; COPYNUM DEX STX CNTLO ;save X LDA HXDC ;hex/dec? BEQ INHEX ;have Hex. JSR IFP ;to FP JSR FASC ;to ASC LDX CNTLO ;get index LDY #$FF ;and copy CNLOOP INY ;the number INX LDA (INBUFF),Y STA MYBUF,X BPL CNLOOP AND #$7F ;mask bit 7 STA MYBUF,X RTS ;leave INHEX JSR BIN2HEX ;make hex LDX CNTLO ;get pos INX ;up it. BEQ ALL ;if 0 do all CPX #20 ;is X > 20? BCS ARG ;yes. SOME LDA LBUFF+2 ;no. just copy STA MYBUF,X ;the LSB part INX ;of the Hex LDA LBUFF+3 ;number. STA MYBUF,X RTS ;bye. ARG LDA #'$ ;install a '$' STA MYBUF,X INX ;up X LDA NBYTE ;Get # of bytes CMP #2 ;is it 2? BEQ SOME ;no. ALL LDY #0 ;no. copy it ALOOP LDA LBUFF,Y ;all to buf STA MYBUF,X INX INY CPY #4 ;done yet? BNE ALOOP ;nope. DEX ;dec X RTS ;so long. ; ;Binary to hexadecimal ; BIN2HEX LDY #0 ;buf indx=0 LDX #1 ;do 2 nums NXTBYT STX SAVEX ;save it LDA #240 ;get HI bits AND FR0,X LSR A ;divide by 16 LSR A LSR A LSR A TAX ;to index LDA HEXDIG,X ;get char STA LBUFF,Y ;and save INY ;up buf index LDX SAVEX ;get X back LDA #15 ;now LO bits AND FR0,X TAX LDA HEXDIG,X ;get char and STA LBUFF,Y ;put in buffer INY ;up buf indx LDX SAVEX ;get X DEX ;down by one BPL NXTBYT ;done? RTS ;yes. bye. ; ;Fill buffer with blanks ; ZBUF LDA #32 ;space LDX #39 ;do 128 spaces ZLOOP STA MYBUF,X ;in buf DEX ;down count BPL ZLOOP ;go again RTS ;bye. ; ;Handle a 6502 BRK instruction ; BRKER LDA EXEC ;running? BNE SAVREG ;yes. PLA ;no. just exit. RTI SAVREG CLD ;chill dec STX USRX ;save registers STY USRY PLA STA USRA PLA STA USRP ;calc BRK point PLA SEC SBC #2 STA USRPC ;put in program PLA ;counter. SBC #0 STA USRPC+1 TSX ;store stck pntr STX USRS ;for user CLI JMP SHOBRK ;bye. ; ;Vertical Blank Interrupt ; ;Update my RTCLOK registers ;in my zero page buffer so ;we can use real-time delay ;loops in the tracer. ; VBI INC MYZPG+20 ;jiffies BNE VBDN INC MYZPG+19 ;'seconds' BNE VBDN INC MYZPG+18 ;'minutes' ; ;Now we check to see if there ;is an input being taken and ;if so blink the cursor ; VBDN LDA IPUT ;inputting? BNE VBOT ;no. LDA SRTIMR ;key pressed? BEQ BLINK? ;no. LDA #63 ;yes. leave STA CSHAPE ;cursor on for LDA #60 ;1 second. STA BLINK BLINK? LDA CSHAPE ;shape DEC BLINK ;down blink BNE VEXIT ;not 0 leave LDY #30 ;1/2 second STY BLINK ;delay EOR #63 ;flip shape STA CSHAPE ;and save VEXIT LDY CEND ;get posit STA COMLN,Y ;save cursor VBOT JMP XITVBV ;all done ; ;Show BRK information ; SHOBRK PHP ;get status TAX PLA AND #$EF ;alter it PHA PLP ;put it back. LDA #0 ;stop EXEC STA EXEC JMP REINIT ;reinit DEBUG+ ; ;Keyboard Handler ; MKEYV LDA EXEC ;running? BEQ MYKEYV LDA KBCODE CMP #$9C ;control ESC? BNE MYKEYV ;no so get key STY USRY ;save Y STX USRX ;save X LDA #$FF ;clear out key STA CH PLA ;pull Accum STA USRA ;store it PLA ;get P stat STA USRP ;save it PLA ;pull LSB of PC STA USRPC ;save it PLA ;pull MSB STA USRPC+1 ;save it TSX ;get S pntr STX USRS ;save it CLI ;clear interrupt JMP SHOBRK ;show info MYKEYV JMP (TKEY) ; ;Show registers ; DOREGS LDY #0 ;zero index DOLOP STY SAVEY JSR ZFR ;clr FR0 LDA USRA,Y ;get reg STA FR0 ;in FR0 JSR BIN2HEX ;to hex. LDY SAVEY ;reload Y LDX DRPOS,Y ;find posit. LDA LBUFF+2 ;get byte SEC SBC #32 STA PCNT,X ;into buffer LDA LBUFF+3 ;next. SEC SBC #32 STA PCNT+1,X INY CPY #4 ;done? BNE DOLOP ;no way. LDA USRPC ;show the STA FR0 ;program cntr LDA USRPC+1 STA FR0+1 JSR BIN2HEX LDY #3 ;put it on PCL LDA LBUFF,Y ;the screen SEC ;make icode SBC #32 STA PCNT,Y DEY BPL PCL LDX #17 ;index for PS LDY #7 ;do 8 bits. BITIT LDA USRP ;get it AND BITS,Y ;mask it BEQ NON LDA #17 ;a '1' BNE PRON NON LDA #16 ;a '0' PRON STA PCNT,X ;on screen INX ;up scr pntr DEY ;dec loop BPL BITIT ;do again. LDA #17 ;put on a 1 STA PCNT+19 ;under unused RTS ;status bit. ; ;Change registers ; CREGS LDY #7 ;copy on prompt CRGL LDA REGTXT,Y STA COMND,Y DEY BPL CRGL REGW JSR GETKEY ;get a key LDY #4 ;test 5 CRG CMP REGIS,Y ;this one? BEQ HAVREG ;yes! DEY ;nope. BPL CRG ;try next BMI REGW ;sorry, again HAVREG TYA ;get address ASL A ;of register TAY ;in memory LDA REGTAB,Y ;and put STA FR0 ;in fp regs LDA REGTAB+1,Y STA FR0+1 JSR CREG ;change memory. JMP DOREGS ;show regs. ; ;These are the routines used ;to convert ASC to ICODE and ;ICODE to ASC. Each uses a ;4 byte table of bit masks ;located at the end of the ;program for the conversion. ; ;Asc to internal ; ASC2IC JSR BITER ;fix up bits ORA A2I,X ;add new mask LDX SAVX2 ;restore X RTS ;done! ; ;Internal to Asc ; IC2ASC JSR BITER ;do bits. ORA I2A,X ;add mask. LDX SAVX2 ;get X RTS ;and leave ; ;Ready the bits ; BITER PHA ;save old byte ROL A ;roll the bits ROL A ;around 4 times ROL A ROL A AND #3 ;make it index STX SAVX2 ;save X TAX ;X = A PLA ;pull old byte AND #$9F ;mask it off RTS ;and leave ; ;Clear screen (3 pages) ; CLRSCR LDA #0 ;get a space TAX ;zero X CLSC STA MYSCRN,X ;page 1 STA MYSCRN+$0100,X ;page 2 STA MYSCRN+$0200,X ;page 3 INX ;up loop BNE CLSC ;and loop again STA ROWCRS ;pos 0,0 RTS ;all done ; ;Input routine ; INPUT LDA #0 ;length = 0 STA CEND STA IPUT ;signal input JSR CLRWIN ;clear window JSR ZBUF ;and buffer GETC JSR GETKEY ;get a key CMP #27 ;ESCape? BNE LEG0 ;nope. INC IPUT SEC ;signal error RTS ;and leave LEG0 LDY NCHK ;check legals? BNE GOTCHR ;nope. LEG1 LDY #40 ;is it a legal LEGL CMP LEGAL,Y ;char? BEQ GOTCHR ;yup. DEY ;not this one BPL LEGL ;try next JSR GOTERR ;error. JMP GETC ;go again. GOTCHR CMP #126 ;Delete? BNE NOTDEL ;no. DEC CEND ;lower length BPL TS2 ;<0? no. LDA #0 ;make zero. STA CEND JSR GOTERR ;give error. TS2 JSR TST1 ;test length LDA CEND ;get length BEQ GETC ;if not 0 go! LDY CEND ;put in a spc CPY #12 BNE DODEL DEY DODEL LDA #0 STA COMLN,Y ;erase char STA COMLN+1,Y ;erase cursor JMP GETC ;get next. NOTDEL CMP #156 ;Delete Line? BEQ INPUT ;yes. LDY CEND STA MYBUF,Y CMP #EOL ;EOL? BEQ ATEND ;done! JSR ASC2IC ;make icode CPY #12 BNE SHCH DEY SHCH STA COMLN,Y ;to screen INY CPY #13 BCC TST9 DEY TST9 STY CEND JSR TST1 ;length? JMP GETC ;do again. ATEND LDA MYBUF CMP #EOL BEQ INPUT LDA #0 ;check 'em STA NCHK ;next time STA COMLN,Y ;and erase cursr INC IPUT CLC ;show good input RTS ;bye. ; ;Test input length ; TST1 LDA CEND ;get length BNE TL2 ;no. STA COMLN ;erase 1st char STA COMLN+1 ;and cursor TL2 RTS ;bye. ; ;Erase error line ; CLRERR LDY #23 ;24 chars. LDA #0 ;to clear CLE STA ERRLN,Y ;on line DEY BPL CLE ;loop. RTS ;so long. ; ;Print to device ; DPRINT LDA #PUTRC ;put record LDX #DDEV STA ICCOM,X ;CIO command LDA #<MYBUF ;mybuf is STA ICBAL,X ;the buffer LDA #>MYBUF ;hi byte STA ICBAH,X LDA #40 ;40 bytes max STA ICBLL,X LDA #0 STA ICBLH,X LDA MYBUF+23 ;if chr is BPL PRT ;>128 invert JSR INV2 PRT JSR CIOV ;print it. BMI STOP ;on error stop RTS STOP PLA PLA JMP DCLOSE ; ;Calculate line address ; CLCLN LDA ROWCRS ;y-pos ASL A ;* 2 TAX ;look up the LDA SCRN,X ;screen memory STA SCR ;address in LDA SCRN+1,X ;table and STA SCR+1 ;store it. RTS ;bye. ; ;Change display between ;Disassembly and display mem ; ALTER LDA DTYPE ;display type EOR #1 STA DTYPE BNE HAVMEM ;in display LDA #1 STA BBCK LDA #33 BNE ALT2 ;finish HAVMEM LDA #6 STA BBCK LDA #48 ALT2 STA PCNT+29 LDA TOPADR STA FR0 LDA TOPADR+1 STA FR0+1 JMP TOEDEV ; ;Find Break point ; FNDBRK LDA #0 ;say none found STA BSET LDY #5 ;try 6 B.P's SET? LDA ADDR+1 ;check if CMP SETHI,Y ;MSB is same? BNE UPLP ;not same. LDA ADDR ;match. try LSB CMP SETLO,Y BNE UPLP ;no go. LDA OPSET,Y ;match.set yet? BEQ UPLP ;no. LDA OLDOP,Y ;yes. restore STA OP ;old opcode. INC BSET ;say set. RTS ;leave. UPLP DEY ;decrease loop BPL SET? ;done? no. RTS ;yes. leave. ; ;Go to correct DISA routine ; FINLIN LDA DTYPE ;type flag BNE FINL2 ;1 = display JMP DISAMEM ;disassemble FINL2 JMP SHOMEM ;and display ; ;Set default GETKEY data ; SETKEY LDA #0 ;set normal vid STA INVS LDA #$40 ;and upper case STA CAPS RTS ; ;-------------- ;PROGRAM TRACER ;-------------- ; ;Get Key Routine ; ;This routine accepts a raw ;key press and converts it ;to ATASCII using the table ;supplied in the OS. ; GETKEY LDA CH ;get key press CMP #$FF ;$FF? BEQ GETKEY ;yes. loop LDX #$FF ;now clear key STX CH ;press STA OLDC ;save press K0 TAY CPY #$C0 ;192? BCC K1 ;no. LDY #$9A ;error 136 K1 LDA $FEFE,Y ;make ascii STA OLDAC ;save it CMP #$80 ;128? BEQ GETKEY ;yes. try again CMP #$81 ;129? BNE K2 ;no. LDA INVS ;yes. EOR #$80 ;flip inverse STA INVS ;status JMP GETKEY ;go again K2 CMP #$82 ;130? BNE K3 LDA CAPS ;yes. flip caps EOR #$40 ;status STA CAPS JMP GETKEY ;go again K3 CMP #$83 ;131? BNE K4 ;shift caps. LDA #$40 ;make caps STA CAPS BNE GETKEY K4 CMP #$84 ;132? BNE K5 LDA #$80 ;control-caps STA CAPS BNE GETKEY K5 CMP #$85 ;skip this one BEQ GETKEY LDA OLDC ;get press CMP #$40 ;64? BCS K6 ;yes. +> LDA OLDAC ;get ascii CMP #$61 ;97? BCC K6 CMP #$7B BCS K6 LDA CAPS ;lower case BEQ K6 ORA OLDC ;mask bits JMP K0 ;and do again K6 LDX #$0F ;scan for a K7 LDA KEYS,X ;special CMP OLDAC ;key press BEQ K8 DEX BPL K7 K8 BEQ K9 LDA OLDAC ;get ascii EOR INVS ;inverse bit STA OLDAC ;save it K9 RTS ;and done ; ;Wait 15 jiffies ; WAIT5 LDA #0 ;get 0 STA RTCLOK ;zero clok W1 LDA RTCLOK CMP #15 ;at 15? BNE W1 ;no. RTS ;so long! ; ;Perform manual RTS ; DORTS LDX USRS ;get pointer INX LDA MYPG1,X ;RTS lo byte STA ADDR ;in trace adr INX LDA MYPG1,X ;RTS hi byte STA ADDR+1 ;in trace adr STX USRS ;update SP JMP NSET ;add a 1 to adr ; ;Perform manual JSR ; DOJSR LDA ADDR ;calc return SEC ;address and SBC #1 ;store it in PHA ;the users LDA ADDR+1 ;stack. SBC #0 LDX USRS ;stk pntr STA MYPG1,X ;install MSB DEX ;down 1 PLA ;get LSB STA MYPG1,X ;put it in DEX STX USRS ;new stk pntr DOJMP LDY #1 ;copy new trace LDA (SAVD),Y ;address into STA ADDR ;pointers. INY ;HI byte. LDA (SAVD),Y STA ADDR+1 RTS ;bye. ; ;Thread an ML program ; TRACE JSR GADR ;get trace adr LDA FR0 ;save it. STA ADDR LDA FR0+1 STA ADDR+1 JSR CLRWIN LDY #7 ;slo or fast? FSL LDA SLOF,Y STA COMND,Y DEY BPL FSL STY SLFS ; ;SLFS = $FF for Slow mode ; = $00 for Fast mode ; = $01 for Option step mode ; FSW JSR GETKEY ;get choice CMP #'F ;FAST? BNE SLO? ;no. INC SLFS ;fast mode BEQ TN SLO? CMP #'S ;SLOW? BEQ TN ;wrong! CMP #'O ;O=option for BNE FSW ;step thru LDA #1 STA SLFS TN JSR CLRSCR ;clear screen JSR CLRWIN ;clear input JSR CLRCMD ;and prompt TLOOP LDA ADDR ;take addr and STA USRPC ;put in Program STA SAVD ;Counter, and LDA ADDR+1 ;instruction STA USRPC+1 ;save address. STA SAVD+1 JSR DISAMEM ;disa this adr JSR SCROLL ;move screen LDY #2 ;install NOP's LDA #234 ;(a NOP) DNOP STA NOPS,Y ;in area DEY BPL DNOP ;done? JSR PAUSE ;wait? JSR DOREGS ;up date USRPC LDA MYBUF+18 ;get disa chr BPL GINS ;inverse? JSR POS15 ;on status line LDA #<BRKPNT ;BRK REACHED LDY #>BRKPNT JMP EPRINT ;print it. GINS CMP #63 ;a '?' ? BNE NOBR ;no. LDY #151 ;yes. a No-inst JMP IOERR ;give error. NOBR LDA OP ;get the Opcode CMP #96 ;is it RTS? BNE NORTS ;no. JSR DORTS ;do the RTS JMP TDNE ;all done. NORTS CMP #$40 ;RTI? BNE IJMP ;no. LDX USRS ;get USRP INC USRS ;off stack. LDA MYPG1,X ;proc status. STA USRP ;in REG INX LDA MYPG1,X STA ADDR INX LDA MYPG1,X STA ADDR+1 STX USRS JMP TDNE ;all done. IJMP CMP #76 ;JMP? BNE CPN2 ;nope. JSR DOJMP ;do JMP JMP TDNE ;done. CPN2 CMP #32 ;JSR? BNE CPN6 ;nope. JSR DOJSR ;make JSR JMP TDNE ;finished. CPN6 CMP #108 ;JMP ()? BNE CPN7 ;no. JSR DOJMP ;yes. get adr LDY #0 ;look up JMP LDA (ADDR),Y ;addr thru PHA ;this adr. INY ;up Y LDA (ADDR),Y ;get HI byte STA ADDR+1 ;in addr PLA ;restore LSB STA ADDR ;in addr JMP TDNE ;done. CPN7 LDA BRAFLG ;branch? BEQ CPN4 ;not this one. LDA OP ;get Op. LDY #3 ;loop 4 times FBRA CMP BRAL,Y ;bit not set? BEQ HAVBRA2 ;YES. CMP BRAH,Y ;bit set? BEQ HAVBRA ;YES. DEY ;no. BPL FBRA ;try next one. ; ;Branch if bit set ; HAVBRA LDA USRP ;get processor AND BBIT,Y ;mask bit. BEQ NOTE ;off? yes. NEWADR LDA BRAN ;set up the STA ADDR ;new branch LDA BRAN+1 ;address for STA ADDR+1 ;next time. NOTE JMP TDNE ;jam! ; ;Branch if bit not set ; HAVBRA2 LDA USRP ;processor AND BBIT,Y ;mask it. BEQ NEWADR ;off? yes. JMP TDNE ;no. CPN4 LDY #0 ;ready to copy CIN LDA (SAVD),Y ;the instr STA NOPS,Y ;into NOP area INY ;for fall thru. CPY NBYTE ;done? BNE CIN ;not yet. ; ;Run the instruction ; LDA #0 ;kill ints STA NMIEN SEI ;set interrupt LDX #0 ;copy user mem CPZ1 LDA ZPAGE,X ;into pages TAY ;0 - 2. LDA MYZPG,X ;PAGE 0 STA ZPAGE,X TYA STA MYZPG,X ; LDA STACK,X ;PAGE 1 TAY ;(the stack) LDA MYPG1,X STA STACK,X TYA STA MYPG1,X ; LDA PAGE2,X ;PAGE 2 TAY ;(interrupts) LDA MYPG2,X ;(and stuff) STA PAGE2,X TYA STA MYPG2,X ; INX BNE CPZ1 TSX ;get stack TXA ;in A LDX USRS ;user stack TXS ;pointer. STA USRS ;save my stack. LDY USRY ;get Y, LDX USRX ;get X, LDA USRP ;put on the PHA ;processor stat LDA USRA ;get A PLP ;pull status NOPS NOP ;* here is * NOP ;* where the * NOP ;* instr goes * PHP ;push status STA USRA ;save A PLA ;save status STA USRP STX USRX ;save X STY USRY ;save Y TSX ;put back stack TXA ;pointers LDX USRS TXS STA USRS SEI ;set for safety LDX #0 ;now copy back ; ;pages 0 - 2 CZP LDA ZPAGE,X ;zero page TAY LDA MYZPG,X STA ZPAGE,X TYA STA MYZPG,X ; LDA STACK,X ;the stack TAY LDA MYPG1,X STA STACK,X TYA STA MYPG1,X ; LDA PAGE2,X ;page 2 TAY LDA MYPG2,X STA PAGE2,X TYA STA MYPG2,X ; INX BNE CZP CLI ;clr interrupts LDA #64 ;turn on the STA NMIEN ;interrupts TDNE JSR DOREGS ;show registers LDA SLFS ;mode. BMI TDN1 ;Slow. BEQ TDN2 ;Fast! LDX #8 ;consol clear STX CONSOL ;clear it. CNW LDA CONSOL ;get it CMP #3 ;OPTION? BNE CNW ;no. STX CONSOL ;yes. zero it. BNE TDN2 TDN1 JSR WAIT5 ;wait 1/4 sec TDN2 JMP TLOOP ;next instr ; ;Move screen up 32 bytes ; MOVE32 LDA #<MYSCRN ;screen STA IND2 ;address in LDA #>MYSCRN ;Zpage addr STA IND2+1 ;so we can LDA IND2 ;the screen up CLC ;40 bytes ADC #32 STA INDR LDA IND2+1 ADC #0 STA INDR+1 LDX #0 ;line 0 MOVE LDY #31 ;32 bytes MOVIT LDA (INDR),Y STA (IND2),Y DEY BPL MOVIT ;loop. LDA INDR+1 ;copy to STA IND2+1 LDA INDR STA IND2 ;add a 32 CLC ;to copy ADC #32 ;from. STA INDR LDA INDR+1 ADC #0 STA INDR+1 INX ;up line CPX #14 ;line 13? BNE MOVE ;no. RTS ;bye. ; ;Clear status line ; ERASTAT LDY #23 ;24 characters LDA #0 ;a zero ERAS1 STA STATLN,Y ;in line DEY ;next BPL ERAS1 ;go to it. RTS ;bye. ; ;Decimal/Hexadecimal Convert ; PRDH LDA HXDC ;# type STA SAVY2 ;save it LDA #3 ;full number STA NBYTE ;length JSR GADR ;get number LDA #32 ;make EOL a spc STA MYBUF,Y STA MYBUF+2,Y LDA #'= ;install = INY STA MYBUF,Y INY STY SAVX2 ;save Y LDA HXDC ;# type EOR #1 ;flip it STA HXDC ;and save again LDX #28 ;copy in # JSR COPYNUM STX CEND LDX #28 ;now move # LDY SAVX2 ;down in string CPN9 LDA MYBUF,X STA MYBUF+1,Y CPX CEND ;at end? BEQ AEND ;yes! INX INY BNE CPN9 ;go again. AEND LDA #EOL ;install EOL STA MYBUF+2,Y JSR POS15 ;on status line LDA SAVY2 ;restore # type STA HXDC JMP IOL3 ;print it. ; ;Erase memory ; ERASE JSR GADR ;start addr LDA FR0 ;transfer to STA SL ;2 Zpage locs LDA FR0+1 STA SL+1 JSR GADR ;End addr LDY #0 LDA FR0+1 ;is End<Start? CMP SL+1 BCC NEWERR ;yes! BNE NEWOK ;no. LDA FR0 ;equal check CMP SL ;LSB. BCC NEWERR ;error! BEQ NEW2 ;equal 1 byte NEWOK TYA ;get 0 STA (SL),Y ;in loc INC SL ;up loc BNE NEW1 ;wrap around? INC SL+1 ;yes. NEW1 LDA FR0+1 ;check to see CMP SL+1 ;if done yet. BNE NEWOK ;not done. LDA FR0 ;check LSB CMP SL BNE NEWOK ;not yet. NEW2 TYA ;and do last STA (SL),Y ;location. RTS ;bye. NEWERR LDY #153 ;ADR RANGE JMP IOERR ;show it. ; ;----------- ;I/O CONTROL ;----------- ; ;Print to command window ; PCOMW STA INDR ;save address STY INDR+1 LDY #0 PCA LDA (INDR),Y ;get a char STA COMND,Y ;on screen CMP #31 ;a '?'? BEQ PCN ;yes. done. INY ;up count BNE PCA ;try again PCN RTS ;leave ; ;Position cursor at line 15 ; POS15 LDA #15 STA ROWCRS RTS ; ;Scroll Screen? ; SCROLL LDA ROWCRS ;Y-pos CMP #14 ;14th line? BNE SCRL ;no. SCRL2 JSR MOVE32 ;yes. scroll LDA #13 ;pos. 13 STA ROWCRS SCRL JMP IOL3 ;print buffer ; ;Pause screen scroll ; PAUSE LDA CH ;key scan CMP #$FF ;no touch? BEQ CLRKEY ;yes. JSR CLRKEY ;clear it. CMP #28 ;was it ESC? BEQ PA2 ;yup. CMP #33 ;space bar? BNE CLRKEY ;no. JSR CLRKEY ;clear. PA3 LDA CH ;wait again CMP #33 ;space? BEQ CLRKEY ;yes. CMP #28 ;ESC? BNE PA3 ;no. wait. PA2 PLA ;have an ESC. PLA ;pull RTS ; ;Clear key ; CLRKEY PHA ;save A LDA #$FF ;clear CH STA CH ;to no touch PLA ;restore A RTS ;leave. ; ;Page thru Disa ; PGTHRU LDA #<PGTR ;print option LDY #>PGTR ;Up or Down? JSR PCOMW PGL2 JSR GETKEY ;get choice CMP #'U ;Up? BNE TDN? ;no. LDA #1 ;put scroll up STA PGWAY ;flag BNE PGLOOP ;do it! TDN? CMP #'D ;Down? BNE PGL2 ;no. LDA #0 ;insert scroll STA PGWAY ;down flag PGLOOP JSR CLRCMD ;clear stuff JSR CLRWIN PGJSR JSR PAUSE ;scroll! LDA PGWAY BEQ DWAY ;pause screen? JSR SCRUP ;do again. JMP PGJSR DWAY JSR SCRDN JMP PGJSR ; ;Disassemble to a device ; DISDEV JSR COPFIL ;get filename JSR GADR ;and start adr LDA #8 ;open IOCB for JSR OPENFIL ;write only LDA FR0 ;copy in adr STA ADDR LDA FR0+1 STA ADDR+1 OLP JSR DISAMEM ;disa a line LDA #32 ;remove arrow STA MYBUF+17 ;in disa LDA MYBUF+18 ; BPL DPR JSR INV2 DPR JSR DPRINT ;print it JSR ERASTAT ;clear line JSR POS15 ;on status LDA #EOL ;set so only STA MYBUF+6 ;addr is shown JSR IOL3 ;print disa LDA CH ;key? CMP #$FF ;no touch? BEQ OLP ;yes. go again JSR CLRKEY ;clear it JSR ERASTAT ;clear line JMP DCLOSE ;close IOCB ; ;Get device ; GETDEV JSR CLRWIN ;no junk LDA #<DEVNAMS ;copy devices LDY #>DEVNAMS ;onto the JSR PCOMW ;screen DEV2 JSR GETKEY ;get a key CMP #27 ;ESC? BNE FNDEV ;no. PLA ;pull of the 2 PLA ;RTS's from PLA ;the stack PLA RTS ;and leave FNDEV LDY #1 ;check if legal DEV3 CMP DEVS,Y ;device BEQ HAVDEV ;got one! DEY ;not this BPL DEV3 ;try next one JSR GOTERR ;sorry wrong JMP DEV2 ;go again HAVDEV RTS ;bye. ; ;Scroll down ; SCRDN LDX #0 ;check if scr SCK TXA ;has info all ASL A ;the way down TAY ;to the last LDA SCRN,Y ;screen line. STA TEMP ;get the line LDA SCRN+1,Y ;address from STA TEMP+1 ;table. LDY #0 ;zero index LDA (TEMP),Y ;get a char BEQ DOWHL ;have a space INX ;try next line CPX #14 ;at 14 yet? BNE SCK ;no. JSR FINLIN JSR SCRL2 LDX #1 ;copy the addr GX1 LDA MYSCRN,X ;from the scr JSR IC2ASC ;into mybuf CMP #32 ;a space? BEQ GX2 ;yes, done. STA MYBUF-1,X ;save it INX ;next char BNE GX1 GX2 LDA #EOL ;insert EOL STA MYBUF-1,X ;in mybuf LDY #0 JSR GET4 ;make integer LDA FR0 ;now copy this STA TOPADR ;to TOPADR LDA FR0+1 ;for next time. STA TOPADR+1 RTS ;done! DOWHL LDA LN2 ;put second STA FR0 ;address in FR0 LDA LN2+1 STA FR0+1 ;and disa all JMP TOEDEV ;16 lines. ; ;Scroll up ; SCRUP LDA TOPADR ;move down SEC ;byte in memory SBC BBCK STA FR0 ;save in FR0 LDA TOPADR+1 SBC #0 ;take care of STA FR0+1 ;Hi byte JMP TOEDEV ;do it! ; ;Clear Command type ; CLRCMD LDA #0 ;make command STA COMND ;2 spaces STA COMND+1 RTS ;bye. ; ;Clear Command Window ; CLRWIN LDY #20 ;do 21 chars LDA #0 ;a blank CW STA COMLN,Y ;in command DEY ;line buffer BPL CW ;do next RTS ;so long. ; ;Free break points ; FREBRK LDY #0 STY FREN ;none free FRE1 STY SAVEY ;save Y LDA SETLO,Y ;get addr STA FR0 ;and put in FR0 LDA SETHI,Y STA FR0+1 JSR BIN2HEX ;convert to hex LDY SAVEY ;get Y LDX BRKLN,Y ;get pos on scr LDY #0 FRE2 LDA LBUFF,Y ;hex digit SEC ;make icode SBC #32 STA FRLN,X ;on screen INX INY CPY #4 ;4 chars? BNE FRE2 ;no. LDY SAVEY ;restore Y LDA OPSET,Y ;BRK set? BNE FRE3 ;yes. INC FREN ;inc free points FRE3 INY ;up Y CPY #6 ;6 BRK's yet? BNE FRE1 ;no LDA FREN ;get free CLC ADC #16 ;make icode STA FRLN+31 ;on screen RTS ;all done ; ;Break Point Handler ; BKPHAN JSR CLRCMD ;clear comms LDA #34 ;a 'B' STA COMND JSR INPUT ;get a line BCC BKG ;good? yes! RTS ;no. bye BKG LDA MYBUF ;get number SEC ;subtr 49 (0-5) SBC #49 TAX ;save in X CMP #6 BCS NUMER ;>5? yes. CMP #0 ;<0? BCC NUMER ;yes. LDA MYBUF+1 ;next char CMP #EOL ;EOL? BEQ DORESET ;yes. reset it LDY #2 STX CNTLO ;save X JSR GTDR ;get addr LDX CNTLO ;restore X LDY #0 LDA (FR0),Y ;get opcode BEQ SETER ;BRK? yes. LDA OPSET,X ;set already? BEQ SETIT ;no. SETER LDY #152 JMP IOERR NUMER JMP GOTERR ;BEEP! SETIT LDA FR0 ;save address STA SETLO,X LDA FR0+1 STA SETHI,X LDA (FR0),Y ;get opcode STA OLDOP,X ;save it TYA ;zero Acc STA (FR0),Y ;insert BRK INC OPSET,X ;show set JMP FREBRK ;and leave ; DORESET JSR CLRCMD ;no junk LDY #0 ;zero Y LDA OPSET,X ;Set yet? BEQ RESER2 ;no. error LDA SETLO,X ;get address STA INDR ;of Bpoint LDA SETHI,X ;and save in STA INDR+1 ;2 Zpage locs LDA OLDOP,X ;get old opcode STA (INDR),Y ;put it back. TYA ;A = 0 STA OPSET,X ;not set. STA SETLO,X STA SETHI,X JMP FREBRK ;update free RESER2 LDY #150 ;give user JMP IOERR ;Error # 150 ; ;Find memory ; FINDIT JSR CLRCMD ;clear line LDA #31 ;a '?' STA COMND STA NCHK ;don't check JSR INPUT ;keys on input BCC FCS ;good input RTS ;bye FCS LDY #0 ;check to see FCP LDA MYBUF,Y ;if input ends CMP #EOL ;with an EOL BEQ FCP2 ;or a comma. CMP #$2C ;if comma the BEQ FCP2 ;get an address STA MBF2,Y ;also copy line INY ;into a temp CPY #12 ;buffer BNE FCP FCP2 STY SLFS ;save Y CMP #$2C ;a comma? BNE FCP3 ;no. JSR GADR ;get address LDA FR0 ;to start from SEC ;subtract 1 SBC #1 ;from it. STA SL ;and save it LDA FR0+1 SBC #0 STA SL+1 LDY #$FF ;force a BNE FCP4 ;branch FCP3 LDY #$FF ;set up $FFFF STY SL STY SL+1 FCP4 INY STY DISKC STY STL STY STL+1 ;end at $FFFF JSR CLRSCR FC1 LDA SL ;add one to CLC ;current addr ADC #1 STA SL LDA SL+1 ADC #0 STA SL+1 CMP #>MYBUF ;at buffers BNE FC9 ;yet? no. LDA SL CMP #<MYBUF BNE FC9 ;no. LDA #<ENDBUF ;skip over STA SL ;the input LDA #>ENDBUF ;and page 0-2 STA SL+1 ;buffers. FC9 LDA DISKC ;first run? BEQ FC3 ;yes. LDA SL ;at $0000? ORA SL+1 BNE FC3 ;no. RTS ;yes. done. FC3 LDY #1 ;second pass STY DISKC DEY ;Y = 0 FC4 LDA (SL),Y ;a char CMP MBF2,Y ;= to mbf2? BNE FC1 ;no. INY ;a match? CPY SLFS ;done yet? BNE FC4 ;no. JSR ZBUF ;set up buffer LDX #5 ;to show what FC5 LDA FTXT,X ;find this STA MYBUF,X ;was and at DEX ;what address BPL FC5 ;the string LDA SL ;was found at. STA FR0 LDA SL+1 ;address STA FR0+1 JSR BIN2HEX LDY #3 LDX #17 FC6 LDA LBUFF,Y ;Hex address STA MYBUF,X DEX DEY BPL FC6 LDA #'$ ;add '$' STA MYBUF,X LDA #EOL ;add in the STA MYBUF+18 ;eol INC STL ;up # of finds BNE NH4 INC STL+1 NH4 LDA STL ;now add in STA FR0 ;the find #. LDA STL+1 STA FR0+1 LDX #7 STX HXDC JSR COPYNUM JSR PAUSE ;pause? JSR SCROLL ;scroll screen JMP FC1 ;go again ; ;Load a binary file ; DOLOAD LDA #'D ;filename JSR COPFL LDA #0 ;signal first STA SLFS ;pass LDA #7 ;get bytes STA DISKC2 ;save LDA #4 ;read only JSR OPENFIL ;open file! JSR READ2 ;get 2 bytes BMI BLO2 ;error? yes. LDA BAL ;is header? CMP #$FF ;$FF? BNE BDLO ;no. CMP BAL+1 ;other one? BEQ DLOAD ;yes. = $FF BDLO LDY #149 ;ERROR 149 BLO2 STY SAVEY ;save it JSR DCLOSE ;close Device LDY SAVEY ;get error JMP IOERR ;and leave DLOAD JSR READ2 ;2 more bytes LDA SLFS ;pass = 1? BNE CHD ;no. LDA BAL ;copy load STA FR0 ;addr to safe LDA BAL+1 ;place STA FR0+1 INC SLFS ;pass = 2 CHD JSR CHKHED ;$FF? JSR STRAD ;set start JSR READ2 ;2 more bytes JSR ENDAD ;set end adr JSR BUFLEN ;calc buf len JSR GETDAT ;get stuff BMI LOADD ;if error done JMP DLOAD ;keep going. LOADD TYA ;error in A PHA ;save it JSR DCLOSE ;close dev PLA ;get error CMP #136 ;EOF? BNE LODERR ;no. Error! JSR ZBUF ;clear buffer LDY #6 ;'LOAD AT' LLP LDA LODAD,Y STA MYBUF,Y DEY BPL LLP JSR BIN2HEX ;convert addr LDY #3 ;to hex© LDX #12 LLP1 LDA LBUFF,Y ;insert # STA MYBUF,X DEX DEY BPL LLP1 LDA #'$ ;add a '$' STA MYBUF,X LDA #EOL ;install EOL STA MYBUF+13 JSR POS15 ;on STAT: JMP IOL3 ;print it. LODERR TAY ;in Y JMP IOERR ;show error ; ;Read in 2 file bytes ; READ2 LDA #<BAL ;point to STA SL ;2 byte buffer LDA #>BAL STA SL+1 LDA #0 ;only 2 bytes STA BLL+1 ;in length LDA #2 ;and fall thru STA BLL ;to getrec ; ;Get file segment ; GETREC LDX #DDEV ;Device LDA DISKC2 ;command STA ICCOM,X LDA SL ;buffer adr STA ICBAL,X LDA SL+1 STA ICBAH,X LDA BLL ;buffer length STA ICBLL,X LDA BLL+1 STA ICBLH,X JMP CIOV ;get it ; ;Calculate buffer length ; BUFLEN LDA ENL ;take end and SEC ;subtract start SBC STL ;to calc length STA BLL LDA ENL+1 SBC STL+1 STA BLL+1 LDA BLL ;then add 1 CLC ;for CIO ADC #1 STA BLL LDA BLL+1 ADC #0 ;add carry STA BLL+1 RTS ;and leave ; ;Put in start addr ; STRAD LDA BAL ;move in start STA STL ;address LDA BAL+1 STA STL+1 RTS ; ;Put in end addr ; ENDAD LDA BAL ;move in end STA ENL ;addr. LDA BAL+1 STA ENL+1 RTS ; ;Check if header ; CHKHED LDX BAL ;first byte INX ;up by 1 BEQ TNXT ;zero? yes. RTS ;nope. TNXT LDX BAL+1 ;second byte INX ;up it BEQ ITSFF ;zero? yes. RTS ;no. ITSFF JMP READ2 ;2 more bytes ; ;Get DATA ; GETDAT LDA STL ;set up start STA SL ;loadind addr LDA STL+1 STA SL+1 JMP GETREC ;and load it ; ;Open Disk ; OPENFIL STA DISKC ;save I/O JSR DCLOSE ;close IOCB LDA DISKC ;get I/O type LDX #DDEV ;device chan STA AUX1,X ;in AUX1 LDA #0 ;AUX2 = 0 STA AUX2,X LDA #3 ;open command STA ICCOM,X LDA #<FILNAM ;point to STA ICBAL,X ;filename LDA #>FILNAM STA ICBAH,X JSR CIOV ;open it! BMI OPENR ;sorry error. RTS ;good open. OPENR PLA ;pull RTS PLA ;and show error JMP IOERR ; ;Copy filename ; COPFIL JSR GETDEV ;device. COPFL PHA ;save it STA FILNAM ;in filename LDA #EOL ;3 char is EOL STA FILNAM+2 PLA ;device CMP #'D ;to Disk? BEQ TOD ;yes. RTS ;no fname. TOD JSR CLRCMD ;clr window LDA #31 ;a ? STA COMND JSR INPUT ;get name BCC CQP1 ;if good branch PLA ;pull RTS PLA RTS ;next command CQP1 LDX #2 ;offset is 2 LDY #0 ;zero Y COPL LDA MYBUF,Y ;char CMP #', ;a comma? BEQ GNAME ;yes. CMP #EOL ;EOL? BEQ GNAME ;yes. STA FILNAM,X ;save in name INY ;up pointers INX CPX #18 ;18 chars yet? BNE COPL ;no. LDY #165 ;Fname error PLA PLA JMP IOERR ;show it GNAME LDA #EOL ;add EOL STA FILNAM,X ;to Fname RTS ;leave ; ;Save a File ; DOSAVE LDA #'D ;Fname JSR COPFL LDA #11 ;put bytes STA DISKC2 JSR GADR ;save start LDA FR0 ;copy it STA STL LDA FR0+1 STA STL+1 JSR GADR ;save end LDA FR0 ;copy it STA ENL LDA FR0+1 ;is end<start? STA ENL+1 CMP STL+1 BCC SIOR2 ;yes. BEQ TESTLO ;equal. BNE DSAV ;save it. TESTLO LDA ENL ;try LSB's CMP STL BCC SIOR2 ;error! DSAV LDA #8 ;write only JSR OPENFIL ;open it! LDA #$FF ;Install header STA BAL STA BAL+1 JSR READ2 ;put it out BMI SIOR ;error LDA STL ;start bytes STA BAL LDA STL+1 STA BAL+1 JSR READ2 ;put them BMI SIOR LDA ENL ;end bytes STA BAL LDA ENL+1 STA BAL+1 JSR READ2 ;put them BMI SIOR JSR BUFLEN ;calc length JSR GETDAT ;and save it BMI SIOR JMP DCLOSE ;close it SIOR2 LDY #153 ;ADR ERROR SIOR TYA PHA JSR DCLOSE PLA TAY JMP IOERR ;show it ; ;This is the command text and ;addresses of routines ;plus string positions for ;Show command. ; CMDTXT .BYTE "QDRN*CGLS" .BYTE "BT-=FPH.E" CMDADR .WORD DOSCMD ;Quit .WORD ALTER ;Display .WORD DOREGS ;Registers .WORD CREGS ;New register .WORD DISMEM ;*=addr .WORD CHGMEM ;Change .WORD GMEM ;Go .WORD DOLOAD ;Load .WORD DOSAVE ;Save .WORD BKPHAN ;Break pnt han .WORD TRACE ;Trace .WORD SCRUP ;- .WORD SCRDN ;= .WORD FINDIT ;Find .WORD DISDEV ;Print .WORD PGTHRU ;High speed .WORD PRDH ;. .WORD ERASE ;Erase ; ;Disassembler Vectors ; DCOMT .WORD IMMED ;immediate .WORD ZPAG ;Zpage .WORD ZPAGX ;Zpage,X .WORD ABSOL ;Absolute .WORD ABSOLX ;Absolute,X .WORD ABSOLY ;Absolute,Y .WORD INDX ;(indirect,X) .WORD INDY ;(indirect),Y .WORD ACCUM ;Accumulator .WORD RELA ;Relative .WORD IMP ;Implied .WORD INDI ;(indirect) .WORD ZPAGY ;Zpage,Y STRPOS .BYTE 5,8,11,14,17,20 ; ;Screen line address table ; SCRN .WORD [MYSCRN+1] ;ln 0 .WORD [MYSCRN+33] ;ln 1 .WORD [MYSCRN+65] ;ln 2 .WORD [MYSCRN+97] ;ln 3 .WORD [MYSCRN+129] ;ln 4 .WORD [MYSCRN+161] ;ln 5 .WORD [MYSCRN+193] ;ln 6 .WORD [MYSCRN+225] ;ln 7 .WORD [MYSCRN+257] ;ln 8 .WORD [MYSCRN+289] ;ln 9 .WORD [MYSCRN+321] ;ln 10 .WORD [MYSCRN+353] ;ln 11 .WORD [MYSCRN+385] ;ln 12 .WORD [MYSCRN+417] ;ln 13 .WORD ERRLN ;ln 14 .WORD STATLN ;ln 15 BAL .BYTE 0,0 DRPOS .BYTE 5,8,11,14,17 BRKS .BYTE 0,0 EXEC .BYTE 0 BRKLN .BYTE 0,5,10,15,20,25 TKEY .BYTE 0,0 ; ;Branch Instrs + branch bits ; BRAL .BYTE $10,$50,$90,$D0 BRAH .BYTE $30,$70,$B0,$F0 BBIT .BYTE $80,$40,$01,$02 ; ;Custom Display List ; DLIST .BYTE $70,$70,$70,$42 .WORD LINE1 .BYTE $00,$02,$20,$42 .WORD MYSCRN .BYTE $02,$02,$02,$02 .BYTE $02,$02,$02,$02 .BYTE $02,$02,$02,$02 .BYTE $02,$20,$42 .WORD LINE2 .BYTE $02,$00,$02 .BYTE $00,$02,$00,$02 .BYTE $00,$02,$02,$41 .WORD DLIST ; ;Screen Memory ; LINE1 .SBYTE +$80," DEBUG+ by: Bryan Schappel " .SBYTE +$80," ADDR B1 B2 B3 MNEMONICS " LINE2 .SBYTE +$80," PC| A| X| Y|SP|NV_BDIZC|MODE " PCNT .SBYTE " | | | | | |DISA " .SBYTE +$80," INPUT:" .BYTE 0 COMND .SBYTE " " COMLN .SBYTE " " .SBYTE " " .SBYTE +$80," ERROR:" .BYTE 0 ERRLN .SBYTE " " .SBYTE +$80," STAT:" .BYTE 0 STATLN .SBYTE " " .SBYTE +$80,"BRK1|BRK2|BRK3|BRK4|BRK5|BRK6|FR" FRLN .SBYTE " | | | | | |00" ; ;Run and trace data tables ; USRA .BYTE 0 USRX .BYTE 0 USRY .BYTE 0 USRS .BYTE 0 USRP .BYTE 0 USRPC .BYTE 0,0 ; ;Register Table ; REGTAB .WORD USRA .WORD USRX .WORD USRY .WORD USRS .WORD USRP BITS .BYTE 1,2,4,8,16,32,64,128 ; ;Icode/Asc convert tables ; A2I .BYTE $40,$00,$20,$60 I2A .BYTE $20,$40,$00,$60 ; ;BRK point data tables ; SETLO .BYTE 0,0,0,0,0,0 ;LSB SETHI .BYTE 0,0,0,0,0,0 ;MSB OLDOP .BYTE 0,0,0,0,0,0 ;opcode OPSET .BYTE 0,0,0,0,0,0 ;flag ; ;Special Key presses ; KEYS .BYTE $FF,$FE,$FD,$9F,$9E .BYTE $9D,$9C,$9B,$7F,$7E .BYTE $7D,$1F,$1E,$1D,$1C .BYTE $1B ; ;Error codes numbers ; ERRS .BYTE 128,130,137,138,139 .BYTE 144,146,162,164,165 .BYTE 167,169,170,149 .BYTE 150,151,152,153 ; ;Error code addresses ; ERRTAB .WORD I128,I130,I137 .WORD I138,I139,I144 .WORD I146,I162,I164 .WORD I165,I167,I169 .WORD I170,I149,I150 .WORD I151,I152,I153 ; ;Miscellaneous Text & Devs ; DEVNAMS .SBYTE "(D,P)?" PGTR .SBYTE "(U,D)?" SLOF .SBYTE "(S,F,O)?" REGTXT .SBYTE "(AXYSP)?" DEVS .BYTE "DP" FILNAM .BYTE " : " .BYTE " ",EOL REGIS .BYTE "AXYSP" BRKPNT .BYTE "BRK POINT FOUND" LEGAL .BYTE $9B,$9C,$7E,",." HEXDIG .BYTE "0123456789ABCDEF" .BYTE "GHIJKLMNOPQRSTUVWXYZ" FTXT .BYTE "FIND #" COMMAX .BYTE ",X)" COMMAY .BYTE "Y,)" LODAD .BYTE "LOAD AT" ; ;English Error Codes ; I128 .CBYTE "BREAK KEY ABORT" I130 .CBYTE "NO DEVICE HANDLER" I137 .CBYTE "TRUNCATED RECORD" I138 .CBYTE "DEVICE TIMEOUT" I139 .CBYTE "DEVICE NAK" I144 .CBYTE "WRITE PROTECTED" I146 .CBYTE "FUNCTION NOT DONE" I162 .CBYTE "DISK FULL" I164 .CBYTE "FILE NUM MISMATCH" I165 .CBYTE "BAD FILE NAME" I167 .CBYTE "FILE LOCKED" I169 .CBYTE "DIRECTORY FULL" I170 .CBYTE "FILE NOT FOUND" I149 .CBYTE "FILE NOT BINARY" I150 .CBYTE "NO SET BRK POINT" I151 .CBYTE "INVALID OPCODE" I152 .CBYTE "BRK POINT SET" I153 .CBYTE "ADR RANGE ERROR" ; ;These are the mnemonics for ;the disassembler. They are ;arranged here in alphabetical ;order. ; MNE .BYTE "ADCANDASLBCCBCS" .BYTE "BEQBITBMIBNEBPL" .BYTE "BRKBVCBVSCLCCLD" .BYTE "CLICLVCMPCPXCPY" .BYTE "DECDEXDEYEORINC" .BYTE "INXINYJMPJSRLDA" .BYTE "LDXLDYLSRNOPORA" .BYTE "PHAPHPPLAPLPROL" .BYTE "RORRTIRTSSBCSEC" .BYTE "SEDSEISTASTXSTY" .BYTE "TAXTAYTSXTXATXS" .BYTE "TYA???" ; ;Opcodes ; OPCODE .BYTE $69,$65,$75,$6D ;ADC .BYTE $7D,$79,$61,$71 .BYTE $29,$25,$35,$2D ;AND .BYTE $3D,$39,$21,$31 .BYTE $0A,$06,$16,$0E ;ASL .BYTE $1E .BYTE $90 ;BCC .BYTE $B0 ;BCS .BYTE $F0 ;BEQ .BYTE $24,$2C ;BIT .BYTE $30 ;BMI .BYTE $D0 ;BNE .BYTE $10 ;BPL .BYTE $00 ;BRK .BYTE $50 ;BVC .BYTE $70 ;BVS .BYTE $18 ;CLC .BYTE $D8 ;CLD .BYTE $58 ;CLI .BYTE $B8 ;CLV .BYTE $C9,$C5,$D5,$CD ;CMP .BYTE $DD,$D9,$C1,$D1 .BYTE $E0,$E4,$EC ;CPX .BYTE $C0,$C4,$CC ;CPY .BYTE $C6,$D6,$CE,$DE ;DEC .BYTE $CA ;DEX .BYTE $88 ;DEY .BYTE $49,$45,$55,$4D ;EOR .BYTE $5D,$59,$41,$51 .BYTE $E6,$F6,$EE,$FE ;INC .BYTE $E8 ;INX .BYTE $C8 ;INY .BYTE $4C,$6C ;JMP .BYTE $20 ;JSR .BYTE $A9,$A5,$B5,$AD ;LDA .BYTE $BD,$B9,$A1,$B1 .BYTE $A2,$A6,$B6,$AE ;LDX .BYTE $BE .BYTE $A0,$A4,$B4,$AC ;LDY .BYTE $BC .BYTE $4A,$46,$56,$4E ;LSR .BYTE $5E .BYTE $EA ;NOP .BYTE $09,$05,$15,$0D ;ORA .BYTE $1D,$19,$01,$11 .BYTE $48 ;PHA .BYTE $08 ;PHP .BYTE $68 ;PLA .BYTE $28 ;PLP .BYTE $2A,$26,$36,$2E ;ROL .BYTE $3E .BYTE $6A,$66,$76,$6E ;ROR .BYTE $7E .BYTE $40 ;RTI .BYTE $60 ;RTS .BYTE $E9,$E5,$F5,$ED ;SBC .BYTE $FD,$F9,$E1,$F1 .BYTE $38 ;SEC .BYTE $F8 ;SED .BYTE $78 ;SEI .BYTE $85,$95,$8D ;STA .BYTE $9D,$99,$81,$91 .BYTE $86,$96,$8E ;STX .BYTE $84,$94,$8C ;STY .BYTE $AA ;TAX .BYTE $A8 ;TAY .BYTE $BA ;TSX .BYTE $8A ;TXA .BYTE $9A ;TXS .BYTE $98 ;TYA ; ;Offsets into Mnemonic table ; OFFSET .BYTE 0,0,0,0,0,0,0,0 ;ADC .BYTE 3,3,3,3,3,3,3,3 ;AND .BYTE 6,6,6,6,6 ;ASL .BYTE 9 ;BCC .BYTE 12 ;BCS .BYTE 15 ;BEQ .BYTE 18,18 ;BIT .BYTE 21 ;BMI .BYTE 24 ;BNE .BYTE 27 ;BPL .BYTE 30 ;BRK .BYTE 33 ;BVC .BYTE 36 ;BVS .BYTE 39 ;CLC .BYTE 42 ;CLD .BYTE 45 ;CLI .BYTE 48 ;CLV .BYTE 51,51,51,51 ;CMP .BYTE 51,51,51,51 .BYTE 54,54,54 ;CPX .BYTE 57,57,57 ;CPY .BYTE 60,60,60,60 ;DEC .BYTE 63 ;DEX .BYTE 66 ;DEY .BYTE 69,69,69,69 ;EOR .BYTE 69,69,69,69 .BYTE 72,72,72,72 ;INC .BYTE 75 ;INX .BYTE 78 ;INY .BYTE 81,81 ;JMP .BYTE 84 ;JSR .BYTE 87,87,87,87 ;LDA .BYTE 87,87,87,87 .BYTE 90,90,90,90,90 ;LDX .BYTE 93,93,93,93,93 ;LDY .BYTE 96,96,96,96,96 ;LSR .BYTE 99 ;NOP .BYTE 102,102,102,102 ;ORA .BYTE 102,102,102,102 .BYTE 105 ;PHA .BYTE 108 ;PHP .BYTE 111 ;PLA .BYTE 114 ;PLP .BYTE 117,117,117,117 ;ROL .BYTE 117 .BYTE 120,120,120,120 ;ROR .BYTE 120 .BYTE 123 ;RTI .BYTE 126 ;RTS .BYTE 129,129,129,129 ;SBC .BYTE 129,129,129,129 .BYTE 132 ;SEC .BYTE 135 ;SED .BYTE 138 ;SEI .BYTE 141,141,141,141 ;STA .BYTE 141,141,141 .BYTE 144,144,144 ;STX .BYTE 147,147,147 ;STY .BYTE 150 ;TAX .BYTE 153 ;TAY .BYTE 156 ;TSX .BYTE 159 ;TXA .BYTE 162 ;TXS .BYTE 165 ;TYA .BYTE 168 ;??? ; ;Instruction Types ; ; 0 = Immediate ; 1 = Zero page ; 2 = Zero page,X ; 3 = Absolute ; 4 = Absolute,X ; 5 = Absolute,Y ; 6 = Indirect,X ; 7 = Indirect,Y ; 8 = Accumulator ; 9 = Relative ;10 = Implied ;11 = Indirect ;12 = Zero page,Y ; ITYPE .BYTE 0,1,2,3,4,5,6,7 ;ADC .BYTE 0,1,2,3,4,5,6,7 ;AND .BYTE 8,1,2,3,4 ;ASL .BYTE 9 ;BCC .BYTE 9 ;BCS .BYTE 9 ;BEQ .BYTE 1,3 ;BIT .BYTE 9 ;BMI .BYTE 9 ;BNE .BYTE 9 ;BPL .BYTE 10 ;BRK .BYTE 9 ;BVC .BYTE 9 ;BVS .BYTE 10 ;CLC .BYTE 10 ;CLD .BYTE 10 ;CLI .BYTE 10 ;CLV .BYTE 0,1,2,3,4,5,6,7 ;CMP .BYTE 0,1,3 ;CPX .BYTE 0,1,3 ;CPY .BYTE 1,2,3,4 ;DEC .BYTE 10 ;DEX .BYTE 10 ;DEY .BYTE 0,1,2,3,4,5,6,7 ;EOR .BYTE 1,2,3,4 ;INC .BYTE 10 ;INX .BYTE 10 ;INY .BYTE 3,11 ;JMP .BYTE 3 ;JSR .BYTE 0,1,2,3,4,5,6,7 ;LDA .BYTE 0,1,12,3,5 ;LDX .BYTE 0,1,2,3,4 ;LDY .BYTE 8,1,2,3,4 ;LSR .BYTE 10 ;NOP .BYTE 0,1,2,3,4,5,6,7 ;ORA .BYTE 10 ;PHA .BYTE 10 ;PHP .BYTE 10 ;PLA .BYTE 10 ;PLP .BYTE 8,1,2,3,4 ;ROL .BYTE 8,1,2,3,4 ;ROR .BYTE 10 ;RTI .BYTE 10 ;RTS .BYTE 0,1,2,3,4,5,6,7 ;SBC .BYTE 10 ;SEC .BYTE 10 ;SED .BYTE 10 ;SEI .BYTE 1,2,3,4,5,6,7 ;STA .BYTE 1,12,3 ;STX .BYTE 1,2,3 ;STY .BYTE 10 ;TAX .BYTE 10 ;TAY .BYTE 10 ;TSX .BYTE 10 ;TXA .BYTE 10 ;TXS .BYTE 10 ;TYA .BYTE 10 ;??? ; MYBUF .DS 40 ;I/O buffer MBF2 .DS 15 ;temp save buff MYZPG .DS 256 ;zero page MYPG1 .DS 256 ;stack MYPG2 .DS 256 ;page two ENDBUF = * ;end of buffers MYSCRN = $BD00 ;scr mem 3pgs ; *= $02E0 .WORD DISA .END