A.N.A.L.O.G. ISSUE 39 / FEBRUARY 1986 / PAGE 53

Debug+

by Bryan Schappel

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!

Typing it in.

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.

  1. Type Listing 1 into your Atari and verify it with Unicheck (see page 11).
  2. Type RUN and press RETURN. The program will begin checking the data lines, printing the line numbers as it goes. You’ll be alerted if it finds any problems. Fix any incorrect lines and re-RUN the program as necessary, until all errors are eliminated.
  3. When all data lines are correct, you will be prompted to INSERT DISK WITH DOS, PRESS RETURN. Place a disk in drive 1 with DOS and press RETURN. The message WRITING FILE will appear, and the computer will create the DEBUG.COM file, printing the line numbers as it goes. Make sure you save the BASIC program under a different filename before continuing.

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:

KeyFunction
*Address Set
DDisplay Toggle
QQuit DEBUG+, go to DOS
GGo at address
TTrace program
PPrint Disassembly
EErase Memory
CChange 1 byte of RAM
NChange Register Value
RDisplay Registers
BSet/Reset Break Point
SSave a binary file
LLoad a binary file
FFind a string in memory
HHigh 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.

Display formats.

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.

Commands.

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.

Notes.

  1. For every command discussed above, the keyboard auto-repeat is active. So, by holding one of the command keys down, you can re-execute the command as fast as a key will repeat. This is very useful while using the scroll commands.
  2. While executing any command, pressing the ESC key will abort that function. If you are entering a filename and decide not to load a file, just press ESC at any time, and the command will abort.
  3. To pause the screen scrolling at any time, press the SPACE BAR. To abort a command that constantly scrolls the screen, press ESC.

Don’ts.

Well, that’s about everything you can do with Debug+. Now let me tell you what you can’t do.

  1. Do not alter any of the contents of the memory between $A100 and $C0FF. This is where Debug+ resides. Changing any of this memory could be fatal.
  2. Debug+ uses the VBREAK vector located at address $0206–$0207 to detect the 6502 BRK instruction. Do not alter this vector. Doing so will severely cripple Debug+. When you exit Debug+, the program will restore the default VBREAK vector.
  3. Debug+ also uses the VKEYBD vector located at address $0208–$0209 to detect the CTRL-ESC key combination during a user run. Do not alter this vector. If you do, you may never be able to stop the execution of one of your programs. When Debug+ is exited, it restores the default vector.
  4. When you press RESET while in Debug+, the program will take control and reinitialize itself. Do not alter the DOSINI vector located at $0C–$0D. When you exit Debug+, the default DOSINI vector is restored.

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.

Listing 1.
BASIC listing.

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 DATLIN<>LINE THEN ? "LINE ";LINE;" MISSING!":POKE 752,0:END 
70 TOTAL=USR(ADR(ML$),ADR(DAT$),ADR(BIN$),LEN(DAT$),TOTAL):IF TOTAL=65535 THEN 160
80 IF PASS=2 THEN ? #1;BIN$;:READ CHKSUM: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,161:CLOSE #1:POKE 752,Z:END 
130 ? "INSERT DISK WITH DOS, PRESS RETURN":INPUT #16,DAT$:OPEN #1,8,Z,"D:DEBUG.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":? :? LINE;" 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 D8A50C8D16A2A50D8D17A2AD08028D5EB2AD09028D5FB2AD06028D55B2AD07028D56B2A579057AF00AA5798D9F,837
1010 DATA A9A57A8DA0A9D8A2008E57B28E4402868D8E0ED486B1E886B286B6BA8EB9B3A9E08DF402A9A0856A78A9EB8D06,285
1020 DATA 02A9A68D0702A9598D0802A9A78D0902A915850CA9A2850D58A200B5009D5AB8BD00019D5AB9BD00029D5ABAE8,821
1030 DATA D0EC201BA2ADBBB385D4ADBCB385D520F4A3A9408D0ED42045AE208BA7203AAE2031AE2029AD2080A92089A929,381
1040 DATA 7FA211DDD8B1F009CA10F82070A24CA4A18A0AAABDEAB18DDEA1BDEBB18DDFA120E5A8204CAC2080A920FFFF4C,947
1050 DATA A4A1A907A062A2E4205CE4AD55B28D0602AD56B28D0702AD16A2850CAD17A2850D78AD5EB28D0802AD5FB28D09,938
1060 DATA 025868686C0A0020FFFF4C33A1A9008DC602A90A8DC502A9928DC802203DA8A96C8D3002A9B28D3102A9218D2F,529
1070 DATA 02A907A016A2A74C5CE4A220A90C9D42034C56E4A90085D485D56085A484A5201EA9A000B1A4C99BF008201DA8,720
1080 DATA 91A2C8D0F2E65460A9648D00D2A9AA8D01D2A9008514A514C905D0FAA2008E01D28E00D2602031AE203AAEA90A,230
1090 DATA 8D1EB3204FA89003686860A000A2008690B923B8C92ED005E690C8D03D204FA28588B923B8C99BD00160A20FDD,622
1100 DATA 7BB4F008CA10F868684C70A206D426D506D426D506D426D506D426D58A05D485D4E688A588C905B0DEC84CB7A2,665
1110 DATA 204FA28588B923B8C99BD022A90085F28489A98085F3A90585F4A688A99B9D80052000D8B01220D2D9B00DA489,553
1120 DATA 60A209DD7BB4F008CA10F868684C70A2C8A6889D8005E6884CF4A2A2008690E8868420E0A6A58585D4A58685D5,904
1130 DATA A2002060A6A99B8D41B8A0008489204FA2A8B18585832051A9A58385D4A489C99BF003993AB820B6A6A59EF00D,692
1140 DATA A001B9820509809982058810F5A489BE28B2AD82059D23B8AD83059D24B820BBA4C8C006D0B960208DA2A5D485,189
1150 DATA 8AA5D5858B208DA2A5D4A000918A60208DA26868A5D48DBBB3A5D58DBCB378A200BD5AB89500BD5AB99D0001BD,246
1160 DATA 5ABA9D0002E8D0EC58AEB9B39AADBAB348AEB7B3ACB8B3ADB6B3EE57B2286CBBB3208DA2A5D4858585A6A5D585,157
1170 DATA 8685A7A90085542076A9201EA9A01EB923B8C99BD002A920201DA891A28810EFE654A554C901D008A58585A8A5,560
1180 DATA 8685A9A554C90ED0D160A00084A18490B18585832051A9A583A000D95CB6F005C8C097D0F684B020E0A6A58585,908
1190 DATA D4A58685D5A2002060A6204FA2A58385D4A2062060A6A4B0BEF3B6A000BDB1B59935B8E8C8C003D0F4A0018484,153
1200 DATA B1858581C8B1858582A4B0B98BB70AA8B90EB28DA1A4B90FB28DA2A420FFFFA027B923B8C920D0038810F6A99B,522
1210 DATA 9924B8A59EF00320C9A4A5851865848585A5866900858660A012B923B849809923B8C8C015D0F36020CAA5A923,164
1220 DATA 8D39B8A9008582A58185D4A58285D5A2174C60A620CAA54CE1A420CAA520E1A4A001E8B9A5B49D24B8CA8810F6,365
1230 DATA 6020CAA520D8A54CE5A4200CA54CFEA4200CA5A92C9D24B8A9599D25B860A900858220CAA520E6A5E8A002D0C8,36
1240 DATA A900858220CAA520E6A5A002B9A8B49D24B8E88810F660A9418D39B86020CAA5E684204FA2E6A1A91D8D34B8A5,969
1250 DATA 811012CE34B8297F497F186901859B38E9024C7CA5859BA5811010A58538E59B85D4A586E90085D54C9BA51865,112
1260 DATA 8585D4A586690085D5A9021865D485D4859FA5D5690085D585A020EDA4C6846020CAA520D8A520E6A5A9299D24,108
1270 DATA B86020CAA520E1A44C1EA5E684204FA2A58185D4A20A4C60A6E684204FA2A58285D4A20E4C60A6A9288D39B84C,719
1280 DATA E5A4204FA284D484AD2070A220E0A620AAD920E6D8A0FFA2FFC8E8B1F39D23B810F7297F9D23B8A99B9D24B886,361
1290 DATA 87A211BDFFB3C5ADF005CA10F6302A8A0AAABD12B48582BD11B48581A0FFA687A92C9D24B8E8C8E8B1819D24B8,736
1300 DATA 10F7297F9D24B8A99B9D25B8A90E855420E5A8A923A0B84C56A2CA868CA590F01920AAD920E6D8A68CA0FFC8E8,47
1310 DATA B1F39D23B810F7297F9D23B86020B6A6A68CE8F01EE014B00EAD82059D23B8E8AD83059D23B860A9249D23B8E8,878
1320 DATA A584C902F0E6A000B980059D23B8E8C8C004D0F4CA60A000A2018691A9F035D44A4A4A4AAABD7BB4998005C8A6,966
1330 DATA 91A90F35D4AABD7BB4998005C8A691CA10DB60A920A2279D23B8CA10FA60AD57B2D0026840D88EB7B38CB8B368,37
1340 DATA 8DB6B3688DBAB36838E9028DBBB368E9008DBCB3BA8EB9B3584C4AA7EE6EB8D008EE6DB8D003EE6CB8A5B2D020,596
1350 DATA AD2B02F008A93F85B4A93C85B3A5B4C6B3D008A01E84B3493F85B4A4879920B34C62E408AA6829EF4828A9008D,85
1360 DATA 57B24C33A1AD57B2F02AAD09D2C99CD0238CB8B38EB7B3A9FF8DFC02688DB6B3688DBAB3688DBBB3688DBCB3BA,801
1370 DATA 8EB9B3584C4AA76C5EB2A0008489204FA2B9B6B385D420B6A6A489BE50B2AD820538E9209DF6B2AD830538E920,654
1380 DATA 9DF7B2C8C004D0D7ADBBB385D4ADBCB385D520B6A6A003B9800538E92099F6B28810F4A211A007ADBAB339C7B3,299
1390 DATA F004A911D002A9109DF6B2E88810EBA9118D09B360A007B949B4991EB38810F72089A9A004D962B4F0058810F8,943
1400 DATA 30F1980AA8B9BDB385D4B9BEB385D520A0A34C8BA7202FA81DCFB3A6AA60202FA81DD3B3A6AA60482A2A2A2A29,570
1410 DATA 0386AAAA68299F60A900AA9D00BD9D00BE9D00BFE8D0F4855460A900858785B2203AAE20E0A62089A9C91BD004,36
1420 DATA E6B23860A48DD010A028D976B4F0098810F82070A24C5BA8C97ED024C6871007A90085872070A220DAA8A587F0,758
1430 DATA CBA487C00CD00188A9009920B39921B34C5BA8C99CF0A9A4879923B8C99BF019201DA8C00CD001889920B3C8C0,634
1440 DATA 0D900188848720DAA84C5BA8AD23B8C99BF080A900858D9920B3E6B21860A587D0068D20B38D21B360A017A900,66
1450 DATA 993EB38810FA60A909A2209D4203A9239D4403A9B89D4503A9289D4803A9009D4903AD3AB8100320C9A42056E4,590
1460 DATA 30016068684C45A2A5540AAABD2EB285A2BD2FB285A360A5B1490185B1D008A90185B6A921D006A90685B6A930,743
1470 DATA 8D13B3A5A685D4A5A785D54CF4A3A900859EA005A586D9DDB3D014A585D9D7B3D00DB9E9B3F008B9E3B38583E6,748
1480 DATA 9E608810E260A5B1D0034C34A44C37A3A90085B9A94085BA60ADFC02C9FFF0F9A2FF8EFC0285B7A8C0C09002A0,109
1490 DATA 9AB9FEFE85B8C980F0E2C981D009A5B9498085B94C89A9C982D009A5BA494085BA4C89A9C983D006A94085BAD0,909
1500 DATA BEC984D006A98085BAD0B4C985F0B0A5B7C940B013A5B8C961900DC97BB009A5BAF00505B74C97A9A20FBDEFB3,485
1510 DATA C5B8F003CA10F6F006A5B845B985B860A9008514A514C90FD0FA60AEB9B3E8BD5AB98585E8BD5AB985868EB9B3,81
1520 DATA 4CBBA4A58538E90148A586E900AEB9B39D5AB9CA689D5AB9CA8EB9B3A001B1AE8585C8B1AE858660208DA2A5D4,520
1530 DATA 8585A5D58586203AAEA007B941B4991EB38810F784802089A9C946D004E680F00CC953F008C94FD0EDA9018580,432
1540 DATA 203DA8203AAE2031AEA5858DBBB385AEA5868DBCB385AF2034A420F7ACA002A9EA99A5AB8810FA2007AD208BA7,144
1550 DATA AD35B8100A20F2ACA967A0B44C56A2C93FD005A0974CEEA5A583C960D0062012AA4CF3ABC940D01EAEB9B3EEB9,210
1560 DATA B3BD5AB98DBAB3E8BD5AB98585E8BD5AB985868EB9B34CF3ABC94CD0062040AA4CF3ABC920D0062027AA4CF3AB,705
1570 DATA C96CD0132040AAA000B18548C8B18585866885854CF3ABA5A1F02FA583A003D960B2F01BD964B2F0038810F3AD,822
1580 DATA BAB33968B2F008A59F8585A5A085864CF3ABADBAB33968B2F0ED4CF3ABA000B1AE99A5ABC8C484D0F6A9008D0E,596
1590 DATA D478A200B500A8BD5AB89500989D5AB8BD0001A8BD5AB99D0001989D5AB9BD0002A8BD5ABA9D0002989D5ABAE8,998
1600 DATA D0D5BA8AAEB9B39A8DB9B3ACB8B3AEB7B3ADBAB348ADB6B328EAEAEA088DB6B3688DBAB38EB7B38CB8B3BA8AAE,522
1610 DATA B9B39A8DB9B378A200B500A8BD5AB89500989D5AB8BD0001A8BD5AB99D0001989D5AB9BD0002A8BD5ABA9D0002,918
1620 DATA 989D5ABAE8D0D558A9408D0ED4208BA7A5803013F014A2088E1FD0AD1FD0C903D0F98E1FD0D0032007AA4C87AA,608
1630 DATA A90085A4A9BD85A5A5A41869208581A5A569008582A200A01FB18191A48810F9A58285A5A58185A41869208581,156
1640 DATA A58269008582E8E00ED0DF60A017A900995EB38810FA60A59085B0A9038584208DA2A9209923B89925B8A93DC8,859
1650 DATA 9923B8C884AAA59049018590A21C2060A68687A21CA4AABD23B89924B8E487F004E8C8D0F2A99B9925B820F2AC,84
1660 DATA A5B085904C59A6208DA2A5D48592A5D58593208DA2A000A5D5C5939023D008A5D4C592901BF015989192E692D0,473
1670 DATA 02E693A5D5C593D0F1A5D4C592D0EB98919260A0994CEEA585818482A000B181991EB3C91FF003C8D0F460A90F,276
1680 DATA 855460A554C90ED0072013ACA90D85544C59A6ADFC02C9FFF01B2029ADC91CF012C921D0102029ADADFC02C921,469
1690 DATA F006C91CD0F5686848A9FF8DFC026860A93BA0B420DFAC2089A9C955D006A90185BBD008C944D0EFA90085BB20,472
1700 DATA 31AE203AAE2007ADA5BBF0062021AE4C53AD20D1AD4C53AD201DB1208DA2A90820F2B0A5D48585A5D585862034,658
1710 DATA A4A9208D34B8AD35B8100320C9A420F0A8204CAC20F2ACA99B8D29B82059A6ADFC02C9FFF0D82029AD204CAC4C,310
1720 DATA 45A2203AAEA935A0B420DFAC2089A9C91BD0056868686860A001D951B4F0098810F82070A24CB4AD60A2008A0A,514
1730 DATA A8B92EB2858EB92FB2858FA000B18EF030E8E00ED0E82076A920FDACA201BD00BD2026A8C920F0069D22B8E8D0,578
1740 DATA F0A99B9D22B8A00020B2A2A5D485A6A5D585A760A5A885D4A5A985D54CF4A3A5A638E5B685D4A5A7E90085D54C,470
1750 DATA F4A3A9008D1EB38D1FB360A014A9009920B38810FA60A00084B58489B9D7B385D4B9DDB385D520B6A6A489BE58,610
1760 DATA B2A000B9800538E9209D96B3E8C8C004D0F1A489B9E9B3D002E6B5C8C006D0CDA5B51869108DB5B3602031AEA9,992
1770 DATA 228D1EB3204FA8900160AD23B838E931AAC906B024C9009020AD24B8C99BF034A002868C20A2A2A68CA000B1D4,280
1780 DATA F005BDE9B3F008A0984CEEA54C70A2A5D49DD7B3A5D59DDDB3B1D49DE3B39891D4FEE9B34C45AE2031AEA000BD,428
1790 DATA E9B3F01CBDD7B38581BDDDB38582BDE3B39181989DE9B39DD7B39DDDB34C45AEA0964CEEA52031AEA91F8D1EB3,416
1800 DATA 858D204FA8900160A000B923B8C99BF00CC92CF008994BB8C8C00CD0ED8480C92CD014208DA2A5D438E9018592,150
1810 DATA A5D5E9008593A0FFD006A0FF84928493C8849C84948495203DA8A5921869018592A59369008593C9B8D00EA592,287
1820 DATA C923D008A95A8592A9BB8593A59CF007A5920593D00160A001849C88B192D94BB8D0CAC8C480D0F420E0A6A205,608
1830 DATA BD9FB49D23B8CA10F7A59285D4A59385D520B6A6A003A211B980059D23B8CA8810F6A9249D23B8A99B8D35B8E6,820
1840 DATA 94D002E695A59485D4A59585D5A20786902060A62007AD20F7AC4C57AFA9442020B1A9008580A907859DA90420,196
1850 DATA F2B02077B0300EAD4EB2C9FFD005CD4FB2F00CA09584892045A2A4894CEEA52077B0A580D00CAD4EB285D4AD4F,302
1860 DATA B285D5E68020D6B020C0B02077B020CBB020A5B020E7B030034C10B098482045A268C988D02F20E0A6A006B9AB,2
1870 DATA B49923B88810F720B6A6A003A20CB980059D23B8CA8810F6A9249D23B8A99B8D30B820F2AC4C59A6A84CEEA5A9,835
1880 DATA 4E8592A9B28593A9008599A9028598A220A59D9D4203A5929D4403A5939D4503A5989D4803A5999D49034C56E4,42
1890 DATA A59638E5948598A597E5958599A5981869018598A5996900859960AD4EB28594AD4FB2859560AD4EB28596AD4F,74
1900 DATA B2859760AE4EB2E8F00160AE4FB2E8F001604C77B0A5948592A59585934C87B0859C2045A2A59CA2209D4A03A9,45
1910 DATA 009D4B03A9039D4203A9539D4403A9B49D45032056E430016068684CEEA520AAAD488D53B4A99B8D55B468C944,868
1920 DATA F001602031AEA91F8D1EB3204FA89003686860A202A000B923B8C92CF014C99BF0109D53B4C8E8E012D0ECA0A5,448
1930 DATA 68684CEEA5A99B9D53B460A9442020B1A90B859D208DA2A5D48594A5D58595208DA2A5D48596A5D58597C59590,723
1940 DATA 45F002D006A596C594903BA90820F2B0A9FF8D4EB28D4FB22077B0302BA5948D4EB2A5958D4FB22077B0301CA5,365
1950 DATA 968D4EB2A5978D4FB22077B0300D20A5B020E7B030054C45A2A09998482045A268A84CEEA55144524E2A43474C,302
1960 DATA 5342542D3D4650482E45E3A12DA98BA7F0A7F1A39DA3B2A3E1AF64B185AE4CAA21AED1AD08AF66AD31AD57ACA1,277
1970 DATA ACD9A4F2A4F8A40CA515A51BA529A538A54FA555A5B1A5B2A5C1A505080B0E111401BD21BD41BD61BD81BDA1BD,862
1980 DATA C1BDE1BD01BE21BE41BE61BE81BEA1BE3EB35EB3000005080B0E1100000000050A0F14190000105090D03070B0,712
1990 DATA F0804001027070704296B20002204200BD020202020202020202020202022042D6B20200020002000200020241,759
2000 DATA 6CB28080A4A5A2B5A78B80808080E2F99A80A2F2F9E1EE80B3E3E8E1F0F0E5EC808080A1A4A4B28080A2918080,470
2010 DATA A2928080A2938080ADAEA5ADAFAEA9A3B3808080808080B0A3FC80A1FC80B8FC80B9FCB3B0FCAEB6BFA2A4A9BA,8
2020 DATA A3FCADAFA4A58080000000007C00007C00007C00007C00007C00000000000000007C24293321000080A9AEB0B5,89
2030 DATA B49A0000000000000000000000000000000000000000000000000080A5B2B2AFB29A0000000000000000000000,579
2040 DATA 00000000000000000000000000008080B3B4A1B49A000000000000000000000000000000000000000000000000,689
2050 DATA 00A2B2AB91FCA2B2AB92FCA2B2AB93FCA2B2AB94FCA2B2AB95FCA2B2AB96FCA6B2000000007C000000007C0000,744
2060 DATA 00007C000000007C000000007C000000007C101000000000000000B6B3B7B3B8B3B9B3BAB30102040810204080,342
2070 DATA 4000206020400060000000000000000000000000000000000000000000000000FFFEFD9F9E9D9C9B7F7E7D1F1E,712
2080 DATA 1D1C1B8082898A8B9092A2A4A5A7A9AA9596979899B2B4C1B4D2B4E2B4F0B4FAB409B51AB523B534B541B54CB5,236
2090 DATA 5AB568B577B587B595B5A2B508240C30091F08350C24091F08330C260C2F091F082138393330091F4450203A20,145
2100 DATA 20202020202020202020209B415859535042524B20504F494E5420464F554E449B9C7E2C2E3031323334353637,57
2110 DATA 38394142434445464748494A4B4C4D4E4F505152535455565758595A46494E4420232C5829592C294C4F414420,208
2120 DATA 4154425245414B204B45592041424F52D44E4F204445564943452048414E444C45D25452554E43415445442052,602
2130 DATA 45434F52C44445564943452054494D454F55D4444556494345204E41CB57524954452050524F5445435445C446,355
2140 DATA 554E4354494F4E204E4F5420444F4EC54449534B2046554CCC46494C45204E554D204D49534D415443C8424144,909
2150 DATA 2046494C45204E414DC546494C45204C4F434B45C44449524543544F52592046554CCC46494C45204E4F542046,383
2160 DATA 4F554EC446494C45204E4F542042494E4152D94E4F205345542042524B20504F494ED4494E56414C4944204F50,939
2170 DATA 434F44C542524B20504F494E54205345D44144522052414E4745204552524FD2414443414E4441534C42434342,462
2180 DATA 4353424551424954424D49424E4542504CC2D2CB425643425653434C43434C44434C49434C56434D5043505843,155
2190 DATA 5059444543444558444559454F52494E43494E58494E594A4D504A53524C44414C44584C44594C53524E4F504F,607
2200 DATA 5241504841504850504C41504C50524F4C524F5252544952545353424353454353454453454953544153545853,78
2210 DATA 54595441585441595453585458415458535459413F3F3F6965756D7D7961712925352D3D3921310A06160E1E90,390
2220 DATA B0F0242C30D01000507018D858B8C9C5D5CDDDD9C1D1E0E4ECC0C4CCC6D6CEDECA884945554D5D594151E6F6EE,322
2230 DATA FEE8C84C6C20A9A5B5ADBDB9A1B1A2A6B6AEBEA0A4B4ACBC4A46564E5EEA0905150D1D190111480868282A2636,476
2240 DATA 2E3E6A66766E7E4060E9E5F5EDFDF9E1F138F87885958D9D99819186968E84948CAAA8BA8A9A98000000000000,463
2250 DATA 000003030303030303030606060606090C0F121215181B1E2124272A2D3033333333333333333636363939393C,735
2260 DATA 3C3C3C3F424545454545454545484848484B4E51515457575757575757575A5A5A5A5A5D5D5D5D5D6060606060,374
2270 DATA 636666666666666666696C6F72757575757578787878787B7E818181818181818184878A8D8D8D8D8D8D8D9090,873
2280 DATA 9093939396999C9FA2A5A800010203040506070001020304050607080102030409090901030909090A09090A0A,751
2290 DATA 0A0A0001020304050607000103000103010203040A0A0001020304050607010203040A0A030B03000102030405,927
2300 DATA 060700010C0305000102030408010203040A00010203040506070A0A0A0A080102030408010203040A0A000102,126
2310 DATA 03040506070A0A0A01020304050607010C030102030A0A0A0A0A0A0A0000000000000000000000000000000000,301
2320 REM * 5940 BYTES

Listing 2.
Assembly listing.

; 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&copy
	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