diff options
-rw-r--r-- | Makefile | 29 | ||||
-rw-r--r-- | da65.txt | 628 | ||||
-rw-r--r-- | equates.inc | 1386 | ||||
-rw-r--r-- | jumpmanjr.cart | bin | 0 -> 16400 bytes | |||
-rw-r--r-- | jumpmanjr.dasm | 7360 | ||||
-rw-r--r-- | jumpmanjr.inc | 68 | ||||
-rw-r--r-- | jumpmanjr.info | 908 | ||||
-rw-r--r-- | jumpmanjr.rom | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | jumpmanjr_manual.pdf | bin | 0 -> 3135749 bytes | |||
-rw-r--r-- | level_descriptors.txt | 127 | ||||
-rw-r--r-- | level_maps.txt | 188 | ||||
-rw-r--r-- | leveldesc.info | 406 | ||||
-rw-r--r-- | main.info | 501 | ||||
-rw-r--r-- | mapping.txt | 8814 | ||||
-rw-r--r-- | mklevelinfo.pl | 91 | ||||
-rw-r--r-- | mkmusiclabels.pl | 15 | ||||
-rw-r--r-- | porting_ideas.txt | 50 |
17 files changed, 20571 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ece7548 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +all: clean jumpmanjr.dasm + +clean: + rm -f jumpmanjr.dasm + +distclean: clean + rm -f jumpmanjr.info leveldesc.info jmjtest.* tmp.lbl 1 2 1.* 2.* atari???.png strace.out + +jumpmanjr.dasm: jumpmanjr.info jumpmanjr.inc + da65 -i jumpmanjr.info + +jumpmanjr.info: main.info leveldesc.info + ( echo '### GENERATED FILE, do not edit, edit main.info and mklevelinfo.pl instead' ;\ + cat main.info leveldesc.info ) > jumpmanjr.info + +leveldesc.info: mklevelinfo.pl + perl mklevelinfo.pl > leveldesc.info + +test: all + cp jumpmanjr.dasm jmjtest.s + ca65 -t none -o jmjtest.o -g jmjtest.s + ld65 -t none -o jmjtest.bin -Ln tmp.lbl --start-addr 0x8000 jmjtest.o + grep -v '\.__' tmp.lbl | sed 's, \., ,' > jmjtest.lbl + @echo + @cmp jumpmanjr.rom jmjtest.bin && echo "=== Binary reassembles correctly" || echo "*** Binary FAILS to reassemble correctly ***" + @echo ; echo "-----------------------" + @echo labels load jmjtest.lbl + @echo "-----------------------" ; echo + @atari800 -nobasic jumpmanjr.cart diff --git a/da65.txt b/da65.txt new file mode 100644 index 0000000..19115f7 --- /dev/null +++ b/da65.txt @@ -0,0 +1,628 @@ + da65 Users Guide + +Ullrich von Bassewitz, +Greg King + +2014-11-23 + + ---------------------------------------------------------------------------- + +da65 is a 6502/65C02 disassembler that is able to read user-supplied information +about its input data, for better results. The output is ready for feeding into +ca65, the macro assembler supplied with the cc65 C compiler. + + ---------------------------------------------------------------------------- + +1. Overview + +2. Usage + + * 2.1 Command line option overview + * 2.2 Command line options in detail + +3. Detailed workings + + * 3.1 Supported CPUs + * 3.2 Attribute map + * 3.3 Labels + * 3.4 Info File + +4. Info File Format + + * 4.1 Comments + * 4.2 Specifying global options + * 4.3 Specifying Ranges + * 4.4 Specifying Labels + * 4.5 Specifying Segments + * 4.6 Specifying Assembler Includes + * 4.7 An Info File Example + +5. Copyright + + ---------------------------------------------------------------------------- + +1. Overview + +da65 is a disassembler for 6502/65C02 code. It is supplied as a utility with the +cc65 C compiler and generates output that is suitable for the ca65 macro +assembler. + +Besides generating output for ca65, one of the design goals was that the user is +able to feed additional information about the code into the disassembler, for +improved results. This information may include the location and size of tables, +and their format. + +One nice advantage of this concept is that disassembly of copyrighted binaries +may be handled without problems: One can just pass the information file for +disassembling the binary, so everyone with a legal copy of the binary can +generate a nicely formatted disassembly with readable labels and other +information. + +2. Usage + +2.1 Command line option overview + +The assembler accepts the following options: + + --------------------------------------------------------------------------- + Usage: da65 [options] [inputfile] + Short options: + -g Add debug info to object file + -h Help (this text) + -i name Specify an info file + -o name Name the output file + -v Increase verbosity + -F Add formfeeds to the output + -S addr Set the start/load address + -V Print the disassembler version + + Long options: + --argument-column n Specify argument start column + --comment-column n Specify comment start column + --comments n Set the comment level for the output + --cpu type Set cpu type + --debug-info Add debug info to object file + --formfeeds Add formfeeds to the output + --help Help (this text) + --hexoffs Use hexadecimal label offsets + --info name Specify an info file + --label-break n Add newline if label exceeds length n + --mnemonic-column n Specify mnemonic start column + --pagelength n Set the page length for the listing + --start-addr addr Set the start/load address + --text-column n Specify text start column + --verbose Increase verbosity + --version Print the disassembler version + --------------------------------------------------------------------------- + +2.2 Command line options in detail + +Here is a description of all the command line options: + +--argument-column n + + Specifies the column where the argument for a mnemonic or pseudo + instruction starts. + +--comment-column n + + Specifies the column where the comment for an instruction starts. + +--comments n + + Set the comment level for the output. Valid arguments are 0..4. Greater + values will increase the level of additional information written to the + output file in form of comments. + +--cpu type + + Set the CPU type. The option takes a parameter, which may be one of + * 6502 + * 6502x + * 65sc02 + * 65c02 + * huc6280 + + 6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU + of the PC engine. Support for the 65816 currently is not available. + +-F, --formfeeds + + Add formfeeds to the generated output. This feature is useful together + with the --pagelength option. If --formfeeds is given, a formfeed is + added to the output after each page. + +-g, --debug-info + + This option adds the .DEBUGINFO command to the output file, so the + assembler will generate debug information when re-assembling the + generated output. + +-h, --help + + Print the short option summary shown above. + +--hexoffs + + Output label offsets in hexadecimal instead of decimal notation. + +-i name, --info name + + Specify an info file. The info file contains global options that may + override or replace command line options plus informations about the + code that has to be disassembled. See the separate section Info File + Format. + +-o name + + Specify a name for an output file. The default is to use stdout, so + without this switch or the corresponding global option OUTPUTNAME, the + output will go to the terminal. + +--label-break n + + Adds a newline if the length of a label exceeds the given length. Note: + If the label would run into the code in the mid column, a linefeed is + always inserted regardless of this setting. + + This option overrides the global option LABELBREAK. + +--mnemonic-column n + + Specifies the column where a mnemonic or pseudo instrcuction is output. + +--pagelength n + + Sets the length of a listing page in lines. After this number of lines, + a new page header is generated. If the --formfeeds is also given, a + formfeed is inserted before generating the page header. + + A value of zero for the page length will disable paging of the output. + +-S addr, --start-addr addr + + Specify the start/load address of the binary code that is going to be + disassembled. The given address is interpreted as an octal value if + preceded with a '0' digit, as a hexadecimal value if preceded with '0x', + '0X', or '$', and as a decimal value in all other cases. If no start + address is specified, $10000 minus the size of the input file is used. + +--text-column n + + Specifies the column where additional text is output. This additional + text consists of the bytes encoded in this line in text representation. + +-v, --verbose + + Increase the disassembler verbosity. Usually only needed for debugging + purposes. You may use this option more than one time for even more + verbose output. + +-V, --version + + Print the version number of the assembler. If you send any suggestions + or bugfixes, please include the version number. + +3. Detailed workings + +3.1 Supported CPUs + +The default (no CPU given on the command line or in the GLOBAL section of the +info file) is the 6502 CPU. The disassembler knows all "official" opcodes for +this CPU. Invalid opcodes are translated into .byte commands. + +With the command line option --cpu, the disassembler may be told to recognize +either the 65SC02 or 65C02 CPUs. The latter understands the same opcodes as the +former, plus 16 additional bit manipulation and bit test-and-branch commands. + +While there is some code for the 65816 in the sources, it is currently +unsupported. + +3.2 Attribute map + +The disassembler works by creating an attribute map for the whole address space +($0000 - $FFFF). Initially, all attributes are cleared. Then, an external info +file (if given) is read. Disassembly is done in several passes. In all passes, +with the exception of the last one, information about the disassembled code is +gathered and added to the symbol and attribute maps. The last pass generates +output using the information from the maps. + +3.3 Labels + +Some instructions may generate labels in the first pass, while most other +instructions do not generate labels, but use them if they are available. Among +others, the branch and jump instructions will generate labels for the target of +the branch in the first pass. External labels (taken from the info file) have +precedence over internally generated ones, They must be valid identifiers as +specified for the ca65 assembler. Internal labels (generated by the +disassembler) have the form Labcd, where abcd is the hexadecimal address of the +label in upper case letters. You should probably avoid using such label names +for external labels. + +3.4 Info File + +The info file is used to pass additional information about the input code to the +disassembler. This includes label names, data areas or tables, and global +options like input and output file names. See the next section for more +information. + +4. Info File Format + +The info file contains lists of specifications grouped together. Each group +directive has an identifying token and an attribute list enclosed in curly +braces. Attributes have a name followed by a value. The syntax of the value +depends on the type of the attribute. String attributes are places in double +quotes, numeric attributes may be specified as decimal numbers or hexadecimal +with a leading dollar sign. There are also attributes where the attribute value +is a keyword; in this case, the keyword is given as-is (without quotes or +anything). Each attribute is terminated by a semicolon. + + group-name { attribute1 attribute-value; attribute2 attribute-value; } + +4.1 Comments + +Comments start with a hash mark (#); and, extend from the position of the mark +to the end of the current line. Hash marks inside of strings will not start a +comment, of course. + +4.2 Specifying global options + +Global options may be specified in a group with the name GLOBAL. The following +attributes are recognized: + +ARGUMENTCOLUMN + + This attribute specifies the column in the output, where the argument + for an opcode or pseudo instruction starts. The corresponding command + line option is --argument-column. + +COMMENTCOLUMN + + This attribute specifies the column in the output, where the comment + starts in a line. It is only used for in-line comments. The + corresponding command line option is --comment-column. + +COMMENTS + + This attribute may be used instead of the --comments option on the + command line. It takes a numerical parameter between 0 and 4. Higher + values increase the amount of information written to the output file in + form of comments. + +CPU + + This attribute may be used instead of the --cpu option on the command + line. For possible values see there. The value is a string and must be + enclosed in quotes. + +HEXOFFS + + The attribute is followed by a boolean value. If true, offsets to labels + are output in hex, otherwise they're output in decimal notation. The + default is false. The attribute may be changed on the command line using + the --hexoffs option. + +INPUTNAME + + The attribute is followed by a string value, which gives the name of the + input file to read. If it is present, the disassembler does not accept + an input file name on the command line. + +INPUTOFFS + + The attribute is followed by a numerical value that gives an offset into + the input file which is skipped before reading data. The attribute may + be used to skip headers or unwanted code sections in the input file. + +INPUTSIZE + + INPUTSIZE is followed by a numerical value that gives the amount of data + to read from the input file. Data beyond INPUTOFFS + INPUTSIZE is + ignored. + +LABELBREAK + + LABELBREAK is followed by a numerical value that specifies the label + length that will force a newline. To have all labels on their own lines, + you may set this value to zero. + + See also the --label-break command line option. A LABELBREAK statement + in the info file will override any value given on the command line. + +MNEMONICCOLUMN + + This attribute specifies the column in the output, where the mnemonic or + pseudo instruction is placed. The corresponding command line option is + --mnemonic-column. + +NEWLINEAFTERJMP + + This attribute is followed by a boolean value. When true, a newline is + inserted after each JMP instruction. The default is false. + +NEWLINEAFTERRTS + + This attribute is followed by a boolean value. When true, a newline is + inserted after each RTS instruction. The default is false. + +OUTPUTNAME + + The attribute is followed by string value, which gives the name of the + output file to write. If it is present, specification of an output file + on the command line using the -o option is not allowed. + + The default is to use stdout for output, so without this attribute or + the corresponding command line option -o the output will go to the + terminal. + +PAGELENGTH + + This attribute may be used instead of the --pagelength option on the + command line. It takes a numerical parameter. Using zero as page length + (which is the default) means that no pages are generated. + +STARTADDR + + This attribute may be used instead of the --start-addr option on the + command line. It takes a numerical parameter. The default for the start + address is $10000 minus the size of the input file (this assumes that + the input file is a ROM that contains the reset and irq vectors). + +TEXTCOLUMN + + This attribute specifies the column, where the data bytes are output + translated into ASCII text. It is only used if COMMENTS is set to at + least 4. The corresponding command line option is --text-column. + +4.3 Specifying Ranges + +The RANGE directive is used to give information about address ranges. The +following attributes are recognized: + +COMMENT + + This attribute is only allowed if a label is also given. It takes a + string as argument. See the description of the LABEL directive for an + explanation. + +END + + This gives the end address of the range. The end address is inclusive, + that means, it is part of the range. Of course, it may not be smaller + than the start address. + +NAME + + This is a convenience attribute. It takes a string argument and will + cause the disassembler to define a label for the start of the range with + the given name. So a separate LABEL directive is not needed. + +START + + This gives the start address of the range. + +TYPE + + This attribute specifies the type of data within the range. The + attribute value is one of the following keywords: + + ADDRTABLE + + The range consists of data and is disassembled as a table + of words (16 bit values). The difference to the WORDTABLE + type is that a label is defined for each entry in the + table. + + BYTETABLE + + The range consists of data and is disassembled as a byte + table. + + CODE + + The range consists of code. + + DBYTETABLE + + The range consists of data and is disassembled as a table + of dbytes (double byte values, 16 bit values with the low + byte containing the most significant byte of the 16 bit + value). + + DWORDTABLE + + The range consists of data and is disassembled as a table + of double words (32 bit values). + + RTSTABLE + + The range consists of data and is disassembled as a table + of words (16 bit values). The values are interpreted as + words that are pushed onto the stack and jump to it via + RTS. This means that they contain address-1 of a function, + for which a label will get defined by the disassembler. + + SKIP + + The range is simply ignored when generating the output + file. Please note that this means that reassembling the + output file will not generate the original file, not only + because the missing piece in between, but also because the + following code will be located on wrong addresses. Output + generated with SKIP ranges will need manual rework. + + TEXTTABLE + + The range consists of readable text. + + WORDTABLE + + The range consists of data and is disassembled as a table + of words (16 bit values). + +4.4 Specifying Labels + +The LABEL directive is used to give names for labels in the disassembled code. +The following attributes are recognized: + +ADDR + + Followed by a numerical value. Specifies the value of the label. + +COMMENT + + Attribute argument is a string. The comment will show up in a separate + line before the label, if the label is within code or data range, or + after the label if it is outside. + + Example output: + + foo := $0001 ; Comment for label named "foo" + + ; Comment for label named "bar" + bar: + +NAME + + The attribute is followed by a string value which gives the name of the + label. Empty names are allowed, in this case the disassembler will + create an unnamed label (see the assembler docs for more information + about unnamed labels). + +SIZE + + This attribute is optional and may be used to specify the size of the + data that follows. If a size greater than 1 is specified, the + disassembler will create labels in the form label+offs for all bytes + within the given range, where label is the label name given with the + NAME attribute, and offs is the offset within the data. + +4.5 Specifying Segments + +The SEGMENT directive is used to specify a segment within the disassembled code. +The following attributes are recognized: + +START + + Followed by a numerical value. Specifies the start address of the + segment. + +END + + Followed by a numerical value. Specifies the end address of the segment. + The end address is the last address that is a part of the segment. + +NAME + + The attribute is followed by a string value which gives the name of the + segment. + +All attributes are mandatory. Segments must not overlap. The disassembler will +change back to the (default) .code segment after the end of each defined +segment. That might not be what you want. As a rule of thumb, if you're using +segments, you should define segments for all disassembled code. + +4.6 Specifying Assembler Includes + +The ASMINC directive is used to give the names of input files containing symbol +assignments in assembler syntax: + + Name = value + Name := value + +The usual conventions apply for symbol names. Values may be specified as hex +(leading $), binary (leading %) or decimal. The values may optionally be signed. + +NOTE: The include file parser is very simple. Expressions are not allowed, and +anything but symbol assignments is flagged as an error (but see the +IGNOREUNKNOWN directive below). + +The following attributes are recognized: + +FILE + + Followed by a string value. Specifies the name of the file to read. + +COMMENTSTART + + The optional attribute is followed by a character constant. It specifies + the character that starts a comment. The default value is a semicolon. + This value is ignored if IGNOREUNKNOWN is true. + +IGNOREUNKNOWN + + This attribute is optional and is followed by a boolean value. It allows + to ignore input lines that don't have a valid syntax. This allows to + read in assembler include files that contain more than just symbol + assignments. Note: When this attribute is used, the disassembler will + ignore any errors in the given include file. This may have undesired + side effects. + +4.7 An Info File Example + +The following is a short example for an info file that contains most of the +directives explained above: + + # This is a comment. It extends to the end of the line + GLOBAL { + OUTPUTNAME "kernal.s"; + INPUTNAME "kernal.bin"; + STARTADDR $E000; + PAGELENGTH 0; # No paging + CPU "6502"; + }; + + # One segment for the whole stuff + SEGMENT { START $E000; END $FFFF; NAME "kernal"; }; + + RANGE { START $E612; END $E631; TYPE Code; }; + RANGE { START $E632; END $E640; TYPE ByteTable; }; + RANGE { START $EA51; END $EA84; TYPE RtsTable; }; + RANGE { START $EC6C; END $ECAB; TYPE RtsTable; }; + RANGE { START $ED08; END $ED11; TYPE AddrTable; }; + + # Zero-page variables + LABEL { NAME "fnadr"; ADDR $90; SIZE 3; }; + LABEL { NAME "sal"; ADDR $93; }; + LABEL { NAME "sah"; ADDR $94; }; + LABEL { NAME "sas"; ADDR $95; }; + + # Stack + LABEL { NAME "stack"; ADDR $100; SIZE 255; }; + + # Indirect vectors + LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ + LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK + LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI + + # Jump table at end of kernal ROM + LABEL { NAME "kscrorg"; ADDR $FFED; }; + LABEL { NAME "kplot"; ADDR $FFF0; }; + LABEL { NAME "kiobase"; ADDR $FFF3; }; + LABEL { NAME "kgbye"; ADDR $FFF6; }; + + # Hardware vectors + LABEL { NAME "hanmi"; ADDR $FFFA; }; + LABEL { NAME "hares"; ADDR $FFFC; }; + LABEL { NAME "hairq"; ADDR $FFFE; }; + +5. Copyright + +da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von Bassewitz. +For usage of the binaries and/or sources, the following conditions do apply: + +This software is provided 'as-is', without any expressed or implied warranty. In +no event will the authors be held liable for any damages arising from the use of +this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/equates.inc b/equates.inc new file mode 100644 index 0000000..9759a8a --- /dev/null +++ b/equates.inc @@ -0,0 +1,1386 @@ +; +; ATARI 800 EQUATE LISTING +; +; (version 20070530_bkw) +; +; This is a heavily modified copy of Appendix A of the Atari System +; Reference Manual (with much info added from Appendix B, and from +; Mapping the Atari and other sources) +; +; +;This listing is based on the original release of Operating System, +;version A. The vectors shown here were not changed in version B. +;New equates for XL and XE models are included and noted. Changes +;from version B to XL/XE are also noted. +; +;Most of the equate names given below are the official Atari +;names. They are in common use but are not mandatory. + +; This file can be included in your assembly source, but it's also +; got a lot of useful human-readable comments. It's meant to serve as +; a "quick reference" to Atari programmers, particularly ones who use +; a cross-assembler on a UNIX-ish platform and a text editor that can +; use "ctags": + +; $ ctags equates.inc +; $ vim mystuff.dasm + +; While in vim, press ^] (control-right-bracket) while sitting on a label, +; to jump to that label's definition in this file. (Also, you can type +; :tag labelname). You can also do completion on the labels in vim by +; typing part of a label and pressing ^N (or Tab, if you use the +; CleverTab script from vimhelp.org) + +; GNU Emacs and XEmacs also support ctags, but I've never used them, so +; I dunno how to do it. I do know that you need to use "Exuberant" ctags, +; not the ctags that comes with emacs (which doesn't grok 6502 asm). + +; If you're using an Atari assembler instead of a cross-assembler, you +; don't want to use this as-is: all the extra comments make it huge, and +; it'll be either too large for the Atari's memory, or at least will take +; a long time to assemble. You can make a comment-less, Atari-compatible +; version like so: + +; perl -lne 's/;.*//; s/\s*$//; print if $_' < equates.inc > small.inc + +; ...then use a8eol to convert it to ATASCII format. + +; 20061028 bkw: Originally downloaded from: + +; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrb.html + +; ...and converted to DASM/ATASM/CA65 format. dasm, atasm, and ca65 use +; similar enough syntax that this file can be used as-is with any of +; them. Unfortunately, this means I can't do conditional assembly in this +; file, since the two assemblers use different semantics... macros are +; even less compatible :( + +; If you use ca65, you need this line in your source: + +;; .FEATURE labels_without_colons + +; before including this file, or else run ca65 with +; "--feature labels_without_colons"). + +; 20070529 bkw: updated, added missing GTIA/POKEY/ANTIC equates, +; documented where the shadows are for those GTIA/POKEY/ANTIC/PIA +; registers that have them. Also added a list of error messages and +; explanation of the cassette buffer layout, and organized the C_* +; CIO constants. Made minor modifications to get this file to assemble +; with ATasm as well as DASM. + +; I have added a few missing equates: this file only +; contained OS ROM locations when I got it. +; I added a few from FMS/DOS as well (e.g. RUNAD and INITAD). + +; XL-specific locations in the original file were duplicate labels +; (e.g. PTIMOT was defined as both $1C and $314), which keeps DASM +; from being able to assemble the file. I prefixed the XL/XL versions +; with "XL_" + +; Also, I've prefixed the CIO command and AUX1 constants with C_, since some +; of them conflicted with other labels in the original version. + +; Areas listed as "unmapped" are literally not connected to anything. +; Trying to read from unmapped address space results in reading whatever +; garbage was on the data bus when the read happened. On my 1200XL, this +; generally results in all 1's ($FF or 255). +; In a 400, 600XL or other Atari with less than 48K of RAM, the missing +; RAM address space is also unmapped. + +; Still TODO: +; - Rest of the DOS/FMS equates +; - Mark 800-ony locations with OSB_ +; - ifdef code, so the user can set the machine type (OSB or XL), +; then refer to e.g. PTIMOT and get either OSB_PTIMOT or XL_PTIMOT +; - Split into separate files? I'd rather not (it's only about 1000 lines) + +; This file's mostly intended for new development. It could also be +; useful for porting old ASM/ED or Mac65 code to DASM, but such code +; may need work... you can always assemble it with ATasm, in that case, +; since it's 99.999% source code compatible with Mac65. + +; References to "APPENDIX C" and such are referring to the Atari System +; Reference Manual, a version of which can be found at: + +; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrtblc.html + +; References to "Mapping" refer to "Mapping the Atari, Revised Edition", +; which can be found at: + +; http://www.atariarchives.org/mapping/index.php + +; I've pasted a few quotes from Mapping into this file; I consider them +; small enough to be covered under the "fair use" provisions of copyright law +; (I am not a lawyer, though). + +; +; +; DEVICE NAMES +; +; +;SCREDT = "E" SCREEN EDITOR +;KBD = "K" KEYBOARD +;DISPLY = "S" DISPLAY +;PRINTR = "P" PRINTER +;CASSET = "C" CASSETTE +;DISK = "D" DISK DRIVE +; +; +; +; STATUS CODES +; +; + +; 20070529 bkw: These are returned as error codes, though various DOSes +; also define their own codes (usually in the range 160-255). +; Errors 2-21 are defined by BASIC. +; Errors 150-154 are defined by the R: (850 or compatible, RS-232) handler. +SUCCES = $01 ; 1 +BRKABT = $80 ; 128 BREAK KEY ABORT +PRVOPN = $82 ; 130 IOCB ALREADY OPEN +NONDEV = $82 ; 130 NONEXISTANT DEVICE +WRONLY = $83 ; 131 OPENED FOR WRITE ONLY +NVALID = $84 ; 132 INVALID COMMAND +NOTOPN = $85 ; 133 DEVICE OR FILE NOT OPEN +BADIOC = $86 ; 134 INVALID IOCB NUMBER +RDONLY = $87 ; 135 OPENED FOR READ ONLY +EOFERR = $88 ; 136 END OF FILE +TRNRCD = $89 ; 137 TRUNCATED RECORD +TIMOUT = $8A ; 138 PERIPHERAL TIME OUT +DNACK = $8B ; 139 DEVICE DOES NOT ACKNOWLEDGE +FRMERR = $8C ; 140 SERIAL BUS FRAMING ERROR +CRSROR = $8D ; 141 CURSOR OUT OF RANGE +OVRRUN = $8E ; 142 SERIAL BUS DATA OVERRUN +CHKERR = $8F ; 143 SERIAL BUS CHECKSUM ERROR +DERROR = $90 ; 144 PERIPHERAL DEVICE ERROR +BADMOD = $91 ; 145 NON EXISTANT SCREEN MODE +FNCNOT = $92 ; 146 FUNCTION NOT IMPLEMENTED +SCRMEM = $93 ; 147 NOT ENOUGH MEMORY FOR SCREEN MODE + +; BASIC error codes (also used by e.g. Basic XL/XE and Turbo BASIC): +;; 2: Insufficient Memory +;; 3: Value Error +;; 4: Too Many Variables +;; 5: String Length Error +;; 6: Out of Data Error +;; 7: Number Greater than 32767 +;; 8: Input Statement Error +;; 9: Array or String DIM Error +;; 10: Argument Stack Overflow +;; 11: Floating Point Overflow or Underflow Error +;; 12: Line Not Found +;; 13: No Matching FOR Statement +;; 14: Line Too Long +;; 15: GOSUB or FOR Line Deleted +;; 16: RETURN Error +;; 17: Garbage Error +;; 18: Invalid String Character +;; 19: LOAD Program Too Long +;; 20: Bad Channel Number +;; 21: LOAD File Error + +; 850/R: error codes: +;; 150: Serial Port Already Open +;; 151: Concurrent Mode Not Enabled +;; 152: Illegal User-Supplied Buffer +;; 153: Active Concurrent Mode Error +;; 154: Concurrent Mode Not Active + +; DOS error codes (DOS 2.0S only; other DOSes may define other errors) +;; 160: Device Number Error +;; 161: Too Many OPEN Files +;; 162: Disk Full +;; 163: Fatal System Error +;; 164: File Number Mismatch +;; 165: Bad File Name +;; 166: POINT Data Length Error +;; 167: File Locked +;; 168: Invalid XIO Command +;; 169: Directory Full +;; 170: File Not Found +;; 171: POINT Invalid +;; 172: DOS 1 File +;; 173: Bad Sector +;; 255: FORMATTING Error (DOS 2.5) + +; +; +; +; +; COMMAND CODES FOR CIO +; +; + +; Command byte goes in ICCOM,x + +;; General-purpose commands: +C_OPEN = $03 ; 3 OPEN (BASIC OPEN) +C_GETREC = $05 ; 5 GET RECORD +C_GETCHR = $07 ; 7 GET BYTE +C_PUTREC = $09 ; 9 WRITE RECORD +C_PUTCHR = $0B ; 11 PUT-BYTE +C_CLOSE = $0C ; 12 +C_STATUS = $0D ; 13 +C_SPECIL = $0E ; 14 BEGINNING OF SPECIAL COMMANDS (aka XIO) +;; Commands for S: device: +C_DRAWLN = $11 ; 17 SCREEN DRAW (BASIC DRAWTO) +C_FILLIN = $12 ; 18 SCREEN FILL +;; Commands for D: device (only when DOS is loaded): +C_RENAME = $20 ; 32 +C_DELETE = $21 ; 33 +C_LOCK = $23 ; 35 +C_UNLOCK = $24 ; 36 +C_POINT = $25 ; 37 +C_NOTE = $26 ; 38 + +; AUX1 modes (ICAX1,x or 2nd parameter of BASIC OPEN command): +C_OPREAD = $04 ; 4 OPEN FOR INPUT +C_OWRITE = $08 ; 8 OPEN FOR OUTPUT +C_APPEND = $09 ; 9 OPEN TO APPEND TO END OF DISK FILE +C_OUPDAT = $0C ; 12 OPEN FOR INPUT AND OUTPUT AT THE SAME TIME +;; D: (DOS) only: +C_OPDIR = $06 ; 6 OPEN TO DISK DIRECTORY +;; S: only: +C_MXDMOD = $10 ; 16 OPEN TO SPLIT SCREEN (MIXED MODE) +C_INSCLR = $20 ; 32 OPEN TO SCREEN BUT DON'T ERASE +;; C: only: +C_NOIRG = $80 ; 128 NO GAP CASSETTE MODE + +;; Command bytes (ICCOM) for the RS-232 (R:) device: +;; +;; Output partial block 32 $20 +;; Control RTS,XMT,DTR 34 $22 +;; Baud, stop bits, word size 36 $24 +;; Translation mode 38 $26 +;; Concurrent mode 40 $28 +;; +;; (see the 850 Interface Manual for details) + + +; SIO command bytes (not part of CIO): +S_DFRMAT = $21 ; 33 FORMAT DISK (RESIDENT DISK HANDLER (RDH)) +S_PTSECT = $50 ; 80 RDH PUT SECTOR +S_GTSECT = $52 ; 82 RDH GET SECTOR +S_DSTAT = $53 ; 83 RDH GET STATUS +S_PSECTV = $57 ; 87 RDH PUT SECTOR AND VERIFY +; Various other SIO commands are supported by different drives + +; 20061028 bkw: CR/EOL not really part of CIO, but useful: +CR = $9B ; 155 CARRIAGE RETURN (EOL) +EOL = CR ; defined in SYSEQU.ASM + +; +IOCBSZ = $10 ; 16 IOCB SIZE +MAXIOC = $80 ; 128 MAX IOCB BLOCK SIZE +IOCBF = $FF ; 255 IOCB FREE +; +LEDGE = $02 ; 2 DEFAULT LEFT MARGIN +REDGE = $27 ; 39 DEFAULT RIGHT MARGIN + +; OS VARIABLES +; +; PAGE 0 +; +LINZBS = $00 ; 0 (800) FOR ORIGINAL DEBUGGER +; $00 0 (XL) RESERVED +NGFLAG = $01 ; 1 (XL) FOR POWER-UP SELF TEST +CASINI = $02 ; 2 +RAMLO = $04 ; 4 POINTER FOR SELF TEST +TRAMSZ = $06 ; 6 TEMPORARY RAM SIZE +TSTDAT = $07 ; 7 TEST DATA +WARMST = $08 ; 8 +BOOTQ = $09 ; 9 SUCCESSFUL BOOT FLAG +; aka BOOT? in the OS source, but some assemblers don't support ? in labels +DOSVEC = $0A ; 10 PROGRAM RUN VECTOR +DOSINI = $0C ; 12 PROGRAM INITIALIZATION +APPMHI = $0E ; 14 DISPLAY LOW LIMIT +POKMSK = $10 ; 16 IRQ ENABLE FLAGS (shadow for IRQEN) +BRKKEY = $11 ; 17 FLAG +RTCLOK = $12 ; 18 3 BYTES, MSB FIRST +BUFADR = $15 ; 21 INDIRECT BUFFER ADDRESS +ICCOMT = $17 ; 23 COMMAND FOR VECTOR +DSKFMS = $18 ; 24 DISK FILE MANAGER POINTER +DSKUTL = $1A ; 26 DISK UTILITY POINTER (DUP.SYS) +PTIMOT = $1C ; 28 (800) PRINTER TIME OUT REGISTER +ABUFPT = $1C ; 28 (XL) RESERVED +PBPNT = $1D ; 29 (800) PRINTER BUFFER POINTER +; $1D ; 29 (XL) RESERVED +PBUFSZ = $1E ; 30 (800) PRINTER BUFFER SIZE +; $1E ; 30 (XL) RESERVED +PTEMP = $1F ; 31 (800) TEMPORARY REGISTER (PTEMP deleted in XL OS) +; $1F ; 31 (XL) RESERVED +ZIOCB = $20 ; 32 ZERO PAGE IOCB +ICHIDZ = $20 ; 32 HANDLER INDEX NUMBER (ID) +ICDNOZ = $21 ; 33 DEVICE NUMBER +ICCOMZ = $22 ; 34 COMMAND +ICSTAZ = $23 ; 35 STATUS +ICBALZ = $24 ; 36 BUFFER POINTER LOW BYTE +ICBAHZ = $25 ; 37 BUFFER POINTER HIGH BYTE +ICPTLZ = $26 ; 38 PUT ROUTINE POINTER LOW +ICPTHZ = $27 ; 39 PUT ROUTINE POINTER HIGH +ICBLLZ = $28 ; 40 BUFFER LENGTH LOW +ICBLHZ = $29 ; 41 +ICAX1Z = $2A ; 42 AUXILIARY INFORMATION BYTE 1 +ICAX2Z = $2B ; 43 +ICSPRZ = $2C ; 44 TWO SPARE BYTES (CIO USE) +ICIDNO = $2E ; 46 IOCB NUMBER X 16 +CIOCHR = $2F ; 47 CHARACTER BYTE FOR CURRENT OPERATION +; +STATUS = $30 ; 48 STATUS STORAGE +CHKSUM = $31 ; 49 SUM WITH CARRY ADDED BACK +BUFRLO = $32 ; 50 DATA BUFFER LOW BYTE +BUFRHI = $33 ; 51 +BFENLO = $34 ; 52 ADDRESS OF LAST BUFFER BYTE +1 (LOW) +BFENHI = $35 ; 53 +CRETRY = $36 ; 54 (800) NUMBER OF COMMAND FRAME RETRIES +XL_LTEMP = $36 ; 54 (XL) LOADER TEMPORARY STORAGE, 2 BYTES +DRETRY = $37 ; 55 (800) DEVICE RETRIES +BUFRFL = $38 ; 56 BUFFER FULL FLAG +RECVDN = $39 ; 57 RECEIVE DONE FLAG +XMTDON = $3A ; 58 TRANSMISSION DONE FLAG +CHKSNT = $3B ; 59 CHECKSUM-SENT FLAG +NOCKSM = $3C ; 60 CHECKSUM-DOES-NOT-FOLLOW-DATA FLAG +BPTR = $3D ; 61 +FTYPE = $3E ; 62 +FEOF = $3F ; 63 +FREQ = $40 ; 64 +; +SOUNDR = $41 ; 65 0=QUIET I/O +CRITIC = $42 ; 66 CRITICAL FUNCTION FLAG, NO DEFFERED VBI +FMSZPG = $43 ; 67 DOS ZERO PAGE, 7 BYTES +CKEY = $4A ; 74 (800) START KEY FLAG +XL_ZCHAIN = $4A ; 74 (XL) HANDLER LOADER TEMP, 2 BYTES +CASSBT = $4B ; 75 (800) CASSETTE BOOT FLAG +DSTAT = $4C ; 76 DISPLAY STATUS +; +ATRACT = $4D ; 77 +DRKMSK = $4E ; 78 ATTRACT MASK +COLRSH = $4F ; 79 ATTRACT COLOR SHIFTER (EORed WITH GRAPHICS) +; +TMPCHR = $50 ; 80 +HOLD1 = $51 ; 81 +LMARGN = $52 ; 82 SCREEN LEFT MARGIN REGISTER +RMARGN = $53 ; 83 SCREEN RIGHT MARGIN +ROWCRS = $54 ; 84 CURSOR ROW +COLCRS = $55 ; 85 CURSOR COLUMN, 2 BYTES +DINDEX = $57 ; 87 DISPLAY MODE +SAVMSC = $58 ; 88 SCREEN ADDRESS +OLDROW = $5A ; 90 CURSOR BEFORE DRAW OR FILL +OLDCOL = $5B ; 91 +OLDCHR = $5D ; 93 DATA UNDER CURSOR +OLDADR = $5E ; 94 CURSOR ADDRESS +XL_FKDEF = $60 ; 96 (XL) FUNCTION KEY DEFINITION POINTER (LSB/MSB) +NEWROW = $60 ; 96 (800) DRAWTO DESTINATION +NEWCOL = $61 ; 97 (800) DRAWTO DESTINATION, 2 BYTES +XL_PALNTS = $62 ; 98 (XL) EUROPE/NORTH AMERICA TV FLAG +LOGCOL = $63 ; 99 LOGICAL LINE COLUMN POINTER +MLTTMP = $66 ; 102 +OPNTMP = $66 ; 102 TEMPORARY STORAGE FOR CHANNEL OPEN +SAVADR = $68 ; 104 +RAMTOP = $6A ; 106 START OF ROM (END OF RAM + 1), HIGH BYTE ONLY +BUFCNT = $6B ; 107 BUFFER COUNT +BUFSTR = $6C ; 108 POINTER USED BY EDITOR +BITMSK = $6E ; 110 POINTER USED BY EDITOR +SHFAMT = $6F ; 111 +ROWAC = $70 ; 112 +COLAC = $72 ; 114 +ENDPT = $74 ; 116 +DELTAR = $76 ; 118 +DELTAC = $77 ; 119 +ROWINC = $79 ; 121 (800) +XL_KEYDEF = $79 ; 121 (XL) KEY DEFINITION POINTER, 2 BYTES +COLINC = $7A ; 122 (800) +SWPFLG = $7B ; 123 NON 0 IF TEXT AND REGULAR RAM IS SWAPPED +HOLDCH = $7C ; 124 CH MOVED HERE BEFORE CTRL AND SHIFT +INSDAT = $7D ; 125 used by S: handler, tmp for char under cursor +COUNTR = $7E ; 126 used by XIO DRAW command (2 bytes) + +; $80 to $FF are free if BASIC and floating point are not used. +; If BASIC is not used, but FP is, $80 to $D0 are still free. +; There is no way to use BASIC without constantly using FP, as all BASIC +; numbers are FP (even "integers" such as line numbers). +ZROFRE = $80 ; 128 FREE ZERO PAGE, 84 BYTES + +; BASIC zero page variables: +LOMEM = $80 ; 128 LSB, BASIC start-of-memory pointer +; $81 ; 129 MSB, LOMEM (not to be confused with the OS's MEMLO!) +VNTP = $82 ; 130 LSB, BASIC start of Variable Name Table pointer +; $83 ; 131 MSB, VNTP +VNTD = $84 ; 132 LSB, BASIC end of Variable Name Table pointer (+1 byte) +; $85 ; 133 MSB, VNTP +VVTP = $86 ; 134 LSB, BASIC start of Variable Value Table pointer +; $87 ; 135 MSB, VVTP +STMTAB = $88 ; 136 LSB, BASIC start of Statement Table pointer +; $89 ; 137 MSB, STMTAB +STMCUR = $8A ; 138 LSB, BASIC current statement pointer +; $8B ; 139 MSB, STMCUR +STARP = $8C ; 140 LSB, BASIC current string/array table pointer +; $8D ; 141 MSB, STARP (also points to end of BASIC program) +RUNSTK = $8E ; 142 LSB, BASIC runtime stack pointer +; $8F ; 143 MSG, RUNSTK +; BASIC and the OS both use the name MEMTOP; I've renamed the BASIC one. +BAS_MEMTOP = $90 ; 144 LSB, pointer to top of BASIC memory +; $91 ; 145 MSB, BAS_MEMTOP +MEOLFLG = $92 ; 146 "modified EOL flag register", whatever that is +; $93 ; 147 listed as "spare" by Mapping's Errata +;COX = $94 ; 148 current output index (?) +POKADR = $95 ; 149 LSB, address of last POKE location +; ; 150 MSB, POKADR + +; Locations $96 to $B5 are used for various purposes by BASIC, +; and most of them are of little or no interest, even for someone +; writing assembly code meant to run as a USR() routine, so I haven't +; bothered listing them all here. See Compute! Books' "Atari BASIC Sourcebook" +; for the gory details. In fact, you can see it here: + +; http://users.telenet.be/kim1-6502/6502/absb.html + +; It's fascinating (at least it is to me)... includes full source code +; to Atari BASIC! + +; DATAD and DATALN are reset to 0 by BASIC RESTORE command. +DATAD = $B6 ; 182 the data element being read (e.g. 10 for 10th item + ; in a DATA statement) +DATALN = $B7 ; 183 LSB current DATA statement line number +; $B8 ; 184 MSB, DATALN +;ERRNUM = $B9 ; 185 Most recent error number. Gets cleared before you + ; can PEEK it; use ERRSAVE instead. +STOPLN = $BA ; 186 LSB, line where a program stopped by STOP/break/error +; $BB ; 187 MSB, STOPLN +; what are $BC and $BD for? +SAVCUR = $BE ; 190 Saves the current line address (LSB?) +; $BF ; 191 presumably, the MSB of SAVCUR? +IOCMD = $C0 ; 192, I/O Command (Mapping Errata) +IODVC = $C1 ; 193, I/O Device (Mapping Errata) +PROMPT = $C2 ; 194, Prompt character (Mapping Errata, presumably INPUT?) +ERRSAVE = $C3 ; 195 Error code that caused a stop or TRAP +;TEMPA = $C4 ; 196 a 2-byte temp +;ZTEMP2 = $C6 ; 198 a 2-byte temp +COLOR = $C8 ; 200 Stores color from COLOR command +PTABW = $C9 ; 201 Number of columns between tab stops + ; (for PRINT with commas, not the TAB key) +LOADFLG = $CA ; 202 Load in progress flag. I can tell you from bitter + ; experience that BASIC clears this often. + +; $CB - $CF are unused by BASIC or the ASM/ED cart. +; $D0 and $D1 are unused by BASIC (does that mean they *are* used by ASM/ED?) + +; $D2 and $D3 are used by BASIC. Mapping Errata calls them the "BASIC +; floating-point work area". They get cleared to 0 by BASIC, probably +; every time a FP number is used (e.g. "POKE 210,1:? PEEK(210)" prints 0). +; The BASIC source code labels $D2 as TVTYPE and VTYPE, and $D3 as +; TVNUM and VNUM. + +; Floating point zero page variables: +FPZRO = $D4 ; 212 FLOATING POINT RAM, 43 BYTES + ; (20070530 bkw: pretty sure that comment is wrong, and + ; should read 44 bytes; see $FF below) +FR0 = $D4 ; 212 FP REGISTER 0 (also used by BASIC for USR() return val) + ; (FR0/FRE/FR1/FR2 are each 6 bytes long) +FRE = $DA ; 218 +FR1 = $E0 ; 224 FP REGISTER 1 +FR2 = $E6 ; 230 FP REGISTER 2 +FRX = $EC ; 236 SPARE +EEXP = $ED ; 237 VALUE OF E +NSIGN = $ED ; 237 SIGN OF FP NUMBER +ESIGN = $EF ; 239 SIGN OF FP EXPONENT +FCHFLG = $F0 ; 240 FIRST CHARACTER FLAG +DIGRT = $F1 ; 241 NUMBER OF DIGITS RIGHT OF DECIMAL POINT +CIX = $F2 ; 242 INPUT INDEX +INBUFF = $F3 ; 243 POINTER TO ASCII FP NUMBER +ZTEMP1 = $F5 ; 245 +ZTEMP4 = $F7 ; 247 +ZTEMP3 = $F9 ; 249 +DEGFLG = $FB ; 251 +RADFLG = $FB ; 251 0=RADIANS, 6=DEGREES +FLPTR = $FC ; 252 POINTER TO BCD FP NUMBER (2 bytes) +FPTR2 = $FE ; 254 maybe a 2nd pointer to an FP number? (2 bytes) +; $FF ; 255 This *definitely* is used by the FP package + ; Try: POKE 255,0:? SIN(1):? PEEK(255) + +; +; PAGE 1 +; +; 65O2 STACK +; +; + +; +; +; PAGE 2 +; +; +; 20070529 bkw: Bytes listed as "spare" should NOT be used for your own +; purposes. They may not really be unused (just undocumented), and/or they +; may be unused on the 800 but not the XL (or vice versa). +INTABS = $0200 ; 512 INTERRUPT RAM +VDSLST = $0200 ; 512 NMI VECTOR +VPRCED = $0202 ; 514 PROCEED LINE IRQ VECTOR +VINTER = $0204 ; 516 INTERRUPT LINE IRQ VECTOR +VBREAK = $0206 ; 518 break key IRQ vector (not in OS rev. A) +VKEYBD = $0208 ; 520 keyboard IRQ vector (not break/console keys) +VSERIN = $020A ; 522 SERIAL INPUT READY IRQ +VSEROR = $020C ; 524 SERIAL OUTPUT READY IRQ +VSEROC = $020E ; 526 SERIAL OUTPUT COMPLETE IRQ +VTIMR1 = $0210 ; 528 TIMER 1 IRQ vector +VTIMR2 = $0212 ; 530 TIMER 2 IRQ vector +VTIMR4 = $0214 ; 532 TIMER 4 IRQ vector +VIMIRQ = $0216 ; 534 IRQ VECTOR +CDTMV1 = $0218 ; 536 COUNTDOWN TIMER 1 vector +CDTMV2 = $021A ; 538 COUNTDOWN TIMER 2 vector +CDTMV3 = $021C ; 540 COUNTDOWN TIMER 3 vector +CDTMV4 = $021E ; 542 COUNTDOWN TIMER 4 vector +CDTMV5 = $0220 ; 544 COUNTDOWN TIMER 5 vector +VVBLKI = $0222 ; 546 immediate VBLANK vector +VVBLKD = $0224 ; 548 deferred VBLANK vector (ignore if CRITIC != 0) +CDTMA1 = $0226 ; 550 COUNTDOWN TIMER 1 JSR ADDRESS +CDTMA2 = $0228 ; 552 COUNTDOWN TIMER 2 JSR ADDRESS +CDTMF3 = $022A ; 554 COUNTDOWN TIMER 3 FLAG +SRTIMR = $022B ; 555 REPEAT TIMER +CDTMF4 = $022C ; 556 COUNTDOWN TIMER 4 FLAG +INTEMP = $022D ; 557 IAN'S TEMP (used by SETVBL routine) +CDTMF5 = $022E ; 558 COUNTDOWN TIMER FLAG 5 +SDMCTL = $022F ; 559 DMACTL SHADOW +SDLSTL = $0230 ; 560 DISPLAY LIST POINTER, LSB (shadow for DLISTL) +SDLSTH = $0231 ; 561 display list pointer, MSB (shadow for DLISTH) +SSKCTL = $0232 ; 562 SKCTL SHADOW +; $0233 ; 563 (800) UNLISTED (Mapping calls this SPARE) +XL_LCOUNT = $0233 ; 563 (XL) LOADER TEMP +LPENH = $0234 ; 564 LIGHT PEN HORIZONTAL (shadow for PENH) +LPENV = $0235 ; 565 LIGHT PEN VERTICAL (shadow for PENV) +; $0236 ; 566 2 SPARE BYTES on OS rev A +VBRKKY = $0236 ; 566 Break key interrupt vector (OS rev B and XL) +BRKKY = VBRKKY ; "OS rev 5" listing calls it this +; $0238 ; 568 (800) SPARE, 2 BYTES +;XL_RELADR = $0238 ; 568 (XL) relocatable loader relative addr, 1200XL only! +XL_VPIRQ = $0238 ; 568 (XL) PBI IRQ vector (not on 1200XL!) +CDEVIC = $023A ; 570 DEVICE COMMAND FRAME BUFFER +CAUX1 = $023C ; 572 DEVICE COMMAND AUX 1 +CAUX2 = $023D ; 573 DEVICE COMMAND AUX 2 +TEMP = $023E ; 574 TEMPORARY STORAGE +ERRFLG = $023F ; 575 DEVICE ERROR FLAG (EXCEPT TIMEOUT) +DFLAGS = $0240 ; 576 FLAGS FROM DISK SECTOR 1 +DBSECT = $0241 ; 577 NUMBER OF BOOT DISK SECTORS +BOOTAD = $0242 ; 578 BOOT LOAD ADDRESS POINTER +COLDST = $0244 ; 580 COLD START FLAG, 1 = COLD START IN PROGRESS +; $0245 ; 581 (800) SPARE +XL_RECLEN = $0245 ; 581 (XL) LOADER +DSKTIM = $0246 ; 582 (800) DISK TIME OUT REGISTER +; $0246 ; 582 (XL) RESERVED, 39 BYTES +LINBUF = $0247 ; 583 (800) CHARACTER LINE BUFFER, 40 BYTES + ; LINBUF was deleted from the XL OS and replaced with: + +; $0247 - $024D are "reserved" on the 1200XL. On other XL's they are: +XL_PDVMSK = $0247 ; 583 shadow for PBI device selection register @ $D1FF +XL_SHPDVS = $0248 ; 584 shadow for PBI register (where??) +XL_PDMSK = $0249 ; 585 PBI interrupt mask +XL_RELADR = $024A ; 586 (XL) LSB, relocatable loader relative addr (NOT 1200XL) +; $024B ; 587 MSB, XL_RELADR +XL_PPTMPA = $024C ; 588 temporaries for relocatable loader +XL_PPTMPX = $024D ; 589 " + +; $024E - $026A are "spare" on all XL/XE's + +; More XL stuff: +XL_CHSALT = $026B ; 619 (XL) CHARACTER SET POINTER (ctrl-F4 on 1200XL) +XL_VSFLAG = $026C ; 620 (XL) FINE SCROLL TEMPORARY +XL_KEYDIS = $026D ; 621 (XL) KEYBOARD DISABLE (ctrl-F1 on 1200XL) +XL_FINE = $026E ; 622 (XL) FINE SCROLL FLAG (POKE 622,255:GR.0) + +GPRIOR = $026F ; 623 P/M PRIORITY AND GTIA MODES (shadow for PRIOR) +;GTIA = $026F ; 623 ; 20070529 bkw: does anyone define this? + +; Game controller shadows (joysticks/paddles) +; Joystick directions and paddle triggers (buttons) are wired to the PIA. +; Joystick triggers (fire buttons) and the actual paddle potentiometers +; are wired to the GTIA. +; If this seems a little odd, that's because it is :) + +; Paddles (potentiometers): +PADDL0 = $0270 ; 624 (XL) 3 MORE PADDLES, (800) 7 MORE PADDLES +PADDL1 = $0271 ; 625 (these are read in BASIC with PADDLE(x) +PADDL2 = $0272 ; 626 (PADDL0-7 are shadows for POT0-7) +PADDL3 = $0273 ; 627 +PADDL4 = $0274 ; 628 (PADDL4-7 are copies of PADDL0-3 on the XL) +PADDL5 = $0275 ; 629 +PADDL6 = $0276 ; 630 +PADDL7 = $0277 ; 631 + +; Joysticks (directions only) +STICK0 = $0278 ; 632 (XL) 1 MORE STICK, (800) 3 MORE STICKS +STICK1 = $0279 ; 633 (these are read in BASIC with STICK(x) +STICK2 = $027A ; 634 (STICK0/1 are shadows for PORTA; STICK2/3 shadows PORTB) +STICK3 = $027B ; 635 +; STICK0 is a shadow for bits 4-7 of PORTA (shifted 4 bits right) +; STICK1 is a shadow for bits 0-3 of PORTA + +; On the 800: +; STICK2 is a shadow for bits 4-7 of PORTB (shifted 4 bits right) +; STICK3 is a shadow for bits 0-3 of PORTB + +; On the XL/XE series: +; STICK2 and STICK3 are copies of STICK0 and STICK1, respectively. + +; In the XL/XE machines, there are only 2 joystick ports, and PORTB +; (formerly joystick ports) is now used to control the MMU. + +; joystick directions are active low (1=not pressed) and decode as: + +; bit direction +; 0 or 4 up +; 1 or 5 down +; 2 or 6 left +; 3 or 7 right + +; A value of $0F in a STICKx register means no direction is being pressed. +; When a direction is pressed, its bit becomes a logic 0, so e.g. $0E means +; someone's moving the joystick up. + +; (bits 4-7 are only used when reading directly from the HW registers, +; PORTA and PORTB). + +; Paddle triggers (buttons) +PTRIG0 = $027C ; 636 (XL) 3 MORE PADDLE TRIGGERS, (800) 7 MORE +PTRIG1 = $027D ; 637 (these are read in BASIC with PTRIG(x)) +PTRIG2 = $027E ; 638 (PTRIG0-3 are shadows for PORTA) +PTRIG3 = $027F ; 639 +PTRIG4 = $0280 ; 640 (PTRIG4-7 are shadows for PORTB on the 800) +PTRIG5 = $0281 ; 641 (they are copies of PTRIG0-3 on the XL) +PTRIG6 = $0282 ; 642 +PTRIG7 = $0283 ; 643 +; In case someone doesn't already know this: The paddle triggers are wired +; to the same pins on the joystick port as the left/right joystick directions. +; Each pair of paddles uses left for the first paddle's trigger and right +; for the second (so PTRIG0/1 are also the left/right bits in STICK0, +; PTRIG2/3 are STICK1, etc). + +; Joystick triggers (buttons) +STRIG0 = $0284 ; 644 (XL) 1 MORE STICK TRIGGER, (800) 3 MORE +STRIG1 = $0285 ; 645 (these are read in BASIC with STRIG(x)) +STRIG2 = $0286 ; 646 (STRIG0-3 are shadows for TRIG0-3) +STRIG3 = $0287 ; 647 + +; C: handler variables: +CSTAT = $0288 ; 648 (800) Cassette status register +; note that CSTAT was deleted from the XL OS, and replaced with: +XL_HIBYTE = $0288 ; 648 (XL) used by relocatable loader +WMODE = $0289 ; 649 used by C: handler (0=read, 128-write) +BLIM = $028A ; 650 cassette buffer data record size +; $028B ; 651 (800) 5 SPARE BYTES (to $028F) +XL_IMASK = $028B ; 651 (XL) used by relocatable loader +XL_JVECK = $028C ; 652 (XL) (Mapping says it's unused) + ; 653 (XL) Presumably the MSB of JVECK (unused?) +XL_NEWADR = $028E ; 654 (XL) LOADER RAM (2 bytes) + +; Misc. S: and/or E: handler variables: +TXTROW = $0290 ; 656 +TXTCOL = $0291 ; 657 +TINDEX = $0293 ; 659 TEXT INDEX +TXTMSC = $0294 ; 660 +TXTOLD = $0296 ; 662 OLD ROW AND OLD COL FOR TEXT, 2 BYTES +; $0298 ; 664 4 SPARE BYTES +TMPX1 = $029C ; 668 (800) +; note that TMPX1 was deleted from the XL OS, and replaced with: +XL_CRETRY = $029C ; 668 (XL) NUMBER OF COMMAND FRAME RETRIES + ; (moved from CRETRY on 800) +SUBTMP = $029E ; 670 +HOLD2 = $029F ; 671 +DMASK = $02A0 ; 672 +TMPLBT = $02A1 ; 673 +ESCFLG = $02A2 ; 674 +TABMAP = $02A3 ; 675 15 BYTE BIT MAP FOR TAB SETTINGS +LOGMAP = $02B2 ; 690 4 BYTE LOGICAL LINE START BIT MAP +INVFLG = $02B6 ; 694 mask for inverse video ($80=inverse, 0=normal) +FILFLG = $02B7 ; 695 FILL DURING DRAW FLAG +TMPROW = $02B8 ; 696 +TMPCOL = $02B9 ; 697 +SCRFLG = $02BB ; 699 SCROLL FLAG +HOLD4 = $02BC ; 700 +HOLD5 = $02BD ; 701 (800) +; note that HOLD5 was deleted from the XL OS, and replaced with: +XL_DRETRY = $02BD ; 701 (XL) NUMBER OF DEVICE RETRIES + ; (moved from DRETRY on 800) +SHFLOC = $02BE ; 702 +BOTSCR = $02BF ; 703 24 NORM, 4 SPLIT + +; Color register shadows (HW registers are in GTIA) +PCOLR0 = $02C0 ; 704 3 MORE PLAYER COLOR REGISTERS (shadows for COLPM0-3) +PCOLR1 = $02C1 ; 705 (missiles use same color regs as same-numbered players!) +PCOLR2 = $02C2 ; 706 +PCOLR3 = $02C3 ; 707 +COLOR0 = $02C4 ; 708 4 MORE GRAPHICS COLOR REGISTERS (shadows for COLPF0-3) +COLOR1 = $02C5 ; 709 (text luminance in GR.0) +COLOR2 = $02C6 ; 710 (text background and chroma in GR.0) +COLOR3 = $02C7 ; 711 +COLOR4 = $02C8 ; 712 (background, shadow for COLBK) +; On boot, system reset, or any time S:/E: devices are opened: +; PCOLR0-3 are initialzed to 0 ($00, black) +; COLOR0 is initialized to 40 ($28, orange) +; COLOR1 is initialized to 202 ($CA, green) +; COLOR2 is initialized to 148 ($94, blue) +; COLOR3 is initialized to 70 ($46, red) +; COLOR4 is initialized to 0 ($00, black) + +; $02C9 713 (800) 23 SPARE BYTES +; XL relocatable handler and other variables: +XL_RUNADR = $02C9 ; 713 (XL) LOADER VECTOR +XL_HIUSED = $02CB ; 715 (XL) LOADER VECTOR +XL_ZHIUSE = $02CD ; 717 (XL) LOADER VECTOR +XL_GBYTEA = $02CF ; 719 (XL) LOADER VECTOR +XL_LOADAD = $02D1 ; 721 (XL) LOADER VECTOR +XL_ZLOADA = $02D3 ; 723 (XL) LOADER VECTOR +XL_DSCTLN = $02D5 ; 725 (XL) DISK SECTOR SIZ +XL_ACMISR = $02D7 ; 727 (XL) RESERVED +XL_KRPDER = $02D9 ; 729 (XL) KEY AUTO REPEAT DELAY +XL_KEYREP = $02DA ; 730 (XL) KEY AUTO REPEAT RATE +XL_NOCLIK = $02DB ; 731 (XL) KEY CLICK DISABLE (ctrl-F3 on 1200XL) +XL_HELPFG = $02DC ; 732 (XL) HELP KEY FLAG +XL_DMASAV = $02DD ; 733 (XL) SDMCTL (DMA) SAVE (ctrl-F2 on 1200XL) +XL_PBPNT = $02DE ; 734 (XL) PRINTER BUFFER POINTER (moved from PBPNT on 800) +XL_PBUFSZ = $02DF ; 735 (XL) PRINTER BUFFER SIZE (moved from PBUFSZ on 800) +; note that PTEMP was deleted from the XL OS + +; DOS/FMS variables: +GLBABS = $02E0 ; 736 GLOBAL VARIABLES, 4 SPARE BYTES (if DOS not loaded) + ; If DOS/FMS is loaded: +RUNAD = $02E0 ; 736 (DOS) Run address for binary file (LSB/MSB) +INITAD = $02E2 ; 736 (DOS) Init address for binary file (LSB/MSB) + +; SYSEQU.ASM defines these: +GOADR = RUNAD +INITADR = INITAD + +; OS variables: +RAMSIZ = $02E4 ; 740 PERMANENT START OF ROM POINTER +MEMTOP = $02E5 ; 741 END OF FREE RAM +MEMLO = $02E7 ; 743 LSB, points to bottom of free memory ($0700 if DOS + ; not booted). Not to be confused with BASIC's LOMEM! +; $02E8 ; 744 MSB of MEMLO + +; $02E9 ; 745 (800) SPARE +XL_HNDLOD = $02E9 ; 745 (XL) HANDLER LOADER FLAG + +DVSTAT = $02EA ; 746 DEVICE STATUS BUFFER, 4 BYTES +CBAUDL = $02EE ; 750 CASSETTE BAUD RATE, 2 BYTES +CRSINH = $02F0 ; 752 1 = INHIBIT CURSOR +KEYDEL = $02F1 ; 753 KEY DELAY AND RATE (aka debounce counter) +CH1 = $02F2 ; 754 prior keyboard character code +CHACT = $02F3 ; 755 (shadow for CHACTL) +CHBAS = $02F4 ; 756 CHARACTER SET POINTER (shadow for CHBASE) + +; These next 4 are located elsewhere on the 800 OS: +XL_NEWROW = $02F5 ; 757 (XL) DRAW DESTINATION +XL_NEWCOL = $02F6 ; 758 (XL) DRAW DESTINATION +XL_ROWINC = $02F8 ; 760 (XL) +XL_COLINC = $02F9 ; 761 (XL) +; $02F5 - $02F9 are "spare" on the 800. + +CHAR = $02FA ; 762 most recent character read/written (screen code) +ATACHR = $02FB ; 763 ATASCII CHARACTER FOR CIO +CH = $02FC ; 764 last key pressed (internal scan code) +FILDAT = $02FC ; 764 COLOR FOR SCREEN FILL +DSPFLG = $02FE ; 766 DISPLAY CONTROL CHARACTERS FLAG +SSFLAG = $02FF ; 767 DISPLAY START/STOP FLAFG + +; +; PAGE 3 +; +; +; RESIDENT DISK HANDLER/SIO INTERFACE +; +; The DCB is used for SIO (serial I/O). +DCB = $0300 ; 768 DEVICE CONTROL BLOCK +DDEVIC = $0300 ; 768 device ID ($31-$38 for D1:-D8:) +DUNIT = $0301 ; 769 disk/device unit numder +DCOMND = $0302 ; 770 device command +DSTATS = $0303 ; 771 status code (set by OS) +DBUFLO = $0304 ; 772 data buffer LSB (set by user) +DBUFHI = $0305 ; 773 data buffer MSB (set by user) +DTIMLO = $0306 ; 774 timeout (set by user, units of 60/64 seconds) +DUNUSE = $0307 ; 775 unused +DBYTLO = $0308 ; 776 number of bytes to transfer, LSB +DBYTHI = $0309 ; 777 number of bytes to transfer, MSB +DAUX1 = $030A ; 778 LSB of sector number (for disk) (set by user) +DAUX2 = $030B ; 779 MSB of sector number (for disk) +TIMER1 = $030C ; 780 INITIAL TIMER VALUE +ADDCOR = $030E ; 782 (800) ADDITION CORRECTION +; note that ADDCOR was deleted from the XL OS, and replaced with: +XL_JMPERS = $030E ; 782 (XL) OPTION JUMPERS +CASFLG = $030F ; 783 CASSETTE MODE WHEN SET +TIMER2 = $0310 ; 784 FINAL VALUE, TIMERS 1 & 2 DETERMINE BAUD RATE +TEMP1 = $0312 ; 786 +XL_TEMP2 = $0313 ; 787 (XL) +TEMP2 = $0314 ; 788 (800) +XL_PTIMOT = $0314 ; 788 (XL) PRINTER TIME OUT +TEMP3 = $0315 ; 789 +SAVIO = $0316 ; 790 SAVE SERIAL IN DATA PORT +TIMFLG = $0317 ; 791 TIME OUT FLAG FOR BAUD RATE CORRECTION +STACKP = $0318 ; 792 SIO STACK POINTER SAVE +TSTAT = $0319 ; 793 TEMPORARY STATUS HOLDER +HATABS = $031A ; 794 HANDLER ADDRESS TABLE, 38 BYTES +MAXDEV = $0321 ; 801 MAXIMUM HANDLER ADDRESS INDEX +XL_PUPBT1 = $033D ; 829 (XL) POWER-UP/RESET +XL_PUPBT2 = $033E ; 830 (XL) POWER-UP/RESET +XL_PUPBT3 = $033F ; 831 (XL) POWER-UP/RESET + +; IOCB's, 8 of them, 16 bytes each. +; Set X register to (IOCB number * 16), and use e.g. ICCOM,x +; +IOCB = $0340 ; 832 ; IOCB base address +ICHID = $0340 ; 832 ; Handler ID (set by OS) +ICDNO = $0341 ; 833 ; Device number (set by OS) +ICCOM = $0342 ; 834 ; Command byte (see C_* constants) (set by user) +ICCMD = ICCOM ; ; alternate name for ICCOM, according to Mapping. +ICSTA = $0343 ; 835 ; Status (set by OS) +ICBAL = $0344 ; 836 ; Buffer address, LSB (set by user) +ICBAH = $0345 ; 837 ; Buffer address, MSB (set by user) +ICPTL = $0346 ; 838 ; Put-one-byte address minus one, LSB (set by OS) +ICPTH = $0347 ; 839 ; Put-one-byte address minus one, MSB (set by OS) +ICBLL = $0348 ; 840 ; Buffer length, LSB (set by user) +ICBLH = $0349 ; 841 ; Buffer length, MSB (set by user) +ICAX1 = $034A ; 842 ; AUX1 byte (2nd param in BASIC OPEN) (set by user) +ICAX2 = $034B ; 843 ; AUX2 byte (4rd param in BASIC OPEN) (set by user) +ICAX3 = $034C ; 844 ; AUX3 byte (used by NOTE/POINT) (set by user) +ICAX4 = $034D ; 845 ; AUX4 byte (used by NOTE/POINT) (set by user) +ICAX5 = $034E ; 846 ; AUX5 byte (used by NOTE/POINT) (set by user) +ICAX6 = $034F ; 847 ; Spare aux byte +; OTHER IOCB's, 112 BYTES ($300 + $10 * channel) + +IOCBLEN = ICAX6-IOCB+1 ; length of one IOCB (from SYSEQU.ASM) + +; Alternative names for the above. I found these in SYSEQU.ASM, as +; distributed with the disk version of Mac65. +ICBADR = ICBAL +ICPUT = ICPTL +ICBLEN = ICBLL +ICAUX1 = ICAX1 +ICAUX2 = ICAX2 +ICAUX3 = ICAX3 +ICAUX4 = ICAX4 +ICAUX5 = ICAX5 +ICAUX6 = ICAX6 + +PRNBUF = $03C0 ; 960 PRINTER BUFFER, 40 BYTES +; $03E8 ; 1000 (800) 21 SPARE BYTES +XL_SUPERF = $03E8 ; 1000 (XL) SCREEN EDITOR +XL_CKEY = $03E9 ; 1001 (XL) START KEY FLAG +XL_CASSBT = $03EA ; 1002 (XL) CASSETTE BOOT FLAG +XL_CARTCK = $03EB ; 1003 (XL) CARTRIDGE CHECKSUM +XL_ACMVAR = $03ED ; 1005 (XL) RESERVED, 10 BYTES (to $03F7) +XL_BASICF = $03F8 ; 1006 (XL) 0 if ROM-BASIC enabled, 1 if not +XL_MINTLK = $03F9 ; 1017 (XL) RESERVED +XL_GINTLK = $03FA ; 1018 (XL) CARTRIDGE INTERLOCK +XL_CHLINK = $03FB ; 1019 (XL) HANDLER CHAIN, 2 BYTES +CASBUF = $03FD ; 1021 CASSETTE BUFFER, 131 BYTES TO $047F + +; Layout of the cassette buffer after a cassette block is read: + +; Baud correction ($55 $55) bytes are located at offsets 0 and 1 +; Control byte is at offset 2 ($03FF): +; Actual data (128 bytes) runs from offset 3 ($0400) to $047F. +; Each cassette frame has a 1 byte checksum after the 128 data bytes, but +; the checksum is NOT stored anywhere in the cassette buffer! + +; CONTROL BYTE VALUES +; Value Meaning +; 250 ($FA) Partial record follows. The actual number of bytes is stored +; in the last byte of the record (CASBUF+130, or $047F). +; 252 ($FC) Record full; 128 bytes follow. +; 254 ($FE) End of File (EOF) record; followed by 128 zero bytes. + +; Boot tapes normally don't have partial or EOF records, but BASIC +; CLOAD/LOAD/LIST and data file tapes do. + +; Mapping the Atari says the first disk boot sector is read into CASBUF also. + +; +; +; PAGE 4 +; +; +USAREA = $0480 ; 1152 128 SPARE BYTES (but used by BASIC) +; +; SEE APPENDIX C FOR PAGES 4 AND 5 USAGE + +; +; +; +; +; PAGE 5 +; +PAGE5 = $0500 ; 1280 127 FREE BYTES +; $057E 1406 129 FREE BYTES IF FLOATING POINT ROUTINES NOT USED +; +;FLOATING POINT NON-ZERO PAGE RAM, NEEDED ONLY IF FP IS USED +; (20070529 bkw: BASIC constantly uses FP! Also, it uses some of these +; addresses for its own purposes.) +; +LBPR1 = $057E ; 1406 LBUFF PREFIX 1 +LBPR2 = $05FE ; 1534 LBUFF PREFIX 2 +LBUFF = $0580 ; 1408 LINE BUFFER +PLYARG = $05E0 ; 1504 POLYNOMIAL ARGUMENTS +FPSCR = $05E6 ; 1510 PLYARG+FPREC +FPSCR1 = $05EC ; 1516 FPSCR+FPREC +FSCR = $05E6 ; 1510 =FPSCR +FSCR1 = $05EC ; 1516 =FPSCR1 +LBFEND = $05FF ; 1535 END OF LBUFF + +; +; PAGE 6 +; +; +PAGE6 = $0600 ; 1536 256 FREE BYTES + +; +; +; PAGE 7 +; +; +BOOTRG = $0700 ; 1792 PROGRAM AREA +; Boot disks (including DOS) are generally loaded here. Also, BASIC RAM +; (variables and program) starts here, if BASIC is booted without DOS. + +; Page 80 (XL): Self-test (aka diagnostic) ROM is mapped at $5000, +; if enabled with bit 7 of PORTB. Normally only happens if you boot without +; BASIC, cartridge, tape, or disk... or if the OS detects a memory error +; during boot. + +; +; +; UPPER ADDRESSES +; +; +RITCAR = $8000 ;32768 RAM IF NO CARTRIDGE (extends to $9FFF) +LFTCAR = $A000 ;40960 RAM IF NO CARTRIDGE (extends to $BFFF) + +; These 2 are from the Atari System Reference Manual, chapter 12: +CARTA = LFTCAR +CARTB = RITCAR + +CARTLOC = $BFFA ;49146 cartridge run address (from SYSEQU.ASM) + +; Carts were originally 8K only when the 400/800 were first released. +; There were plans to release 16K programs on two cartridges, but this +; never happened (the price of 16K ROMs came down, I guess). 16K cartridges +; go in the left slot, but they actually use the address space for both +; the right and left slots. + +; Mapping the Atari has this to say about cartridges: +;; Byte Purpose +;; Left (A) Right(B) +;; 49146 ($BFFA) 40954 ($9FFA) Cartridge start address (low byte) +;; +;; 49147 ($BFFB) 40955 ($9FFB) Cartridge start address (high byte) +;; +;; 49148 ($BFFC) 40956 ($9FFC) Reads zero if a cartridge is +;; inserted, non-zero when no cartridge is present. This information +;; is passed down to the page zero RAM: if the A cartridge is plugged +;; in, then location 6 will read one; if the B cartridge is plugged in, +;; then location 7 will read one; otherwise they will read zero. +;; +;; 49149 ($BFFD) 40957 ($9FFD) Option byte. If BIT 0 equals one, +;; then boot the disk (else there is no disk boot). If BIT 2 equals one, +;; then initialize and start the cartridge (else initialize but do not +;; start). If BIT 7 equals one, then the cartridge is a diagnostic +;; cartridge which will take control, but not initialize the OS (else +;; non-diagnostic cartridge). Diagnostic cartridges were used by +;; Atari in the development of the system and are not available to the +;; public. +;; +;; 49150 ($BFFE) 40958 ($9FFE) Cartridge initialization address +;; low byte. +;; +;; 49151 ($BFFF) 40959 ($9FFF) Cartridge initialization address +;; high byte. This is the address to which the OS will jump during all +;; powerup and RESETs. +;; +;; The OS makes temporary use of locations 36876 to 36896 ($900C to +;; $9020) to set up vectors for the interrupt handler. See the OS +;; listings pages 31 and 81. This code was only used in the +;; development system used to design the Atari. + + +; Page 192 + +C0PAGE = $C000 ;49152 (800) EMPTY, 4K BYTES + ; 20070529 bkw: unmapped address space. + ; Mapping the Atari erroneously lists this as "unused ROM". + ; There are upgrades to the 800 to give 4K of RAM here + ; (for a total of 52K of RAM), or ROM (Omnimon?). + ; Also, there is RAM here if you boot the Translator + ; disk on an XL. + +; (XL) $C000 also contains info about the ROM revision. From Mapping: + +;Bytes 49152-49163 ($C000-$C00B) are used to identify the computer +;and the ROM in the $C000-$DFFF block: +; +;Byte Use +;49152-3/C000-1 Checksum (LSB/MSB) of all the bytes +; in ROM except the checksum bytes +; themselves. +;49154/C002 Revision date, stored in the form +; DDMMYY. This is DD, day, usually $10. +;49155/C003 Revision date, month; usually $05. +;49156/C004 Revision date, year; usually $83. +;49157/C005 Reserved option byte; reads zero for +; the 1200, 800XL, and 130XE. +;49158/C006 Part number in the form AANNNNNN; +; AA is an ASCII character and +; NNNNNN is a four-bit BCD digit. This is +; byte A1. +;49159-62/C007-A Part number, bytes A2, N1-N6 (each +; byte has two N values of four bits +; each). +;49163/C00B Revision number. Mapping author's 800XL and 130XE say 2. + +;C0PAGE = $C000 ;49152 (XL) OS ROM, mostly interrupt handlers +; $C800 51200 (XL) START OF OS ROM +CHORG2 = $CC00 ;52224 (XL) INTERNATIONAL CHARACTER SET + + + +; +; +; HARDWARE REGISTERS +; +; +; SEE REGISTER LIST FOR MORE INFORMATION +; +; + +; GTIA +GTIA = $D000 +HPOSP0 = $D000 ;53248 (W) ; P/M positions (no shadows) +HPOSP1 = $D001 ;53249 (W) +HPOSP2 = $D002 ;53250 (W) +HPOSP3 = $D003 ;53251 (W) +HPOSM0 = $D004 ;53252 (W) +HPOSM1 = $D005 ;53253 (W) +HPOSM2 = $D006 ;53254 (W) +HPOSM3 = $D007 ;53255 (W) +SIZEP0 = $D008 ;53256 (W) ; P/M size regs (no shadows) +SIZEP1 = $D009 ;53257 (W) +SIZEP2 = $D00A ;53258 (W) +SIZEP3 = $D00B ;53259 (W) +SIZEM = $D00C ;53260 (W) +M0PF = $D000 ;53248 (R) ; collision regs (no shadows) +M1PF = $D001 ;53249 (R) +M2PF = $D002 ;53250 (R) +M3PF = $D003 ;53251 (R) +P0PF = $D004 ;53252 (R) +P1PF = $D005 ;53253 (R) +P2PF = $D006 ;53254 (R) +P3PF = $D007 ;53255 (R) +M0PL = $D008 ;53256 (R) +M1PL = $D009 ;53257 (R) +M2PL = $D00A ;53258 (R) +M3PL = $D00B ;53259 (R) +P0PL = $D00C ;53260 (R) +P1PL = $D00D ;53261 (R) +P2PL = $D00E ;53262 (R) +P3PL = $D00F ;53263 (R) +GRAFP0 = $D00D ;53261 (W) ; direct (non-DMA) P/M graphics regs (no shadows) +GRAFP1 = $D00E ;53262 (W) +GRAFP2 = $D00F ;53263 (W) +GRAFP3 = $D010 ;53264 (W) +GRAFM = $D011 ;53265 (W) +TRIG0 = $D010 ;53264 (R) ; Joystick triggers (shadows @ STRIG0-3) +TRIG1 = $D011 ;53265 (R) +TRIG2 = $D012 ;53266 (R) +TRIG3 = $D013 ;53267 (R) +PAL = $D014 ;53268 (R) ; PAL/NTSC detect (no shadow) + ; PAL supposedly moved to XL_PALNTS on XL; what was it + ; replaced with? +COLPM0 = $D012 ;53266 (W) ; P/M colors (shadows @ PCOLR0-3) +COLPM1 = $D013 ;53267 (W) +COLPM2 = $D014 ;53268 (W) +COLPM3 = $D015 ;53269 (W) +COLPF0 = $D016 ;53270 (W) ; Playfield colors (shadows @ COLOR0-3) +COLPF1 = $D017 ;53271 (W) +COLPF2 = $D018 ;53272 (W) +COLPF3 = $D019 ;53273 (W) +COLBK = $D01A ;53274 (W) ; Background color (shadow @ COLOR4) +PRIOR = $D01B ;53275 (W) ; GTIA priority (shadow @ GPRIOR) +GTIAR = $D01B ;53275 (R?) +VDELAY = $D01C ;53276 (W) +GRACTL = $D01D ;53277 (W) +HITCLR = $D01E ;53278 (W), latch +CONSOL = $D01F ;53279 (W=keyclick spkr, R=console keys) + +; $D020 - $D0FF are mirrors of GTIA address space +; $D100 - $D1FF are supposed to be unused (unmapped) on the 800 +; On the XL, $D100 - $D1FF is switched to device memory during PBI I/O + +; POKEY +POKEY = $D200 +; no shadows for AUDC/AUDF +AUDF1 = $D200 ;53760 (W) ; Audio frequency 1 +AUDC1 = $D201 ;53761 (W) ; Audio control 1 (distortion/volume) +AUDF2 = $D202 ;53762 (W) +AUDC2 = $D203 ;53763 (W) +AUDF3 = $D204 ;53764 (W) +AUDC3 = $D205 ;53765 (W) +AUDF4 = $D206 ;53766 (W) +AUDC4 = $D207 ;53767 (W) + +; POT0-7 shadows at PADDL0-7 +POT0 = $D200 ;53760 (R) ; Paddle positions +POT1 = $D201 ;53761 (R) +POT2 = $D202 ;53762 (R) +POT3 = $D203 ;53763 (R) +POT4 = $D204 ;53764 (R) ; pots 3-7 don't exist on XL/XE +POT5 = $D205 ;53765 (R) +POT6 = $D206 ;53766 (R) +POT7 = $D207 ;53767 (R) + +AUDCTL = $D208 ;53768 (W) ; Audio control (no shadow) +ALLPOT = $D208 ;53768 (R) (no shadow) +STIMER = $D209 ;53769 (W) (no shadow) +KBCODE = $D209 ;53769 (R) (shadow @ CH) +SKREST = $D20A ;53770 (W) (latch) +RANDOM = $D20A ;53770 (R) (no shadow) +POTGO = $D20B ;53771 (W) (latch) +; $D20C (53772) is unused +SEROUT = $D20D ;53773 (W) (no shadow) +SERIN = $D20D ;53773 (R) (no shadow) +IRQEN = $D20E ;53774 (W) (shadow @ POKMSK) +IRQST = $D20E ;53774 (R) +SKCTL = $D20F ;53775 (W) (shadow @ SSKCTL) +SKSTAT = $D20F ;53775 (R) + +; $D210 - $D2FF are mirrors of POKEY address space. The "stereo POKEY" +; modification adds a second POKEY chip, usually addressed at $D210. + +; PIA +; No shadow regs for PIA regs +PIA = $D300 +PORTA = $D300 ;54016 +PORTB = $D301 ;54017 +PACTL = $D302 ;54018 +PBCTL = $D303 ;54019 + +; $D304 - $D3FF are mirrors of PIA address space + +; ANTIC +ANTIC = $D400 +DMACTL = $D400 ;54272 (W) (shadow @ SDMCTL) +CHACTL = $D401 ;54273 (W) (shadow @ CHACT) +DLISTL = $D402 ;54274 (W) (shadow @ SDLSTL) +DLISTH = $D403 ;54275 (W) (shadow @ SDLSTH) +HSCROL = $D404 ;54276 (W) (no shadow) +VSCROL = $D405 ;54277 (W) (no shadow) +; $D406 (54278) is unused +PMBASE = $D407 ;54279 (W) (no shadow) +; $D408 (54280) is unused +CHBASE = $D409 ;54281 (W) (shadow @ CHBAS) +WSYNC = $D40A ;54282 (W), latch (data written doesn't matter) +VCOUNT = $D40B ;54283 (R) (no shadow) +PENH = $D40C ;54284 (R) (shadow @ LPENH) +PENV = $D40D ;54285 (R) (shadow @ LPENV) +NMIEN = $D40E ;54286 (W) (no shadow) +NMIRES = $D40F ;54287 (W), latch? +NMIST = $D40F ;54287 (R) (no shadow) + +; $D410 - $D4FF are mirrors of ANTIC address space + +CCNTL = $D500 ;54528 Cartridge control (sometimes used for bankswitching) +; $D500 - $D5FF is supposed to be all be mapped to CCNTL + +; $D600 - $D7FF is unmapped? used by PBI on XL? seems to read all $FF + +; +; FLOATING POINT MATH ROUTINES +; +; From Mapping: +; These entry points are the same on 400/800 and XL OS, though the +; routines themselves are different (bugfixed/optimized for XL) +; Also, on the XL, the $D800 area is bankswitched to PBI device ROM, +; during PBI I/O. Not sure if all of $D800 - $DFFF is switched out +; or just part of it. +AFP = $D800 ;55296 ASCII to Floating Point (FP) conversion. +FASC = $D8E6 ;55526 FP value to ASCII conversion. +IFP = $D9AA ;55722 Integer to FP conversion +FPI = $D9D2 ;55762 FP to Integer conversion +ZFR0 = $DA44 ;55876 Clear FR0 (set all bytes to 0) +ZF1 = $DA46 ;55878 Clear FR1 (set all bytes to 0) (aka AF1 (De Re)) +FSUB = $DA60 ;55904 FP subtract: FR0 = FR0 - FR1 +FADD = $DA66 ;55910 FP add: FR0 = FR0 + FR1 +FMUL = $DADB ;56027 FP multiply: FR0 = FR0 * FR1 +FDIV = $DB28 ;56104 FP divide: FR0 = FR0 / FR1 +PLYEVL = $DD40 ;56640 FP polynomial evaluation +FLD0R = $DD89 ;56713 Load FP number into FR0 from 6502 X/Y registers +FLD0P = $DD8D ;56717 Load FP number into FR0 from FLPTR +FLD1R = $DD98 ;56728 Load FP number into FR1 from 6502 X/Y registers +FLD1P = $DD9C ;56732 Load FP number into FR1 from FLPTR +FST0R = $DDA7 ;56743 Store FP number into 6502 X/Y regs from FR0 +FST0P = $DDAB ;56747 Store FP number from FR0, using FLPTR +FMOVE = $DDB6 ;56758 Move FP number from FR0 into FR1 (FR1 = FR0) +EXP = $DDC0 ;56768 FP base e exponentiation +EXP10 = $DDCC ;56780 FP base 10 exponentiation +LOG = $DECD ;57037 FP natural logarithm +LOG10 = $DED1 ;57041 FP base 10 logarithm + +; +; +; OPERATING SYSTEM +; +; +; MODULE ORIGIN TABLE +; +CHORG = $E000 ;57344 CHARACTER SET, 1K +VECTBL = $E400 ;58368 VECTOR TABLE +VCTABL = $E480 ;58496 RAM VECTOR INITIAL VALUE TABLE +CIOORG = $E4A6 ;58534 CIO HANDLER +INTORG = $E6D5 ;59093 INTERRUPT HANDLER +SIOORG = $E944 ;59716 SIO DRIVER +DSKORT = $EDEA ;60906 DISK HANDLER +PRNORG = $EE78 ;61048 PRINTER HANDLER +CASORG = $EE78 ;61048 CASSETTE HANDLER +MONORG = $F0E3 ;61667 MONITOR/POWER UP MODULE +KBDORG = $F3E4 ;62436 KEYBOARD/DISPLAY HANDLER +; +; +; VECTOR TABLE, CONTAINS ADDRESSES OF CIO ROUTINES IN THE +; FOLLOWING ORDER. THE ADDRESSES IN THE TABLE ARE TRUE ADDRESSES-1 +; +; ADDRESS + 0 OPEN +; + 2 CLOSE +; + 4 GET +; + 6 PUT +; + 8 STATUS +; + A SPECIAL +; + C JMP TO INITIALIZATION +; + F NOT USED +; +; + +; 20070529 bkw: why are they address minus one? because they are called +; via RTS: a JSR actually pushes the return address minus one, and RTS +; increments the address on the stack after popping it. The Atari OS +; "pretends" to have done a JSR by pushing the address-1 on the stack, +; then executes RTS, which "returns" to the correct address. + +EDITRV = $E400 ;58368 EDITOR +SCRENV = $E410 ;58384 SCREEN +KEYBDV = $E420 ;58400 KEYBOARD +PRINTV = $E430 ;58416 PRINTER +CASETV = $E440 ;58432 CASSETTE +; +; ROM VECTORS +; +; 20070529 bkw: These consist of a JMP xxxx instruction in the ROM. +DSKINV = $E453 ;58451 +CIOV = $E456 ;58454 ; Main CIO entry point! +SIOV = $E459 ;58457 ; Main SIO entry point! +SETVBV = $E45C ;58460 +SYSVBV = $E45F ;58463 +VBIVAL = $E460 ;58464 ADR AT VVBLKI (operand of JMP @ $E45F) +XITVBV = $E462 ;58466 EXIT VBI +VBIXVL = $E463 ;58467 ADR AT VVBLKD (operand of JMP @ $E462) +SIOINV = $E465 ;58469 +SENDEV = $E468 ;58472 +INTINV = $E46B ;58475 +CIOINV = $E46E ;58478 +BLKBDV = $E471 ;58481 MEMO PAD MODE (self-test in XL) +WARMSV = $E474 ;58484 ; warmstart (RESET key jumps here) +COLDSV = $E477 ;58487 ; coldstart (reboot) the Atari +RBLOKV = $E47A ;58490 +CSOPIV = $E47D ;58493 + +; SYSEQU.ASM defines this: +CIO = CIOV + +; XL-only entry points: +XL_SELFSV = BLKBDV ; self-test (same entry point as 800 memo pad) +XL_SELFTST = BLKBDV ; alt. name (Mapping) +XL_PUPDIV = $E480 ;58496 (XL) Power-up ATARI logo (1200XL only), or self-test +XL_SLFTSV = $E483 ;58499 (XL) Self-test vector (points to $5000) +XL_PENTV = $E486 ;58502 (XL) Entry to the handler uploaded from peripheral + ; or disk (is this for the PBI?) +XL_PHUNLV = $E489 ;58505 (XL) Entry to uploaded handler unlink (PBI?) +XL_PHINIV = $E48C ;58508 (XL) Entry to uploaded handler init (PBI?) +XL_GPDVV = $E48F ;58511 (XL) General-purpose parallel device handler + ; (copy to HATABS to use) + +;;;;; Here endeth the list of official mnemonics + +; Mapping has this to say about the XL ROMs: +;Byte Use +;65518/FFEE Revision date D1 and D2 (four-bit BCD) +;65519/FFEF Revision date M1 and M2 +;65520/FFF0 Revision date Y1 and Y2 +;65521/FFF1 Option byte; should read 1 for the +; 1200XL (Mapping author's 800XL reads 2) +;65522-26/FFF2-6 Part number in the form AANNNNNN +;65527/FFF7 Revision number (again, mine reads 2) +;65528-9/FFF8-9 Checksum, bytes (LSB/MSB) +; There don't seem to be any known mnemonics for the above... + +; 20061120 bkw: display list stuff. These are not official Atari mnemonics, +; but they *are* somewhat based on the "Checkers Demo" by Carol Shaw, +; in the Atari Hardware Manual (she didn't define all these, and she didn't +; use the "DL_" prefix, probably because her assembler was limited to +; 6-character labels and/or didn't support the underscore). + +; blank lines, 1-8 scanlines high +DL_BLANK1 = $00 +DL_BLANK2 = $10 +DL_BLANK3 = $20 +DL_BLANK4 = $30 +DL_BLANK5 = $40 +DL_BLANK6 = $50 +DL_BLANK7 = $60 +DL_BLANK8 = $70 + +; modifier bits.. +DL_VSCROLL = $10 +DL_HSCROLL = $20 +DL_LMS = $40 +DL_DLI = $80 + +; graphics modes (these are the BASIC modes) +; If you're more familiar with the ANTIC modes, nobody's forcing you +; to use these :) +DL_GR0 = $02 +DL_GR1 = $06 +DL_GR2 = $07 +DL_GR3 = $08 +DL_GR4 = $09 +DL_GR5 = $0A +DL_GR6 = $0B +DL_GR7 = $0D +DL_GR8 = $0F +DL_GR12 = $04 ; GR. 12-15 only supported by GRAPHICS command on XL/XE, +DL_GR13 = $05 ; but they exist on all ANTIC revisions +DL_GR14 = $0C +DL_GR15 = $0E ; AKA "graphics 7.5" +; No GRAPHICS mode for ANTIC $03 (true descender) mode + +; jump instructions +DL_JMP = $01 ; jump without vertical blank (used to skip over 1K boundary) +DL_JVB = $41 ; jump & wait for VBLANK (end of display list) + +; How to use the above: here's a sample display list for GR.0, with a DLI +; on screen line 10. + +; dlist: +; ; 4*8 = 32 blank lines at start of display +; byte DL_BLANK8, DL_BLANK8, DL_BLANK8, DL_BLANK8 +; +; byte DL_GR0 | DL_LMS ; display GR.0 line, and load screen memory address.. +; word screen_ram ; ...from our screen memory (declared elsewhere) +; +; ; 8 more GR.0 lines +; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0 +; +; byte DL_GR0 | DL_DLI ; another GR.0 line, with the DLI bit enabled +; +; ; lines 11-24 (14 more GR.0 bytes) +; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0 +; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0 +; +; ; that's 24 lines, so finish with a VBLANK +; byte DL_JVB ; jump (and wait), to... +; word dlist ; ...the beginning. diff --git a/jumpmanjr.cart b/jumpmanjr.cart Binary files differnew file mode 100644 index 0000000..218dbe3 --- /dev/null +++ b/jumpmanjr.cart diff --git a/jumpmanjr.dasm b/jumpmanjr.dasm new file mode 100644 index 0000000..b856ad9 --- /dev/null +++ b/jumpmanjr.dasm @@ -0,0 +1,7360 @@ +; da65 V2.15 - Git 104f898 +; Created: 2016-08-29 14:55:43 +; Input file: jumpmanjr.rom +; Page: 1 + + + .setcpu "6502" + +; ---------------------------------------------------------------------------- +L0000 := $0000 +dm_ypos := $0054 ; see draw_map and level_maps.txt +dm_xpos := $0055 ; see draw_map and level_maps.txt +SAVMSC := $0058 ; OS's idea of the start of screen memory [redundant to set here?] +dm_count := $00BE ; graphics object definition is this long +dm_length := $00BF ; see draw_map and level_maps.txt +dm_progctr := $00C0 ; see draw_map and level_maps.txt +dm_objptr := $00C2 ; see draw_map and level_maps.txt +dm_screen_addr := $00C4 ; points to byte to write gfx data to +dm_x_with_offset:= $00C6 ; graphics object X offset, plus dm_xpos +dm_y_with_offset:= $00C7 ; graphics object Y offset, plus dm_xpos +dm_delta_x := $00C9 ; see draw_map and level_maps.txt +dm_delta_y := $00CA ; see draw_map and level_maps.txt +zp_temp1 := $00CB ; used for (zp,y) addressing, also for checking console keys in vblank_imm_isr +FR1 := $00E0 +VDSLST := $0200 +VKEYBD := $0208 +VKEYBD_hi := $0209 +SDMCTL := $022F +GPRIOR := $026F +PCOLR0 := $02C0 +PCOLR1 := $02C1 +PCOLR2 := $02C2 +PCOLR3 := $02C3 +COLOR0 := $02C4 +COLOR1 := $02C5 +COLOR2 := $02C6 +COLOR3 := $02C7 +COLOR4 := $02C8 +CHBAS := $02F4 +jiffy_timer_1 := $061A ; gets incremented every frame +jiffy_timer_2 := $061B ; gets incremented every frame +speed_jiffy_timer:= $061E ; counts 0..initial_speed +player_speed := $0624 +initial_speed := $0625 +bonus_jiffy_timer:= $0626 ; gets incremented every frame when playing a level, bonus-=100 when this reaches 0 +playing_level := $0627 ; 0 = not playing, non-0 = playing +sfx_lock := $062F ; lets other code know cue_sfx is still running? not 100% sure +player_delta_x := $0630 ; amount to move jumpman this frame (1 or $FF aka -1) +player_delta_y := $0631 ; amount to move jumpman this frame (1 or $FF aka -1) +joystick_disabled:= $0632 ; nonzero = jumpman can't move (title screen or materialization, etc) +joystick_state := $0633 ; last PORTA read (bottom 4 bits), or 0 if joystick_disabled +trigger_disabled:= $0634 ; nonzero = jumpman can't jump (he's already jumping, or title screen or materialization, etc) +trigger_state := $0635 ; last TRIG0 read (0 = pressed) +sfx_ptr := $063C +sfx_slot_tempo := $063E ; tempo of this sfx +sfx_slot_timer := $063F +sfx_slot_duration:= $0646 +sfx_slot_freq := $0647 +sfx_slot_curpos := $064E ; address we've got to so far, playing this sfx +sfx_tempo_tmp := $0661 ; ?? +dlist_shadow_lo := $06AC ; stored in DLISTL if dlist_shadow_hi nonzero +dlist_shadow_hi := $06AD ; stored in DLISTH if nonzero +dli_vec_shadow_lo:= $06AE ; stored in VDSLST if dli_vec_shadow_hi nonzero +dli_vec_shadow_hi:= $06AF ; stored in VDSLST if nonzero +collision_save := $06B0 ; save_collisions copies GTIA collision regs $D000-$d00f here +option_key_vec := $06C0 ; vblank_imm_isr jumps thru here if option key pressed +select_key_vec := $06C2 ; vblank_imm_isr jumps thru here if select key pressed +start_key_vec := $06C4 ; vblank_imm_isr jumps thru here if start key pressed +option_key_enabled:= $06C6 ; non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr) +select_key_enabled:= $06C7 ; non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr) +start_key_enabled:= $06C8 ; non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr) +L06DF := $06DF +L06E0 := $06E0 +L06E3 := $06E3 +L06E6 := $06E6 +randomizer_mode := $06F3 ; only after beating levels 1-12 in order +number_of_players:= $06F4 ; 0 for single-player game, otherwise range 1-3 (2 to 4 players) +level := $06F6 +speed_value := $06F9 ; decoded speed (1-8) +current_player := $06FE ; *think* this ranges 1-4, not 0-3 +score := $0700 +lives := $070A +work_level_desc := $0780 ; first 2 bytes are level number in screencodes +work_level_sub0 := $0782 ; a subroutine +work_level_sub1 := $0784 ; a subroutine +work_level_sub2 := $0786 ; a subroutine +work_level_sub3 := $0788 ; a subroutine +work_level_num_bombs:= $078A ; number of bombs to pick up on this level +work_level_bullet_chance:= $078B ; 0 = no bullets +work_level_y_start:= $078C ; jumpman starting Y position +work_level_x_start:= $078D ; jumpman starting X position +work_level_offs_14:= $078E ; points to $0600 +work_level_points_per_bomb:= $0790 ; points awarded per bomb pickup (always $64 aka 100) +work_level_time_bonus:= $0791 ; amount of time bonus at start of level +work_level_offs_19:= $0793 ; always $00 +work_level_unkn_table0:= $0794 ; pointer to ROM table or $06xx +work_level_map0 := $0796 ; map data +work_level_map1 := $0798 ; map data +work_level_map2 := $079A ; map data +work_level_unkn_table1:= $079C ; unknown, pointer to a ROM table or $0000 +work_level_offs_30:= $079E ; always $0000 +work_level_sub4 := $07A0 ; $06E6 for most levels, or else a ROM subroutine +work_level_sub5 := $07A2 ; $06E6 for some levels, or else a ROM subroutine +work_level_sub6 := $07A4 ; always $9740 aka game_main_loop +work_level_sub_eol:= $07A6 ; called at end of level (all bombs picked up). $06E6 for all but level07 +work_level_offs_40:= $07A8 ; all zeroes +work_level_offs_46:= $07AE ; unknown +work_level_offs_55:= $07B7 ; unknown, always $00 $00 $00 +work_level_offs_58:= $07BA ; unknown, not a ROM address +work_level_offs_60:= $07BC ; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +cur_level_desc := $07C0 ; first 2 bytes are level number in screencodes +cur_level_sub0 := $07C2 ; a subroutine +cur_level_sub1 := $07C4 ; a subroutine +cur_level_sub2 := $07C6 ; a subroutine +cur_level_sub3 := $07C8 ; a subroutine +cur_level_num_bombs:= $07CA ; number of bombs to pick up on this level +cur_level_bullet_chance:= $07CB ; 0 = no bullets +cur_level_y_start:= $07CC ; jumpman starting Y position +cur_level_x_start:= $07CD ; jumpman starting X position +cur_level_offs_14:= $07CE ; points to $0600 +cur_level_points_per_bomb:= $07D0 ; points awarded per bomb pickup (always $64 aka 100) +cur_level_time_bonus:= $07D1 ; amount of time bonus at start of level +cur_level_offs_19:= $07D3 ; always $00 +cur_level_unkn_table0:= $07D4 ; pointer to ROM table or $06xx +cur_level_map0 := $07D6 ; map data +cur_level_map1 := $07D8 ; map data +cur_level_map2 := $07DA ; map data +cur_level_unkn_table1:= $07DC ; unknown, pointer to a ROM table or $0000 +cur_level_offs_30:= $07DE ; always $0000 +cur_level_sub4 := $07E0 ; $06E6 for most levels, or else a ROM subroutine +cur_level_sub5 := $07E2 ; $06E6 for some levels, or else a ROM subroutine +cur_level_sub6 := $07E4 ; always $9740 aka game_main_loop +cur_level_sub_eol:= $07E6 ; called at end of level (all bombs picked up). $06E6 for all but level07 +cur_level_offs_40:= $07E8 ; all zeroes +cur_level_offs_46:= $07EE ; unknown +cur_level_offs_55:= $07F7 ; unknown, always $00 $00 $00 +cur_level_offs_58:= $07FA ; unknown, not a ROM address +cur_level_offs_60:= $07FC ; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +L0830 := $0830 +game_display_list:= $0881 ; display list for game board +pm_memory := $2800 +HPOSP0_minus_two:= $CFFE +HPOSP3 := $D003 +HPOSM0 := $D004 +HPOSM1 := $D005 +HPOSM2 := $D006 +HPOSM3 := $D007 +SIZEP2 := $D00A +SIZEP3 := $D00B +SIZEM := $D00C +TRIG0 := $D010 +GRAFM := $D011 +COLPM0 := $D012 +COLPM1 := $D013 +COLPF0 := $D016 +COLPF1 := $D017 +COLPF2 := $D018 +COLPF3 := $D019 +COLBK := $D01A +PRIOR := $D01B +GRACTL := $D01D +HITCLR := $D01E +CONSOL := $D01F +AUDF1_minus_two := $D1FE +AUDF1_minus_one := $D1FF +AUDF1 := $D200 +AUDC1 := $D201 +AUDF2 := $D202 +AUDC2 := $D203 +AUDF3 := $D204 +AUDC3 := $D205 +AUDF4 := $D206 +AUDC4 := $D207 +AUDCTL := $D208 +KBCODE := $D209 +RANDOM := $D20A +IRQEN := $D20E +SKCTL := $D20F +PORTA := $D300 +DMACTL := $D400 +DLISTL := $D402 +DLISTH := $D403 +HSCROL := $D404 +PMBASE := $D407 +CHBASE := $D409 +WSYNC := $D40A +NMIEN := $D40E +SETVBV := $E45C +XITVBV := $E462 +; ---------------------------------------------------------------------------- +; the entry point for parsing the level map and drawing graphics from it. see level_maps.txt. +draw_map_jv: + jmp draw_map ; 8000 4C 49 80 LI. + +; ---------------------------------------------------------------------------- +L8003: jmp cue_sfx_lowprior ; 8003 4C 40 82 L@. + +; ---------------------------------------------------------------------------- +; setup to play sfx +cue_sfx_jv: + jmp cue_sfx ; 8006 4C 55 82 LU. + +; ---------------------------------------------------------------------------- +; gets called after the level is drawn & the intro music stops, and also during the level (?) +xxx_level_something_jv: + jmp xxx_level_something ; 8009 4C 00 86 L.. + +; ---------------------------------------------------------------------------- +L800C: jmp L8CBC ; 800C 4C BC 8C L.. + +; ---------------------------------------------------------------------------- +L800F: jmp L867E ; 800F 4C 7E 86 L~. + +; ---------------------------------------------------------------------------- +; bottom 2 GR.1 lines on the game board +update_status_window_jv: + jmp update_status_window ; 8012 4C 94 86 L.. + +; ---------------------------------------------------------------------------- +; for some reason there are 2 copies of the display list, at $0800 and $0881 +setup_gameboard_dlist_jv: + jmp setup_gameboard_dlist ; 8015 4C 00 9B L.. + +; ---------------------------------------------------------------------------- +; setup to play whichever music is in A reg, using 5-byte sfx stuct +cue_music_jv: + jmp cue_music ; 8018 4C 92 8F L.. + +; ---------------------------------------------------------------------------- +; called after level-intro music is finished playing +enable_joystick_jv: + jmp enable_joystick ; 801B 4C 75 87 Lu. + +; ---------------------------------------------------------------------------- +; clear the gameboard screen memory (called before drawing a level, natch) +clear_screen_mem_jv: + jmp clear_screen_mem ; 801E 4C 14 87 L.. + +; ---------------------------------------------------------------------------- +; bonus -= 100; +decrement_time_bonus_jv: + jmp decrement_time_bonus ; 8021 4C CE 8D L.. + +; ---------------------------------------------------------------------------- +init_page_7_jv: + jmp init_page_7 ; 8024 4C 5C 9A L\. + +; ---------------------------------------------------------------------------- +L8027: jmp L9AAA ; 8027 4C AA 9A L.. + +; ---------------------------------------------------------------------------- +L802A: jmp LBA00 ; 802A 4C 00 BA L.. + +; ---------------------------------------------------------------------------- +level_finished_jv: + jmp level_finished ; 802D 4C 00 8E L.. + +; ---------------------------------------------------------------------------- +; just lost your last life +crumble_gameboard_jv: + jmp crumble_gameboard ; 8030 4C 00 8D L.. + +; ---------------------------------------------------------------------------- +L8033: jmp L87A0 ; 8033 4C A0 87 L.. + +; ---------------------------------------------------------------------------- +L8036: jmp L8B23 ; 8036 4C 23 8B L#. + +; ---------------------------------------------------------------------------- + jmp L8B2D ; 8039 4C 2D 8B L-. + +; ---------------------------------------------------------------------------- +L803C: jmp L8AE0 ; 803C 4C E0 8A L.. + +; ---------------------------------------------------------------------------- +; 3 unused jump vectors, all pointed to the same RTS +unused_vecs: + jmp unused_vec_rts ; 803F 4C 48 80 LH. + +; ---------------------------------------------------------------------------- + jmp unused_vec_rts ; 8042 4C 48 80 LH. + +; ---------------------------------------------------------------------------- + jmp unused_vec_rts ; 8045 4C 48 80 LH. + +; ---------------------------------------------------------------------------- +; unused jump vectors point here +unused_vec_rts: + rts ; 8048 60 ` + +; ---------------------------------------------------------------------------- +; the entry point for parsing the level map and drawing graphics from it. see level_maps.txt. caller must set $C0/$C1 to the address of the map data. modders beware: bogus map data can & will cause infinite loops. +draw_map: + ldy #$00 ; 8049 A0 00 .. +; $C0/$C1 points to $A300 (level00_desc) on the first call +dm_get_opcode: + lda (dm_progctr),y ; 804B B1 C0 .. +; map opcodes: $FC = jump, $FF = end, $FD = set drawing direction, $FE = select graphics object +dm_switch_opcode: + cmp #$FC ; 804D C9 FC .. + bcc dm_draw_gfx ; 804F 90 3F .? + beq dm_jump ; 8051 F0 09 .. + cmp #$FD ; 8053 C9 FD .. + beq dm_delta ; 8055 F0 14 .. + cmp #$FE ; 8057 C9 FE .. + beq dm_obj ; 8059 F0 28 .( +; handle gfx_end opcode +dm_fallthru: + rts ; 805B 60 ` + +; ---------------------------------------------------------------------------- +; handle gfx_jump opcode +dm_jump:iny ; 805C C8 . + lda (dm_progctr),y ; 805D B1 C0 .. + pha ; 805F 48 H + iny ; 8060 C8 . + lda (dm_progctr),y ; 8061 B1 C0 .. + sta dm_progctr+1 ; 8063 85 C1 .. + pla ; 8065 68 h + sta dm_progctr ; 8066 85 C0 .. + jmp draw_map ; 8068 4C 49 80 LI. + +; ---------------------------------------------------------------------------- +; handle gfx_delta opcode +dm_delta: + iny ; 806B C8 . + lda (dm_progctr),y ; 806C B1 C0 .. + sta dm_delta_x ; 806E 85 C9 .. + iny ; 8070 C8 . + lda (dm_progctr),y ; 8071 B1 C0 .. + sta dm_delta_y ; 8073 85 CA .. +; all the other opcode handlers jump here +dm_next_opcode: + lda dm_progctr ; 8075 A5 C0 .. + clc ; 8077 18 . + adc #$03 ; 8078 69 03 i. + sta dm_progctr ; 807A 85 C0 .. + bcc draw_map ; 807C 90 CB .. + inc dm_progctr+1 ; 807E E6 C1 .. + jmp draw_map ; 8080 4C 49 80 LI. + +; ---------------------------------------------------------------------------- +; handle gfx_object opcode +dm_obj: iny ; 8083 C8 . + lda (dm_progctr),y ; 8084 B1 C0 .. + sta dm_objptr ; 8086 85 C2 .. + iny ; 8088 C8 . + lda (dm_progctr),y ; 8089 B1 C0 .. + sta dm_objptr+1 ; 808B 85 C3 .. + jmp dm_next_opcode ; 808D 4C 75 80 Lu. + +; ---------------------------------------------------------------------------- +; handle gfx_draw opcode +dm_draw_gfx: + sta dm_xpos ; 8090 85 55 .U + iny ; 8092 C8 . + lda (dm_progctr),y ; 8093 B1 C0 .. + sta dm_ypos ; 8095 85 54 .T + iny ; 8097 C8 . + lda (dm_progctr),y ; 8098 B1 C0 .. + sta dm_length ; 809A 85 BF .. +; loop 'dm_length' times +dm_draw_loop: + jsr dm_draw_obj ; 809C 20 B4 80 .. + dec dm_length ; 809F C6 BF .. + beq dm_next_opcode ; 80A1 F0 D2 .. + lda dm_delta_x ; 80A3 A5 C9 .. + clc ; 80A5 18 . + adc dm_xpos ; 80A6 65 55 eU + sta dm_xpos ; 80A8 85 55 .U + lda dm_delta_y ; 80AA A5 CA .. + clc ; 80AC 18 . + adc dm_ypos ; 80AD 65 54 eT + sta dm_ypos ; 80AF 85 54 .T + jmp dm_draw_loop ; 80B1 4C 9C 80 L.. + +; ---------------------------------------------------------------------------- +; draw current object at current x/y position +dm_draw_obj: + ldy #$00 ; 80B4 A0 00 .. +; object definition ends with $FF +dm_draw_obj_loop: + lda (dm_objptr),y ; 80B6 B1 C2 .. + cmp #$FF ; 80B8 C9 FF .. + bne dm_obj_to_screen ; 80BA D0 01 .. + rts ; 80BC 60 ` + +; ---------------------------------------------------------------------------- +; actually write the object's pixels to screen memory. quite hairy. +dm_obj_to_screen: + sta dm_count ; 80BD 85 BE .. + iny ; 80BF C8 . + clc ; 80C0 18 . + lda (dm_objptr),y ; 80C1 B1 C2 .. + adc dm_xpos ; 80C3 65 55 eU + sta dm_x_with_offset ; 80C5 85 C6 .. + iny ; 80C7 C8 . + clc ; 80C8 18 . + lda (dm_objptr),y ; 80C9 B1 C2 .. + adc dm_ypos ; 80CB 65 54 eT + sta dm_y_with_offset ; 80CD 85 C7 .. + iny ; 80CF C8 . +; calculate 40 * dm_y_with_offset + dm_x_with_offset + screen mem address, store in dm_screen_addr +calc_screen_addr: + lda #$28 ; 80D0 A9 28 .( + sta $BD ; 80D2 85 BD .. + lda #$00 ; 80D4 A9 00 .. + sta dm_screen_addr ; 80D6 85 C4 .. + ldx #$08 ; 80D8 A2 08 .. +L80DA: lsr $BD ; 80DA 46 BD F. + bcc L80E1 ; 80DC 90 03 .. + clc ; 80DE 18 . + adc dm_y_with_offset ; 80DF 65 C7 e. +L80E1: ror a ; 80E1 6A j + ror dm_screen_addr ; 80E2 66 C4 f. + dex ; 80E4 CA . + bne L80DA ; 80E5 D0 F3 .. + clc ; 80E7 18 . + adc SAVMSC+1 ; 80E8 65 59 eY + sta dm_screen_addr+1 ; 80EA 85 C5 .. + lda dm_x_with_offset ; 80EC A5 C6 .. + lsr a ; 80EE 4A J + ror $C8 ; 80EF 66 C8 f. + lsr a ; 80F1 4A J + ror $C8 ; 80F2 66 C8 f. + clc ; 80F4 18 . + adc dm_screen_addr ; 80F5 65 C4 e. + sta dm_screen_addr ; 80F7 85 C4 .. + bcc L80FD ; 80F9 90 02 .. + inc dm_screen_addr+1 ; 80FB E6 C5 .. +L80FD: asl $C8 ; 80FD 06 C8 .. + rol a ; 80FF 2A * + asl $C8 ; 8100 06 C8 .. + rol a ; 8102 2A * + and #$03 ; 8103 29 03 ). + sta $C8 ; 8105 85 C8 .. +L8107: lda (dm_objptr),y ; 8107 B1 C2 .. + sta $BD ; 8109 85 BD .. + lda $C8 ; 810B A5 C8 .. + lsr $BD ; 810D 46 BD F. + rol a ; 810F 2A * + lsr $BD ; 8110 46 BD F. + rol a ; 8112 2A * + sta $BD ; 8113 85 BD .. + iny ; 8115 C8 . + tya ; 8116 98 . + pha ; 8117 48 H + ldy #$00 ; 8118 A0 00 .. + ldx $C8 ; 811A A6 C8 .. + lda (dm_screen_addr),y ; 811C B1 C4 .. + and gr7_and_masks,x ; 811E 3D 53 81 =S. + ldx $BD ; 8121 A6 BD .. + ora gr7_or_masks,x ; 8123 1D 43 81 .C. + sta (dm_screen_addr),y ; 8126 91 C4 .. + pla ; 8128 68 h + tay ; 8129 A8 . + inc $C8 ; 812A E6 C8 .. + lda $C8 ; 812C A5 C8 .. + cmp #$04 ; 812E C9 04 .. + bcc L813C ; 8130 90 0A .. + lda #$00 ; 8132 A9 00 .. + sta $C8 ; 8134 85 C8 .. + inc dm_screen_addr ; 8136 E6 C4 .. + bne L813C ; 8138 D0 02 .. + inc dm_screen_addr+1 ; 813A E6 C5 .. +L813C: dec dm_count ; 813C C6 BE .. + bne L8107 ; 813E D0 C7 .. + jmp dm_draw_obj_loop ; 8140 4C B6 80 L.. + +; ---------------------------------------------------------------------------- +gr7_or_masks: + .byte $00,$80,$40,$C0,$00,$20,$10,$30 ; 8143 00 80 40 C0 00 20 10 30 ..@.. .0 + .byte $00,$08,$04,$0C,$00,$02,$01,$03 ; 814B 00 08 04 0C 00 02 01 03 ........ +gr7_and_masks: + .byte $3F,$CF,$F3,$FC ; 8153 3F CF F3 FC ?... +; ---------------------------------------------------------------------------- +; we have 4 slots (because POKEY has 4 voices), X counts down by 2 from 10 to 2 (at 0, the loop exits) +sfx_player_entry: + ldx #$0A ; 8157 A2 0A .. + lda sfx_lock ; 8159 AD 2F 06 ./. + beq next_sfx_slot ; 815C F0 01 .. +sfx_exit: + rts ; 815E 60 ` + +; ---------------------------------------------------------------------------- +next_sfx_slot: + dex ; 815F CA . + dex ; 8160 CA . + beq sfx_exit ; 8161 F0 FB .. +; skip it, if slot is inactive +is_slot_active: + lda sfx_slot_tempo,x ; 8163 BD 3E 06 .>. + beq next_sfx_slot ; 8166 F0 F7 .. +L8168: lda sfx_slot_timer,x ; 8168 BD 3F 06 .?. + beq sfx_next_note ; 816B F0 10 .. + dec sfx_slot_timer,x ; 816D DE 3F 06 .?. + cmp sfx_slot_duration,x ; 8170 DD 46 06 .F. + bne next_sfx_slot ; 8173 D0 EA .. + lda #$00 ; 8175 A9 00 .. + sta AUDF1_minus_one,x ; 8177 9D FF D1 ... + jmp next_sfx_slot ; 817A 4C 5F 81 L_. + +; ---------------------------------------------------------------------------- +sfx_next_note: + lda sfx_slot_curpos,x ; 817D BD 4E 06 .N. + sta zp_temp1 ; 8180 85 CB .. + lda sfx_slot_curpos+1,x ; 8182 BD 4F 06 .O. + sta zp_temp1+1 ; 8185 85 CC .. + ldy #$00 ; 8187 A0 00 .. + lda (zp_temp1),y ; 8189 B1 CB .. + cmp #$04 ; 818B C9 04 .. + bcs sfx_play_note ; 818D B0 77 .w + cmp #$01 ; 818F C9 01 .. + beq sfx_change_tempo ; 8191 F0 1B .. + cmp #$02 ; 8193 C9 02 .. + beq sfx_jump ; 8195 F0 31 .1 + cmp #$03 ; 8197 C9 03 .. + beq sfx_play_rest ; 8199 F0 03 .. + jmp sfx_finished ; 819B 4C 26 82 L&. + +; ---------------------------------------------------------------------------- +; y==0 on entry +sfx_play_rest: + tya ; 819E 98 . + sta AUDF1_minus_one,x ; 819F 9D FF D1 ... + iny ; 81A2 C8 . + lda (zp_temp1),y ; 81A3 B1 CB .. + sta sfx_slot_timer,x ; 81A5 9D 3F 06 .?. + jsr inc_sfx_pos ; 81A8 20 31 82 1. + jmp L8168 ; 81AB 4C 68 81 Lh. + +; ---------------------------------------------------------------------------- +; y==0 on entry +sfx_change_tempo: + iny ; 81AE C8 . + lda (zp_temp1),y ; 81AF B1 CB .. + sta sfx_slot_freq,x ; 81B1 9D 47 06 .G. + iny ; 81B4 C8 . + lda (zp_temp1),y ; 81B5 B1 CB .. + sta sfx_slot_duration,x ; 81B7 9D 46 06 .F. + jsr inc_sfx_pos ; 81BA 20 31 82 1. + inc sfx_slot_curpos,x ; 81BD FE 4E 06 .N. + bne L8168 ; 81C0 D0 A6 .. + inc sfx_slot_curpos+1,x ; 81C2 FE 4F 06 .O. + jmp L8168 ; 81C5 4C 68 81 Lh. + +; ---------------------------------------------------------------------------- +; I *think* this jumps to a different sfx address... +sfx_jump: + iny ; 81C8 C8 . + lda (zp_temp1),y ; 81C9 B1 CB .. + sta sfx_slot_curpos,x ; 81CB 9D 4E 06 .N. + iny ; 81CE C8 . + lda (zp_temp1),y ; 81CF B1 CB .. + sta sfx_slot_curpos+1,x ; 81D1 9D 4F 06 .O. + iny ; 81D4 C8 . + lda $065E,x ; 81D5 BD 5E 06 .^. + beq L81EE ; 81D8 F0 14 .. + dec $065E,x ; 81DA DE 5E 06 .^. + bne sfx_next_note ; 81DD D0 9E .. + lda $0656,x ; 81DF BD 56 06 .V. + sta sfx_slot_curpos,x ; 81E2 9D 4E 06 .N. + lda $0657,x ; 81E5 BD 57 06 .W. + sta sfx_slot_curpos+1,x ; 81E8 9D 4F 06 .O. + jmp sfx_next_note ; 81EB 4C 7D 81 L}. + +; ---------------------------------------------------------------------------- +L81EE: nop ; 81EE EA . + lda (zp_temp1),y ; 81EF B1 CB .. + sta $065E,x ; 81F1 9D 5E 06 .^. + lda zp_temp1 ; 81F4 A5 CB .. + clc ; 81F6 18 . + adc #$04 ; 81F7 69 04 i. + sta $0656,x ; 81F9 9D 56 06 .V. + lda zp_temp1+1 ; 81FC A5 CC .. + adc #$00 ; 81FE 69 00 i. + sta $0657,x ; 8200 9D 57 06 .W. + jmp sfx_next_note ; 8203 4C 7D 81 L}. + +; ---------------------------------------------------------------------------- +; y==0, a>=4 on entry +sfx_play_note: + sta AUDF1_minus_two,x ; 8206 9D FE D1 ... + iny ; 8209 C8 . + lda (zp_temp1),y ; 820A B1 CB .. + sta sfx_slot_timer,x ; 820C 9D 3F 06 .?. + lda sfx_slot_freq,x ; 820F BD 47 06 .G. + sta AUDF1_minus_one,x ; 8212 9D FF D1 ... + clc ; 8215 18 . + lda sfx_slot_curpos,x ; 8216 BD 4E 06 .N. + adc #$02 ; 8219 69 02 i. + sta sfx_slot_curpos,x ; 821B 9D 4E 06 .N. + bcc L8223 ; 821E 90 03 .. + inc sfx_slot_curpos+1,x ; 8220 FE 4F 06 .O. +L8223: jmp L8168 ; 8223 4C 68 81 Lh. + +; ---------------------------------------------------------------------------- +; done playing this sfx, free up the slot, X-indexed +sfx_finished: + lda #$00 ; 8226 A9 00 .. + sta sfx_slot_tempo,x ; 8228 9D 3E 06 .>. + sta AUDF1_minus_one,x ; 822B 9D FF D1 ... + jmp next_sfx_slot ; 822E 4C 5F 81 L_. + +; ---------------------------------------------------------------------------- +; point to next byte in current sfx slot indexed by X +inc_sfx_pos: + clc ; 8231 18 . + lda sfx_slot_curpos,x ; 8232 BD 4E 06 .N. + adc #$02 ; 8235 69 02 i. + sta sfx_slot_curpos,x ; 8237 9D 4E 06 .N. + bcc inc_done ; 823A 90 03 .. + inc sfx_slot_curpos+1,x ; 823C FE 4F 06 .O. +inc_done: + rts ; 823F 60 ` + +; ---------------------------------------------------------------------------- +; if cue_sfx not already in progress, setup to play sfx at (sfx_slot_tempo, sfx_lock) tempo (?) A +cue_sfx_lowprior: + pha ; 8240 48 H + lda sfx_ptr+1 ; 8241 AD 3D 06 .=. +cue_ok: beq L8248 ; 8244 F0 02 .. + pla ; 8246 68 h + rts ; 8247 60 ` + +; ---------------------------------------------------------------------------- +L8248: lda sfx_slot_tempo ; 8248 AD 3E 06 .>. + sta sfx_ptr ; 824B 8D 3C 06 .<. + lda sfx_slot_timer ; 824E AD 3F 06 .?. + sta sfx_ptr+1 ; 8251 8D 3D 06 .=. + pla ; 8254 68 h +; setup to play sfx at *sfx_ptr, tempo (?) A +cue_sfx:sta sfx_tempo_tmp ; 8255 8D 61 06 .a. + inc sfx_lock ; 8258 EE 2F 06 ./. + ldx #$0A ; 825B A2 0A .. +L825D: dex ; 825D CA . + dex ; 825E CA . + beq L8281 ; 825F F0 20 . + lda sfx_slot_tempo,x ; 8261 BD 3E 06 .>. + bne L825D ; 8264 D0 F7 .. +L8266: lda sfx_ptr ; 8266 AD 3C 06 .<. + sta sfx_slot_curpos,x ; 8269 9D 4E 06 .N. + lda sfx_ptr+1 ; 826C AD 3D 06 .=. + sta sfx_slot_curpos+1,x ; 826F 9D 4F 06 .O. + lda sfx_tempo_tmp ; 8272 AD 61 06 .a. + sta sfx_slot_tempo,x ; 8275 9D 3E 06 .>. +cue_done: + lda #$00 ; 8278 A9 00 .. + sta sfx_ptr+1 ; 827A 8D 3D 06 .=. + dec sfx_lock ; 827D CE 2F 06 ./. + rts ; 8280 60 ` + +; ---------------------------------------------------------------------------- +L8281: ldx #$0A ; 8281 A2 0A .. +L8283: dex ; 8283 CA . + dex ; 8284 CA . + beq cue_done ; 8285 F0 F1 .. + lda sfx_slot_tempo,x ; 8287 BD 3E 06 .>. + cmp sfx_tempo_tmp ; 828A CD 61 06 .a. + bcc L8266 ; 828D 90 D7 .. + jmp L8283 ; 828F 4C 83 82 L.. + +; ---------------------------------------------------------------------------- + .byte $82 ; 8292 82 . +position_missiles: + ldx #$05 ; 8293 A2 05 .. +L8295: dex ; 8295 CA . + beq missiles_done ; 8296 F0 45 .E + lda $069A,x ; 8298 BD 9A 06 ... + cmp $06A2,x ; 829B DD A2 06 ... + beq L82A6 ; 829E F0 06 .. + sta $06A2,x ; 82A0 9D A2 06 ... + sta HPOSP3,x ; 82A3 9D 03 D0 ... +L82A6: lda $06A6,x ; 82A6 BD A6 06 ... + cmp $069E,x ; 82A9 DD 9E 06 ... + beq L8295 ; 82AC F0 E7 .. + tay ; 82AE A8 . + lda $2B00,y ; 82AF B9 00 2B ..+ + and missiles_mask_table_minus_one,x ; 82B2 3D DF 82 =.. + sta $2B00,y ; 82B5 99 00 2B ..+ + lda $2B01,y ; 82B8 B9 01 2B ..+ + and missiles_mask_table_minus_one,x ; 82BB 3D DF 82 =.. + sta $2B01,y ; 82BE 99 01 2B ..+ + lda $069E,x ; 82C1 BD 9E 06 ... + sta $06A6,x ; 82C4 9D A6 06 ... + tay ; 82C7 A8 . + lda $2B00,y ; 82C8 B9 00 2B ..+ + ora L82E3,x ; 82CB 1D E3 82 ... + sta $2B00,y ; 82CE 99 00 2B ..+ + lda $2B01,y ; 82D1 B9 01 2B ..+ + ora L82E3,x ; 82D4 1D E3 82 ... + sta $2B01,y ; 82D7 99 01 2B ..+ + jmp L8295 ; 82DA 4C 95 82 L.. + +; ---------------------------------------------------------------------------- +missiles_done: +missiles_mask_table_minus_one:= * + 2 + jmp position_players ; 82DD 4C E9 82 L.. + +; ---------------------------------------------------------------------------- +missiles_mask_table: + .byte $FC,$F3,$CF ; 82E0 FC F3 CF ... +L82E3: .byte $3F,$03,$0C,$30,$C0 ; 82E3 3F 03 0C 30 C0 ?..0. +; ---------------------------------------------------------------------------- +position_done: + rts ; 82E8 60 ` + +; ---------------------------------------------------------------------------- +; X counts down 5..1 (starts at 6, immediately decremented, and loop is done with 0). zp_temp1 is ZP pointer to the current player or missile being written to ($2f00..$2b00, or p3/p2/p1/p0/missiles). +position_players: + lda #$00 ; 82E9 A9 00 .. + sta zp_temp1 ; 82EB 85 CB .. + lda #$30 ; 82ED A9 30 .0 + sta zp_temp1+1 ; 82EF 85 CC .. + ldx #$06 ; 82F1 A2 06 .. +L82F3: dec zp_temp1+1 ; 82F3 C6 CC .. + dex ; 82F5 CA . + beq position_done ; 82F6 F0 F0 .. + lda $0668,x ; 82F8 BD 68 06 .h. + beq L82F3 ; 82FB F0 F6 .. + lda $067C,x ; 82FD BD 7C 06 .|. + cmp $068B,x ; 8300 DD 8B 06 ... + beq position_pm_vert ; 8303 F0 1D .. + sta $068B,x ; 8305 9D 8B 06 ... + sta HPOSP0_minus_two,x ; 8308 9D FE CF ... + cpx #$01 ; 830B E0 01 .. + bne position_pm_vert ; 830D D0 13 .. + tay ; 830F A8 . +; position the 4 missiles side-by-side +position_player_5: + sty HPOSM3 ; 8310 8C 07 D0 ... + iny ; 8313 C8 . + iny ; 8314 C8 . + sty HPOSM2 ; 8315 8C 06 D0 ... + iny ; 8318 C8 . + iny ; 8319 C8 . + sty HPOSM1 ; 831A 8C 05 D0 ... + iny ; 831D C8 . + iny ; 831E C8 . + sty HPOSM0 ; 831F 8C 04 D0 ... +position_pm_vert: + lda $0690,x ; 8322 BD 90 06 ... + cmp $0681,x ; 8325 DD 81 06 ... + bne L8338 ; 8328 D0 0E .. + lda $0686,x ; 832A BD 86 06 ... + cmp $0695,x ; 832D DD 95 06 ... + beq L82F3 ; 8330 F0 C1 .. + sta $0695,x ; 8332 9D 95 06 ... + lda $0690,x ; 8335 BD 90 06 ... +L8338: sta zp_temp1 ; 8338 85 CB .. + lda $0677,x ; 833A BD 77 06 .w. + sta $CF ; 833D 85 CF .. + lda #$00 ; 833F A9 00 .. + tay ; 8341 A8 . +; write zeroes to unused portion of this player/missile +clear_pm: + sta (zp_temp1),y ; 8342 91 CB .. + iny ; 8344 C8 . + cpy $CF ; 8345 C4 CF .. + bne clear_pm ; 8347 D0 F9 .. + lda $0681,x ; 8349 BD 81 06 ... + sta $0690,x ; 834C 9D 90 06 ... + sta zp_temp1 ; 834F 85 CB .. + lda $066D,x ; 8351 BD 6D 06 .m. + sta $CD ; 8354 85 CD .. + lda $0672,x ; 8356 BD 72 06 .r. + sta $CE ; 8359 85 CE .. + ldy $0686,x ; 835B BC 86 06 ... + clc ; 835E 18 . +L835F: dey ; 835F 88 . + beq L8370 ; 8360 F0 0E .. + lda $CF ; 8362 A5 CF .. + adc $CD ; 8364 65 CD e. + sta $CD ; 8366 85 CD .. + bcc L835F ; 8368 90 F5 .. + inc $CE ; 836A E6 CE .. + clc ; 836C 18 . + jmp L835F ; 836D 4C 5F 83 L_. + +; ---------------------------------------------------------------------------- +L8370: lda ($CD),y ; 8370 B1 CD .. + sta (zp_temp1),y ; 8372 91 CB .. + iny ; 8374 C8 . + dec $CF ; 8375 C6 CF .. + bne L8370 ; 8377 D0 F7 .. + jmp L82F3 ; 8379 4C F3 82 L.. + +; ---------------------------------------------------------------------------- +init_hardware: + ldx #$18 ; 837C A2 18 .. +; movement_direction_table+31 should read data_table_85de-1, da65 isn't perfect yet +init_page6_loop: + lda movement_direction_table+31,x ; 837E BD DD 85 ... + sta $05FF,x ; 8381 9D FF 05 ... + dex ; 8384 CA . + bne init_page6_loop ; 8385 D0 F7 .. + stx AUDCTL ; 8387 8E 08 D2 ... + lda #$28 ; 838A A9 28 .( + sta PMBASE ; 838C 8D 07 D4 ... +; std playfield, enable players + missiles, single-line p/m res, DMA enabled +set_dma_ctl: + lda #$3E ; 838F A9 3E .> + sta SDMCTL ; 8391 8D 2F 02 ./. + sta DMACTL ; 8394 8D 00 D4 ... + lda #$11 ; 8397 A9 11 .. +; priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles) +init_set_prior: + sta GPRIOR ; 8399 8D 6F 02 .o. + sta PRIOR ; 839C 8D 1B D0 ... + lda #$03 ; 839F A9 03 .. + sta SKCTL ; 83A1 8D 0F D2 ... + sta GRACTL ; 83A4 8D 1D D0 ... + lda #$09 ; 83A7 A9 09 .. + sta player_speed ; 83A9 8D 24 06 .$. + lda #$4C ; 83AC A9 4C .L + sta L06E0 ; 83AE 8D E0 06 ... + lda #$20 ; 83B1 A9 20 . + sta L06E3 ; 83B3 8D E3 06 ... +; store an RTS at $06E6, which will get JSR'ed to by unused level subroutines +store_rts: + lda #$60 ; 83B6 A9 60 .` + sta L06E6 ; 83B8 8D E6 06 ... +; use character set at $9e00 aka charset +set_char_base: + lda #$9E ; 83BB A9 9E .. + sta CHBAS ; 83BD 8D F4 02 ... + sta CHBASE ; 83C0 8D 09 D4 ... + lda #$9D ; 83C3 A9 9D .. + sta $0674 ; 83C5 8D 74 06 .t. + sta $0675 ; 83C8 8D 75 06 .u. + lda #$E8 ; 83CB A9 E8 .. + sta $0670 ; 83CD 8D 70 06 .p. + sta $066A ; 83D0 8D 6A 06 .j. + sta $066B ; 83D3 8D 6B 06 .k. + lda #$0A ; 83D6 A9 0A .. + sta $0679 ; 83D8 8D 79 06 .y. + inc $067A ; 83DB EE 7A 06 .z. + lda #$00 ; 83DE A9 00 .. + sta VKEYBD ; 83E0 8D 08 02 ... + sta SAVMSC ; 83E3 85 58 .X + sta $D5 ; 83E5 85 D5 .. + lda #$30 ; 83E7 A9 30 .0 +; tell OS that screen memory starts at $3000 +set_savmsc: + sta SAVMSC+1 ; 83E9 85 59 .Y + lda #$9C ; 83EB A9 9C .. +; VKEYBD now points to $9c00 aka keyboard_isr +set_vkeybd: + sta VKEYBD_hi ; 83ED 8D 09 02 ... + ldx #$07 ; 83F0 A2 07 .. +L83F2: lda L8405,x ; 83F2 BD 05 84 ... + sta $06D8,x ; 83F5 9D D8 06 ... + dex ; 83F8 CA . + bne L83F2 ; 83F9 D0 F7 .. + ldy #$0D ; 83FB A0 0D .. + ldx #$84 ; 83FD A2 84 .. + lda #$06 ; 83FF A9 06 .. +; VVBLKI now points to $840d aka vblank_imm_isr +set_vvblki: + jsr SETVBV ; 8401 20 5C E4 \. + cld ; 8404 D8 . +L8405: rts ; 8405 60 ` + +; ---------------------------------------------------------------------------- +data_8406: + .byte $FE,$49,$9C,$00,$00,$01,$FF ; 8406 FE 49 9C 00 00 01 FF .I..... +; ---------------------------------------------------------------------------- +; service immediate vblank interrupt +vblank_imm_isr: + ldx #$09 ; 840D A2 09 .. +; update color regs from shadow regs (X ranges 1 to 9, GRAFM+1 is COLPM0, $2bf+1 is PCOLR0) +update_color_regs: + lda $02BF,x ; 840F BD BF 02 ... + sta GRAFM,x ; 8412 9D 11 D0 ... + dex ; 8415 CA . + bne update_color_regs ; 8416 D0 F7 .. + inc $0619 ; 8418 EE 19 06 ... + bne L841F ; 841B D0 02 .. + inc $A2 ; 841D E6 A2 .. +L841F: inc jiffy_timer_1 ; 841F EE 1A 06 ... + inc jiffy_timer_2 ; 8422 EE 1B 06 ... + inc $061C ; 8425 EE 1C 06 ... + lda $061C ; 8428 AD 1C 06 ... + and #$01 ; 842B 29 01 ). + sta $061C ; 842D 8D 1C 06 ... + lda #$00 ; 8430 A9 00 .. + sta $0621 ; 8432 8D 21 06 .!. + sta $0622 ; 8435 8D 22 06 .". + sta $06FD ; 8438 8D FD 06 ... + inc $061D ; 843B EE 1D 06 ... + inc speed_jiffy_timer ; 843E EE 1E 06 ... + lda player_speed ; 8441 AD 24 06 .$. + cmp #$09 ; 8444 C9 09 .. + bcs L847E ; 8446 B0 36 .6 + lda $061D ; 8448 AD 1D 06 ... + cmp player_speed ; 844B CD 24 06 .$. + bcc L846E ; 844E 90 1E .. + lda #$00 ; 8450 A9 00 .. + sta $061D ; 8452 8D 1D 06 ... + inc $0621 ; 8455 EE 21 06 .!. + inc $061F ; 8458 EE 1F 06 ... + inc $0620 ; 845B EE 20 06 . . + lda $061F ; 845E AD 1F 06 ... + and #$01 ; 8461 29 01 ). + sta $061F ; 8463 8D 1F 06 ... + lda $0620 ; 8466 AD 20 06 . . + and #$03 ; 8469 29 03 ). + sta $0620 ; 846B 8D 20 06 . . +L846E: lda speed_jiffy_timer ; 846E AD 1E 06 ... + cmp initial_speed ; 8471 CD 25 06 .%. + bcc L847E ; 8474 90 08 .. + lda #$00 ; 8476 A9 00 .. + sta speed_jiffy_timer ; 8478 8D 1E 06 ... + inc $0622 ; 847B EE 22 06 .". +L847E: lda playing_level ; 847E AD 27 06 .'. + beq no_dec_bonus ; 8481 F0 08 .. + inc bonus_jiffy_timer ; 8483 EE 26 06 .&. + bne no_dec_bonus ; 8486 D0 03 .. + jsr decrement_time_bonus_jv ; 8488 20 21 80 !. +no_dec_bonus: + lda $0619 ; 848B AD 19 06 ... + and #$07 ; 848E 29 07 ). + bne check_joystick_enabled ; 8490 D0 12 .. + inc $0628 ; 8492 EE 28 06 .(. + lda $0628 ; 8495 AD 28 06 .(. + and #$07 ; 8498 29 07 ). + sta $0628 ; 849A 8D 28 06 .(. + tax ; 849D AA . + lda data_table_85b6,x ; 849E BD B6 85 ... + sta $062A ; 84A1 8D 2A 06 .*. +; read the joystick if not disabled +check_joystick_enabled: + lda joystick_disabled ; 84A4 AD 32 06 .2. + beq read_joystick ; 84A7 F0 03 .. + jmp store_joystick_state ; 84A9 4C B1 84 L.. + +; ---------------------------------------------------------------------------- +; always joystick #1 (all players use the same joystick and pass it around) +read_joystick: + lda PORTA ; 84AC AD 00 D3 ... + and #$0F ; 84AF 29 0F ). +; store bottom 4 bits of PORTA, or 0 if joystick_disabled +store_joystick_state: + sta joystick_state ; 84B1 8D 33 06 .3. + asl a ; 84B4 0A . + tax ; 84B5 AA . + lda movement_direction_table,x ; 84B6 BD BE 85 ... + sta player_delta_x ; 84B9 8D 30 06 .0. + lda movement_direction_table+1,x ; 84BC BD BF 85 ... + sta player_delta_y ; 84BF 8D 31 06 .1. + lda trigger_disabled ; 84C2 AD 34 06 .4. + beq read_trigger ; 84C5 F0 0C .. + cmp #$01 ; 84C7 C9 01 .. + beq fake_read_trigger ; 84C9 F0 02 .. + lda #$00 ; 84CB A9 00 .. +; ?? +fake_read_trigger: + sta trigger_state ; 84CD 8D 35 06 .5. + jmp L84D9 ; 84D0 4C D9 84 L.. + +; ---------------------------------------------------------------------------- +; always joystick #1 +read_trigger: + lda TRIG0 ; 84D3 AD 10 D0 ... + sta trigger_state ; 84D6 8D 35 06 .5. +L84D9: ldx #$08 ; 84D9 A2 08 .. +L84DB: lda work_level_desc+1,x ; 84DB BD 81 07 ... + beq L84EE ; 84DE F0 0E .. + sta $0603,x ; 84E0 9D 03 06 ... + lda work_level_desc,x ; 84E3 BD 80 07 ... + sta $0602,x ; 84E6 9D 02 06 ... + lda #$00 ; 84E9 A9 00 .. + sta work_level_desc+1,x ; 84EB 9D 81 07 ... +L84EE: dex ; 84EE CA . + dex ; 84EF CA . + bne L84DB ; 84F0 D0 E9 .. + lda $0640 ; 84F2 AD 40 06 .@. + ora $0642 ; 84F5 0D 42 06 .B. + ora $0644 ; 84F8 0D 44 06 .D. + ora sfx_slot_duration ; 84FB 0D 46 06 .F. + sta $0663 ; 84FE 8D 63 06 .c. + ldx #$10 ; 8501 A2 10 .. +; save contents of GTIA collision regs (X ranges 1 to $10, dli_vec_shadow_hi should read collision_save-1) +save_collisions: + lda $CFFF,x ; 8503 BD FF CF ... + sta dli_vec_shadow_hi,x ; 8506 9D AF 06 ... + dex ; 8509 CA . + bne save_collisions ; 850A D0 F7 .. + inx ; 850C E8 . +clear_collisions: + stx HITCLR ; 850D 8E 1E D0 ... +; update display list, if there's a new one in the shadow reg +update_dlist: + lda dlist_shadow_hi ; 8510 AD AD 06 ... + beq update_dli_vector ; 8513 F0 0E .. + sta DLISTH ; 8515 8D 03 D4 ... + lda dlist_shadow_lo ; 8518 AD AC 06 ... + sta DLISTL ; 851B 8D 02 D4 ... +; clear the shadow now that we've updated the HW +clear_dlist_shadow: + lda #$00 ; 851E A9 00 .. + sta dlist_shadow_hi ; 8520 8D AD 06 ... +; update DLI vector, if there's a new one in the shadow reg +update_dli_vector: + lda dli_vec_shadow_hi ; 8523 AD AF 06 ... + beq L853B ; 8526 F0 13 .. + sta VDSLST+1 ; 8528 8D 01 02 ... + lda dli_vec_shadow_lo ; 852B AD AE 06 ... + sta VDSLST ; 852E 8D 00 02 ... +; clear the shadow now that we've updated the HW +clear_dli_shadow: + lda #$00 ; 8531 A9 00 .. + sta dli_vec_shadow_hi ; 8533 8D AF 06 ... +; enable DLI now that we've set up the vector +enable_dli: + lda #$C0 ; 8536 A9 C0 .. + sta NMIEN ; 8538 8D 0E D4 ... +L853B: lda $06FC ; 853B AD FC 06 ... + cmp $0888 ; 853E CD 88 08 ... + bcc L8551 ; 8541 90 0E .. + inc $06FD ; 8543 EE FD 06 ... + inc $06FB ; 8546 EE FB 06 ... + lda #$00 ; 8549 A9 00 .. + sta $06FC ; 854B 8D FC 06 ... + jmp enable_keyboard_irq ; 854E 4C 54 85 LT. + +; ---------------------------------------------------------------------------- +L8551: inc $06FC ; 8551 EE FC 06 ... +; $C0 = regular keypress, break keypress +enable_keyboard_irq: + lda #$C0 ; 8554 A9 C0 .. + sta IRQEN ; 8556 8D 0E D2 ... + cli ; 8559 58 X +; 8 = silent (0 would be a click) +silence_console_speaker: + lda #$08 ; 855A A9 08 .. + sta CONSOL ; 855C 8D 1F D0 ... + ldx #$FF ; 855F A2 FF .. +; carry set = not pressed, clear = pressed +check_start_key: + lda CONSOL ; 8561 AD 1F D0 ... + sta zp_temp1 ; 8564 85 CB .. + lsr zp_temp1 ; 8566 46 CB F. + bcs check_select_key ; 8568 B0 09 .. + lda start_key_enabled ; 856A AD C8 06 ... + beq check_select_key ; 856D F0 04 .. + txs ; 856F 9A . + jmp (start_key_vec) ; 8570 6C C4 06 l.. + +; ---------------------------------------------------------------------------- +; carry set = not pressed, clear = pressed +check_select_key: + lsr zp_temp1 ; 8573 46 CB F. + bcs check_option_key ; 8575 B0 09 .. + lda select_key_enabled ; 8577 AD C7 06 ... + beq check_option_key ; 857A F0 04 .. + txs ; 857C 9A . + jmp (select_key_vec) ; 857D 6C C2 06 l.. + +; ---------------------------------------------------------------------------- +; carry set = not pressed, clear = pressed +check_option_key: + lsr zp_temp1 ; 8580 46 CB F. + bcs L858D ; 8582 B0 09 .. + lda option_key_enabled ; 8584 AD C6 06 ... + beq L858D ; 8587 F0 04 .. + txs ; 8589 9A . + jmp (option_key_vec) ; 858A 6C C0 06 l.. + +; ---------------------------------------------------------------------------- +L858D: ldx $0618 ; 858D AE 18 06 ... + cpx #$18 ; 8590 E0 18 .. + bne L859C ; 8592 D0 08 .. + lda #$00 ; 8594 A9 00 .. + sta $0618 ; 8596 8D 18 06 ... + jmp XITVBV ; 8599 4C 62 E4 Lb. + +; ---------------------------------------------------------------------------- +L859C: inc $0618 ; 859C EE 18 06 ... + inc $0618 ; 859F EE 18 06 ... + lda $0601,x ; 85A2 BD 01 06 ... + beq L858D ; 85A5 F0 E6 .. + sta $06E5 ; 85A7 8D E5 06 ... + lda $0600,x ; 85AA BD 00 06 ... + sta $06E4 ; 85AD 8D E4 06 ... + jsr L06E3 ; 85B0 20 E3 06 .. + jmp L858D ; 85B3 4C 8D 85 L.. + +; ---------------------------------------------------------------------------- +; used in vblank_imm_isr, not sure for what yet +data_table_85b6: + .byte $1A,$96,$28,$66,$C6,$56,$0E,$F6 ; 85B6 1A 96 28 66 C6 56 0E F6 ..(f.V.. +; ---------------------------------------------------------------------------- +; X/Y movement, indexed by joystick_state << 1, each entry is XXYY, $FF is -1 +movement_direction_table: + .word $0000,$0000,$0000,$0000 ; 85BE 00 00 00 00 00 00 00 00 ........ + .word $0000,$0101,$FF01,$0001 ; 85C6 00 00 01 01 01 FF 01 00 ........ + .word $0000,$01FF,$FFFF,$00FF ; 85CE 00 00 FF 01 FF FF FF 00 ........ + .word $0000,$0100,$FF00,$0000 ; 85D6 00 00 00 01 00 FF 00 00 ........ +; ---------------------------------------------------------------------------- +; dunno what this is for yet, but it's copied into page 6 by init_hardware +data_table_85de: + .byte $C8,$88,$05,$84,$05,$84,$05,$84 ; 85DE C8 88 05 84 05 84 05 84 ........ + .byte $05,$84,$05,$84,$05,$84,$00,$98 ; 85E6 05 84 05 84 05 84 00 98 ........ + .byte $93,$82,$69,$8E,$00,$89,$57,$81 ; 85EE 93 82 69 8E 00 89 57 81 ..i...W. +; probably just filler +zero_filler_85f6: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 85F6 00 00 00 00 00 00 00 00 ........ + .byte $00,$00 ; 85FE 00 00 .. +; ---------------------------------------------------------------------------- +; gets called after the level is drawn & the intro music stops, and also during the level (?) +xxx_level_something: + ldx #$00 ; 8600 A2 00 .. + ldy #$00 ; 8602 A0 00 .. + stx $0665 ; 8604 8E 65 06 .e. +L8607: lda #$10 ; 8607 A9 10 .. + clc ; 8609 18 . + adc $D5 ; 860A 65 D5 e. + sta ($D3),y ; 860C 91 D3 .. +L860E: sec ; 860E 38 8 + lda $D0 ; 860F A5 D0 .. + sbc L8702,x ; 8611 FD 02 87 ... + sta $D0 ; 8614 85 D0 .. + lda $D1 ; 8616 A5 D1 .. + sbc L8703,x ; 8618 FD 03 87 ... + sta $D1 ; 861B 85 D1 .. + lda $D2 ; 861D A5 D2 .. + sbc L8704,x ; 861F FD 04 87 ... + sta $D2 ; 8622 85 D2 .. + bcc L8633 ; 8624 90 0D .. + lda ($D3),y ; 8626 B1 D3 .. + clc ; 8628 18 . + adc #$01 ; 8629 69 01 i. + sta ($D3),y ; 862B 91 D3 .. + sta $0665 ; 862D 8D 65 06 .e. + jmp L860E ; 8630 4C 0E 86 L.. + +; ---------------------------------------------------------------------------- +L8633: clc ; 8633 18 . + lda L8702,x ; 8634 BD 02 87 ... + adc $D0 ; 8637 65 D0 e. + sta $D0 ; 8639 85 D0 .. + lda L8703,x ; 863B BD 03 87 ... + adc $D1 ; 863E 65 D1 e. + sta $D1 ; 8640 85 D1 .. + lda L8704,x ; 8642 BD 04 87 ... + adc $D2 ; 8645 65 D2 e. + sta $D2 ; 8647 85 D2 .. + lda $0665 ; 8649 AD 65 06 .e. + bne L865C ; 864C D0 0E .. + lda ($D3),y ; 864E B1 D3 .. + and #$0F ; 8650 29 0F ). + bne L865C ; 8652 D0 08 .. + cpy #$05 ; 8654 C0 05 .. + beq L8667 ; 8656 F0 0F .. + lda #$00 ; 8658 A9 00 .. + sta ($D3),y ; 865A 91 D3 .. +L865C: cpx #$0F ; 865C E0 0F .. + beq L8667 ; 865E F0 07 .. + inx ; 8660 E8 . + inx ; 8661 E8 . + inx ; 8662 E8 . + iny ; 8663 C8 . + jmp L8607 ; 8664 4C 07 86 L.. + +; ---------------------------------------------------------------------------- +L8667: rts ; 8667 60 ` + +; ---------------------------------------------------------------------------- +L8668: lda #$F5 ; 8668 A9 F5 .. + sta $D3 ; 866A 85 D3 .. + lda #$3D ; 866C A9 3D .= + sta $D4 ; 866E 85 D4 .. + ldx #$03 ; 8670 A2 03 .. +L8672: lda $06FF,x ; 8672 BD FF 06 ... + sta $CF,x ; 8675 95 CF .. + dex ; 8677 CA . + bne L8672 ; 8678 D0 F8 .. + jsr xxx_level_something ; 867A 20 00 86 .. + rts ; 867D 60 ` + +; ---------------------------------------------------------------------------- +L867E: lda #$09 ; 867E A9 09 .. + sta $D3 ; 8680 85 D3 .. + lda #$3E ; 8682 A9 3E .> + sta $D4 ; 8684 85 D4 .. + ldx #$03 ; 8686 A2 03 .. +L8688: lda work_level_points_per_bomb,x ; 8688 BD 90 07 ... + sta $CF,x ; 868B 95 CF .. + dex ; 868D CA . + bne L8688 ; 868E D0 F8 .. + jsr xxx_level_something ; 8690 20 00 86 .. + rts ; 8693 60 ` + +; ---------------------------------------------------------------------------- +; bottom 2 GR.1 lines on the game board +update_status_window: + lda #$00 ; 8694 A9 00 .. + sta HSCROL ; 8696 8D 04 D4 ... + ldx #$28 ; 8699 A2 28 .( +L869B: lda L86D9,x ; 869B BD D9 86 ... + sec ; 869E 38 8 + sbc #$20 ; 869F E9 20 . + sta $3DE7,x ; 86A1 9D E7 3D ..= + dex ; 86A4 CA . + bne L869B ; 86A5 D0 F4 .. +; 1 to 4 +show_current_player: + lda current_player ; 86A7 AD FE 06 ... + ora #$10 ; 86AA 09 10 .. + sta $3DE9 ; 86AC 8D E9 3D ..= + lda work_level_desc ; 86AF AD 80 07 ... + sta $3DED ; 86B2 8D ED 3D ..= + lda work_level_desc+1 ; 86B5 AD 81 07 ... + sta $3DEE ; 86B8 8D EE 3D ..= +; up to 6 jumpmen, and a + if lives > 6. char $C1 = jumpman icon, $CB = plus sign +show_lives_icons: + ldy #$00 ; 86BB A0 00 .. + lda #$C1 ; 86BD A9 C1 .. +L86BF: cpy #$07 ; 86BF C0 07 .. + bcs L86CE ; 86C1 B0 0B .. + cpy lives ; 86C3 CC 0A 07 ... + beq L86D3 ; 86C6 F0 0B .. + sta $3DFD,y ; 86C8 99 FD 3D ..= + iny ; 86CB C8 . + bne L86BF ; 86CC D0 F1 .. +L86CE: lda #$CB ; 86CE A9 CB .. + sta $3DFC,y ; 86D0 99 FC 3D ..= +L86D3: jsr L8668 ; 86D3 20 68 86 h. + jsr L867E ; 86D6 20 7E 86 ~. +L86D9: rts ; 86D9 60 ` + +; ---------------------------------------------------------------------------- +data_table_86da: + .byte $20,$30,$20,$8C,$7D,$30,$30,$20 ; 86DA 20 30 20 8C 7D 30 30 20 0 .}00 + .byte $D3,$C3,$CF,$D2,$C5,$20,$20,$20 ; 86E2 D3 C3 CF D2 C5 20 20 20 ..... + .byte $20,$20,$20,$20,$20,$20,$20,$20 ; 86EA 20 20 20 20 20 20 20 20 + .byte $20,$20,$20,$20,$C2,$CF,$CE,$D5 ; 86F2 20 20 20 20 C2 CF CE D5 .... + .byte $D3,$20,$20,$20,$20,$20,$20,$20 ; 86FA D3 20 20 20 20 20 20 20 . +L8702: .byte $A0 ; 8702 A0 . +L8703: .byte $86 ; 8703 86 . +L8704: .byte $01,$10,$27,$00,$E8,$03,$00,$64 ; 8704 01 10 27 00 E8 03 00 64 ..'....d + .byte $00,$00,$0A,$00,$00,$01,$00,$00 ; 870C 00 00 0A 00 00 01 00 00 ........ +; ---------------------------------------------------------------------------- +; clear the gameboard screen memory (called before drawing a level, natch) +clear_screen_mem: + ldx #$10 ; 8714 A2 10 .. + lda SAVMSC+1 ; 8716 A5 59 .Y + sta $AF ; 8718 85 AF .. + lda #$00 ; 871A A9 00 .. + sta $AE ; 871C 85 AE .. + tay ; 871E A8 . +csm_loop: + sta ($AE),y ; 871F 91 AE .. + iny ; 8721 C8 . + bne csm_loop ; 8722 D0 FB .. + inc $AF ; 8724 E6 AF .. + dex ; 8726 CA . + bne csm_loop ; 8727 D0 F6 .. + rts ; 8729 60 ` + +; ---------------------------------------------------------------------------- +; clear P/M mem +clear_pm_mem: + lda #$09 ; 872A A9 09 .. + sta player_speed ; 872C 8D 24 06 .$. + ldx #$05 ; 872F A2 05 .. + lda #$00 ; 8731 A9 00 .. + sta playing_level ; 8733 8D 27 06 .'. +L8736: sta $0681,x ; 8736 9D 81 06 ... + sta $0668,x ; 8739 9D 68 06 .h. + sta $069A,x ; 873C 9D 9A 06 ... + jsr hide_player ; 873F 20 B8 8D .. + dex ; 8742 CA . + bne L8736 ; 8743 D0 F1 .. + lda #$2B ; 8745 A9 2B .+ + sta $B8 ; 8747 85 B8 .. + lda #$00 ; 8749 A9 00 .. + sta $B7 ; 874B 85 B7 .. + tay ; 874D A8 . + ldx #$05 ; 874E A2 05 .. +L8750: sta ($B7),y ; 8750 91 B7 .. + iny ; 8752 C8 . + bne L8750 ; 8753 D0 FB .. + inc $B8 ; 8755 E6 B8 .. + dex ; 8757 CA . + bne L8750 ; 8758 D0 F6 .. + rts ; 875A 60 ` + +; ---------------------------------------------------------------------------- +; set all AUDFx to 0 +silence_audio: + ldx #$00 ; 875B A2 00 .. + lda #$00 ; 875D A9 00 .. +sa_loop:sta $0640,x ; 875F 9D 40 06 .@. + sta $0641,x ; 8762 9D 41 06 .A. + sta $0660,x ; 8765 9D 60 06 .`. + sta AUDF1,x ; 8768 9D 00 D2 ... + jsr store_audc ; 876B 20 C6 8D .. + inx ; 876E E8 . + inx ; 876F E8 . + cpx #$08 ; 8770 E0 08 .. + bne sa_loop ; 8772 D0 EB .. + rts ; 8774 60 ` + +; ---------------------------------------------------------------------------- +; called after level-intro music is finished playing +enable_joystick: + ldx #$08 ; 8775 A2 08 .. +ej_loop:lda #$E6 ; 8777 A9 E6 .. + sta work_level_desc,x ; 8779 9D 80 07 ... + lda #$06 ; 877C A9 06 .. + sta work_level_desc+1,x ; 877E 9D 81 07 ... + dex ; 8781 CA . + dex ; 8782 CA . + bne ej_loop ; 8783 D0 F2 .. + stx joystick_disabled ; 8785 8E 32 06 .2. + stx sfx_lock ; 8788 8E 2F 06 ./. + stx work_level_bullet_chance ; 878B 8E 8B 07 ... + jsr clear_pm_mem ; 878E 20 2A 87 *. + jsr silence_audio ; 8791 20 5B 87 [. + lda #$30 ; 8794 A9 30 .0 + sta SAVMSC+1 ; 8796 85 59 .Y +; priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles) [redundant? init_set_prior sets this, nothing appears to change it] +set_prior: + lda #$11 ; 8798 A9 11 .. + sta PRIOR ; 879A 8D 1B D0 ... + jmp L88A8 ; 879D 4C A8 88 L.. + +; ---------------------------------------------------------------------------- +L87A0: lda collision_save+4 ; 87A0 AD B4 06 ... + and #$04 ; 87A3 29 04 ). + bne L87A8 ; 87A5 D0 01 .. + rts ; 87A7 60 ` + +; ---------------------------------------------------------------------------- +L87A8: lda $067E ; 87A8 AD 7E 06 .~. + clc ; 87AB 18 . + adc work_level_offs_14 ; 87AC 6D 8E 07 m.. + and #$E0 ; 87AF 29 E0 ). + sta $B6 ; 87B1 85 B6 .. + clc ; 87B3 18 . + lda $0683 ; 87B4 AD 83 06 ... + adc work_level_offs_14+1 ; 87B7 6D 8F 07 m.. + and #$E0 ; 87BA 29 E0 ). + lsr a ; 87BC 4A J + lsr a ; 87BD 4A J + lsr a ; 87BE 4A J + lsr a ; 87BF 4A J + ora $B6 ; 87C0 05 B6 .. + sta $B6 ; 87C2 85 B6 .. + lda work_level_map2 ; 87C4 AD 9A 07 ... + sta $B4 ; 87C7 85 B4 .. + lda work_level_map2+1 ; 87C9 AD 9B 07 ... + sta $B5 ; 87CC 85 B5 .. + ldy #$00 ; 87CE A0 00 .. +L87D0: lda ($B4),y ; 87D0 B1 B4 .. + cmp #$FF ; 87D2 C9 FF .. + bne L87D7 ; 87D4 D0 01 .. + rts ; 87D6 60 ` + +; ---------------------------------------------------------------------------- +L87D7: cmp $B6 ; 87D7 C5 B6 .. + beq L87E0 ; 87D9 F0 05 .. + iny ; 87DB C8 . + iny ; 87DC C8 . + jmp L87D0 ; 87DD 4C D0 87 L.. + +; ---------------------------------------------------------------------------- +L87E0: lda work_level_map1 ; 87E0 AD 98 07 ... + sta $B0 ; 87E3 85 B0 .. + lda work_level_map1+1 ; 87E5 AD 99 07 ... + sta $B1 ; 87E8 85 B1 .. + tya ; 87EA 98 . + sta $B2 ; 87EB 85 B2 .. + lsr a ; 87ED 4A J + clc ; 87EE 18 . + adc $B2 ; 87EF 65 B2 e. + tay ; 87F1 A8 . + lda ($B0),y ; 87F2 B1 B0 .. + sta $06DC ; 87F4 8D DC 06 ... + iny ; 87F7 C8 . + lda ($B0),y ; 87F8 B1 B0 .. + sta $06DD ; 87FA 8D DD 06 ... + lda #$92 ; 87FD A9 92 .. + sta sfx_ptr ; 87FF 8D 3C 06 .<. + lda #$88 ; 8802 A9 88 .. + sta sfx_ptr+1 ; 8804 8D 3D 06 .=. + lda #$08 ; 8807 A9 08 .. + jsr cue_sfx_jv ; 8809 20 06 80 .. + ldy $B2 ; 880C A4 B2 .. + iny ; 880E C8 . + lda ($B4),y ; 880F B1 B4 .. + beq L8856 ; 8811 F0 43 .C + and #$F0 ; 8813 29 F0 ). + beq L8831 ; 8815 F0 1A .. + lsr a ; 8817 4A J + lsr a ; 8818 4A J + lsr a ; 8819 4A J + tay ; 881A A8 . + lda work_level_unkn_table1 ; 881B AD 9C 07 ... + sta $B0 ; 881E 85 B0 .. + lda work_level_unkn_table1+1 ; 8820 AD 9D 07 ... + sta $B1 ; 8823 85 B1 .. + lda ($B0),y ; 8825 B1 B0 .. + sta dm_progctr ; 8827 85 C0 .. + iny ; 8829 C8 . + lda ($B0),y ; 882A B1 B0 .. + sta dm_progctr+1 ; 882C 85 C1 .. + jsr draw_map_jv ; 882E 20 00 80 .. +L8831: ldy $B2 ; 8831 A4 B2 .. + iny ; 8833 C8 . + lda ($B4),y ; 8834 B1 B4 .. + beq L8856 ; 8836 F0 1E .. + and #$0F ; 8838 29 0F ). + beq L8856 ; 883A F0 1A .. + asl a ; 883C 0A . + tay ; 883D A8 . + lda work_level_offs_30 ; 883E AD 9E 07 ... + sta $B0 ; 8841 85 B0 .. + lda work_level_offs_30+1 ; 8843 AD 9F 07 ... + sta $B1 ; 8846 85 B1 .. + lda ($B0),y ; 8848 B1 B0 .. + sta $06E4 ; 884A 8D E4 06 ... + iny ; 884D C8 . + lda ($B0),y ; 884E B1 B0 .. + sta $06E5 ; 8850 8D E5 06 ... + jsr L06E3 ; 8853 20 E3 06 .. +L8856: lda work_level_sub4 ; 8856 AD A0 07 ... + sta $06E4 ; 8859 8D E4 06 ... + lda work_level_sub4+1 ; 885C AD A1 07 ... + sta $06E5 ; 885F 8D E5 06 ... + jsr L06E3 ; 8862 20 E3 06 .. + clc ; 8865 18 . + lda score ; 8866 AD 00 07 ... + adc work_level_points_per_bomb ; 8869 6D 90 07 m.. + sta score ; 886C 8D 00 07 ... + bcc L8879 ; 886F 90 08 .. + inc score+1 ; 8871 EE 01 07 ... + bne L8879 ; 8874 D0 03 .. + inc score+2 ; 8876 EE 02 07 ... +L8879: lda #$D9 ; 8879 A9 D9 .. + sta dm_progctr ; 887B 85 C0 .. + lda #$06 ; 887D A9 06 .. + sta dm_progctr+1 ; 887F 85 C1 .. + jsr draw_map_jv ; 8881 20 00 80 .. + jsr L800C ; 8884 20 0C 80 .. + dec work_level_num_bombs ; 8887 CE 8A 07 ... +L888A: lda collision_save+4 ; 888A AD B4 06 ... + and #$04 ; 888D 29 04 ). + bne L888A ; 888F D0 F9 .. + rts ; 8891 60 ` + +; ---------------------------------------------------------------------------- +data_8892: + .byte $01,$A6,$00,$1E,$03,$28,$03,$1E ; 8892 01 A6 00 1E 03 28 03 1E .....(.. + .byte $03,$28,$03,$1E,$03,$28,$03,$1E ; 889A 03 28 03 1E 03 28 03 1E .(...(.. + .byte $03,$28,$03,$00,$00,$00 ; 88A2 03 28 03 00 00 00 .(.... +; ---------------------------------------------------------------------------- +L88A8: ldx #$00 ; 88A8 A2 00 .. + txa ; 88AA 8A . +L88AB: sta $2B00,x ; 88AB 9D 00 2B ..+ + sta $2C00,x ; 88AE 9D 00 2C .., + sta $2D00,x ; 88B1 9D 00 2D ..- + sta $2E00,x ; 88B4 9D 00 2E ... + sta $2F00,x ; 88B7 9D 00 2F ../ + dex ; 88BA CA . + bne L88AB ; 88BB D0 EE .. + rts ; 88BD 60 ` + +; ---------------------------------------------------------------------------- + brk ; 88BE 00 . + brk ; 88BF 00 . + brk ; 88C0 00 . + brk ; 88C1 00 . + brk ; 88C2 00 . + brk ; 88C3 00 . + brk ; 88C4 00 . + brk ; 88C5 00 . + brk ; 88C6 00 . + brk ; 88C7 00 . +check_consol: + lda player_delta_x ; 88C8 AD 30 06 .0. + ora player_delta_y ; 88CB 0D 31 06 .1. + bne L88DC ; 88CE D0 0C .. + lda CONSOL ; 88D0 AD 1F D0 ... + and #$07 ; 88D3 29 07 ). + cmp #$07 ; 88D5 C9 07 .. + bne L88DC ; 88D7 D0 03 .. + jmp L88E0 ; 88D9 4C E0 88 L.. + +; ---------------------------------------------------------------------------- +L88DC: lda #$00 ; 88DC A9 00 .. + sta $A2 ; 88DE 85 A2 .. +L88E0: lda $A0 ; 88E0 A5 A0 .. + bne L88E7 ; 88E2 D0 03 .. + sta $A2 ; 88E4 85 A2 .. +L88E6: rts ; 88E6 60 ` + +; ---------------------------------------------------------------------------- +L88E7: lda $A2 ; 88E7 A5 A2 .. + cmp #$28 ; 88E9 C9 28 .( + bcc L88E6 ; 88EB 90 F9 .. + lda #$00 ; 88ED A9 00 .. + sta $A0 ; 88EF 85 A0 .. + sta $A2 ; 88F1 85 A2 .. + ldx #$FF ; 88F3 A2 FF .. + txs ; 88F5 9A . + jmp init_game ; 88F6 4C 00 90 L.. + +; ---------------------------------------------------------------------------- + brk ; 88F9 00 . + brk ; 88FA 00 . + brk ; 88FB 00 . + brk ; 88FC 00 . + brk ; 88FD 00 . + brk ; 88FE 00 . + brk ; 88FF 00 . + lda $0621 ; 8900 AD 21 06 .!. + beq L890F ; 8903 F0 0A .. + lda $0623 ; 8905 AD 23 06 .#. + cmp #$01 ; 8908 C9 01 .. + beq L8910 ; 890A F0 04 .. + jmp L89F3 ; 890C 4C F3 89 L.. + +; ---------------------------------------------------------------------------- +L890F: rts ; 890F 60 ` + +; ---------------------------------------------------------------------------- +L8910: lda $06EE ; 8910 AD EE 06 ... + bne L8945 ; 8913 D0 30 .0 + inc $06EE ; 8915 EE EE 06 ... + lda #$02 ; 8918 A9 02 .. + sta player_speed ; 891A 8D 24 06 .$. + sta $067F ; 891D 8D 7F 06 ... + lda #$00 ; 8920 A9 00 .. + sta playing_level ; 8922 8D 27 06 .'. + sta $06E9 ; 8925 8D E9 06 ... + sta $06EA ; 8928 8D EA 06 ... + lda RANDOM ; 892B AD 0A D2 ... + and #$0F ; 892E 29 0F ). + sta $0688 ; 8930 8D 88 06 ... + inc $0688 ; 8933 EE 88 06 ... + lda #$60 ; 8936 A9 60 .` + sta sfx_slot_tempo ; 8938 8D 3E 06 .>. + lda #$8A ; 893B A9 8A .. + sta sfx_slot_timer ; 893D 8D 3F 06 .?. + lda #$07 ; 8940 A9 07 .. + jsr L8003 ; 8942 20 03 80 .. +L8945: lda $0683 ; 8945 AD 83 06 ... + cmp #$C6 ; 8948 C9 C6 .. + bcc L895D ; 894A 90 11 .. + lda #$00 ; 894C A9 00 .. + sta AUDF1 ; 894E 8D 00 D2 ... + sta AUDC1 ; 8951 8D 01 D2 ... + sta $06EF ; 8954 8D EF 06 ... + inc $0623 ; 8957 EE 23 06 .#. + jmp L89F3 ; 895A 4C F3 89 L.. + +; ---------------------------------------------------------------------------- +L895D: lda #$70 ; 895D A9 70 .p + sta $0801 ; 895F 8D 01 08 ... + sta game_display_list ; 8962 8D 81 08 ... + lda $06EA ; 8965 AD EA 06 ... + bne L89A9 ; 8968 D0 3F .? +L896A: inc $0683 ; 896A EE 83 06 ... + inc $0683 ; 896D EE 83 06 ... + lda $0683 ; 8970 AD 83 06 ... + sta AUDF1 ; 8973 8D 00 D2 ... + lda #$A3 ; 8976 A9 A3 .. + sta AUDC1 ; 8978 8D 01 D2 ... + lda collision_save+4 ; 897B AD B4 06 ... + and #$01 ; 897E 29 01 ). + bne falling_bounce ; 8980 D0 01 .. + rts ; 8982 60 ` + +; ---------------------------------------------------------------------------- +; this looks like it hurts... +falling_bounce: + lda RANDOM ; 8983 AD 0A D2 ... + and #$03 ; 8986 29 03 ). + beq falling_bounce ; 8988 F0 F9 .. + sta $06E9 ; 898A 8D E9 06 ... + lda #$00 ; 898D A9 00 .. + sta $06EA ; 898F 8D EA 06 ... + lda #$50 ; 8992 A9 50 .P + sta $0801 ; 8994 8D 01 08 ... + sta game_display_list ; 8997 8D 81 08 ... +play_sfx_bounce_1: + lda #$4B ; 899A A9 4B .K + sta sfx_slot_tempo ; 899C 8D 3E 06 .>. + lda #$8A ; 899F A9 8A .. + sta sfx_slot_timer ; 89A1 8D 3F 06 .?. + lda #$04 ; 89A4 A9 04 .. + jsr L8003 ; 89A6 20 03 80 .. +L89A9: ldx $06EA ; 89A9 AE EA 06 ... + cpx #$09 ; 89AC E0 09 .. + bne L89B8 ; 89AE D0 08 .. + lda #$00 ; 89B0 A9 00 .. + sta $06EA ; 89B2 8D EA 06 ... + jmp L896A ; 89B5 4C 6A 89 Lj. + +; ---------------------------------------------------------------------------- +L89B8: ldy data_table_8a39,x ; 89B8 BC 39 8A .9. + lda $06E9 ; 89BB AD E9 06 ... + cmp #$01 ; 89BE C9 01 .. + beq L89D1 ; 89C0 F0 0F .. + ldy #$00 ; 89C2 A0 00 .. + cmp #$02 ; 89C4 C9 02 .. + beq L89D1 ; 89C6 F0 09 .. + lda data_table_8a39,x ; 89C8 BD 39 8A .9. + eor #$FF ; 89CB 49 FF I. + clc ; 89CD 18 . + adc #$01 ; 89CE 69 01 i. + tay ; 89D0 A8 . +L89D1: clc ; 89D1 18 . + tya ; 89D2 98 . + adc $067E ; 89D3 6D 7E 06 m~. + sta $067E ; 89D6 8D 7E 06 .~. + lda L8A42,x ; 89D9 BD 42 8A .B. + clc ; 89DC 18 . + adc $0683 ; 89DD 6D 83 06 m.. + sta $0683 ; 89E0 8D 83 06 ... + sta AUDF1 ; 89E3 8D 00 D2 ... + inc $06EA ; 89E6 EE EA 06 ... + clc ; 89E9 18 . + lda $0620 ; 89EA AD 20 06 . . + adc #$12 ; 89ED 69 12 i. + sta $0688 ; 89EF 8D 88 06 ... + rts ; 89F2 60 ` + +; ---------------------------------------------------------------------------- +L89F3: lda $0623 ; 89F3 AD 23 06 .#. + cmp #$02 ; 89F6 C9 02 .. + beq L89FB ; 89F8 F0 01 .. + rts ; 89FA 60 ` + +; ---------------------------------------------------------------------------- +L89FB: lda $06EF ; 89FB AD EF 06 ... + bne L8A16 ; 89FE D0 16 .. + sta jiffy_timer_2 ; 8A00 8D 1B 06 ... + inc $06EF ; 8A03 EE EF 06 ... + lda #$00 ; 8A06 A9 00 .. + jsr cue_music_jv ; 8A08 20 18 80 .. + lda #$04 ; 8A0B A9 04 .. + sta player_speed ; 8A0D 8D 24 06 .$. + lda #$16 ; 8A10 A9 16 .. + sta $0688 ; 8A12 8D 88 06 ... + rts ; 8A15 60 ` + +; ---------------------------------------------------------------------------- +L8A16: lda $0663 ; 8A16 AD 63 06 .c. + beq L8A25 ; 8A19 F0 0A .. + lda #$16 ; 8A1B A9 16 .. + clc ; 8A1D 18 . + adc $061F ; 8A1E 6D 1F 06 m.. + sta $0688 ; 8A21 8D 88 06 ... + rts ; 8A24 60 ` + +; ---------------------------------------------------------------------------- +L8A25: lda #$09 ; 8A25 A9 09 .. + sta player_speed ; 8A27 8D 24 06 .$. + lda #$00 ; 8A2A A9 00 .. + sta $0623 ; 8A2C 8D 23 06 .#. + sta $067E ; 8A2F 8D 7E 06 .~. + dec lives ; 8A32 CE 0A 07 ... + sta $06EE ; 8A35 8D EE 06 ... + rts ; 8A38 60 ` + +; ---------------------------------------------------------------------------- +data_table_8a39: + .byte $02,$02,$02,$02,$02,$02,$00,$00 ; 8A39 02 02 02 02 02 02 00 00 ........ + .byte $00 ; 8A41 00 . +L8A42: .byte $FE,$FE,$00,$00,$02,$02,$02,$02 ; 8A42 FE FE 00 00 02 02 02 02 ........ + .byte $02 ; 8A4A 02 . +; used when jumpman is falling? +sfx_bounce_1: + .byte $01,$8E,$00,$30,$01,$01,$8B,$00 ; 8A4B 01 8E 00 30 01 01 8B 00 ...0.... + .byte $40,$01,$01,$88,$00,$50,$01,$01 ; 8A53 40 01 01 88 00 50 01 01 @....P.. + .byte $85,$00,$60,$01,$00 ; 8A5B 85 00 60 01 00 ..`.. +; jumpman hit by bullet or started falling +sfx_death: + .byte $01,$C8,$00,$0A,$02,$FA,$02,$14 ; 8A60 01 C8 00 0A 02 FA 02 14 ........ + .byte $02,$F0,$02,$1E,$02,$E8,$02,$28 ; 8A68 02 F0 02 1E 02 E8 02 28 .......( + .byte $02,$DC,$02,$32,$02,$D2,$02,$3C ; 8A70 02 DC 02 32 02 D2 02 3C ...2...< + .byte $02,$C8,$02,$00,$00,$00,$00,$00 ; 8A78 02 C8 02 00 00 00 00 00 ........ +; ---------------------------------------------------------------------------- +play_sfx_bounce_2: + lda $061F ; 8A80 AD 1F 06 ... + bne L8A94 ; 8A83 D0 0F .. + lda #$97 ; 8A85 A9 97 .. + sta sfx_slot_tempo ; 8A87 8D 3E 06 .>. + lda #$8A ; 8A8A A9 8A .. + sta sfx_slot_timer ; 8A8C 8D 3F 06 .?. + lda #$02 ; 8A8F A9 02 .. + jsr L8003 ; 8A91 20 03 80 .. +L8A94: jmp L9925 ; 8A94 4C 25 99 L%. + +; ---------------------------------------------------------------------------- +; used when jumpman is falling? +sfx_bounce_2: + .byte $01,$81,$00,$04,$01,$00,$00,$00 ; 8A97 01 81 00 04 01 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 8A9F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 8AA7 00 00 00 00 00 00 00 00 ........ + .byte $00 ; 8AAF 00 . +sfx_option_pressed: + .byte $01,$A4,$00,$3C,$02,$00,$00,$00 ; 8AB0 01 A4 00 3C 02 00 00 00 ...<.... + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 8AB8 00 00 00 00 00 00 00 00 ........ +; ---------------------------------------------------------------------------- +cart_entry_point: + ldx #$00 ; 8AC0 A2 00 .. + lda #$00 ; 8AC2 A9 00 .. +; clear pages 6 and 7 +init_loop: + sta $0600,x ; 8AC4 9D 00 06 ... + sta score,x ; 8AC7 9D 00 07 ... + inx ; 8ACA E8 . + bne init_loop ; 8ACB D0 F7 .. + jsr init_hardware ; 8ACD 20 7C 83 |. + lda #$DD ; 8AD0 A9 DD .. + sta dlist_shadow_lo ; 8AD2 8D AC 06 ... + lda #$8A ; 8AD5 A9 8A .. + sta dlist_shadow_hi ; 8AD7 8D AD 06 ... + jmp init_game ; 8ADA 4C 00 90 L.. + +; ---------------------------------------------------------------------------- +; yet another jump-to-itself empty display list +blank_dlist_8add: + .byte $41,$DD,$8A ; 8ADD 41 DD 8A A.. +; ---------------------------------------------------------------------------- +L8AE0: lda #$EB ; 8AE0 A9 EB .. + sta dlist_shadow_lo ; 8AE2 8D AC 06 ... + lda #$8A ; 8AE5 A9 8A .. + sta dlist_shadow_hi ; 8AE7 8D AD 06 ... + rts ; 8AEA 60 ` + +; ---------------------------------------------------------------------------- +; another jump-to-itself empty display list +blank_dlist_8aeb: + .byte $41,$EB,$8A ; 8AEB 41 EB 8A A.. +; ---------------------------------------------------------------------------- + brk ; 8AEE 00 . + brk ; 8AEF 00 . + brk ; 8AF0 00 . + brk ; 8AF1 00 . + brk ; 8AF2 00 . + brk ; 8AF3 00 . + brk ; 8AF4 00 . + brk ; 8AF5 00 . + brk ; 8AF6 00 . + brk ; 8AF7 00 . + brk ; 8AF8 00 . + brk ; 8AF9 00 . + brk ; 8AFA 00 . + brk ; 8AFB 00 . + brk ; 8AFC 00 . + brk ; 8AFD 00 . +cart_start_stub: + clc ; 8AFE 18 . + rts ; 8AFF 60 ` + +; ---------------------------------------------------------------------------- + brk ; 8B00 00 . + brk ; 8B01 00 . + brk ; 8B02 00 . + brk ; 8B03 00 . + brk ; 8B04 00 . + brk ; 8B05 00 . + brk ; 8B06 00 . + brk ; 8B07 00 . + brk ; 8B08 00 . + brk ; 8B09 00 . + brk ; 8B0A 00 . + brk ; 8B0B 00 . + brk ; 8B0C 00 . + brk ; 8B0D 00 . + brk ; 8B0E 00 . + brk ; 8B0F 00 . + brk ; 8B10 00 . + brk ; 8B11 00 . + brk ; 8B12 00 . + brk ; 8B13 00 . + brk ; 8B14 00 . + brk ; 8B15 00 . + brk ; 8B16 00 . + brk ; 8B17 00 . + brk ; 8B18 00 . + brk ; 8B19 00 . + brk ; 8B1A 00 . + brk ; 8B1B 00 . + brk ; 8B1C 00 . + brk ; 8B1D 00 . + brk ; 8B1E 00 . + brk ; 8B1F 00 . + brk ; 8B20 00 . + brk ; 8B21 00 . + brk ; 8B22 00 . +L8B23: ldx #$20 ; 8B23 A2 20 . + lda #$00 ; 8B25 A9 00 .. +L8B27: sta $075F,x ; 8B27 9D 5F 07 ._. + dex ; 8B2A CA . + bne L8B27 ; 8B2B D0 FA .. +L8B2D: lda work_level_unkn_table0 ; 8B2D AD 94 07 ... + sta $AC ; 8B30 85 AC .. + lda work_level_unkn_table0+1 ; 8B32 AD 95 07 ... + sta $AD ; 8B35 85 AD .. + ldy #$00 ; 8B37 A0 00 .. +L8B39: lda ($AC),y ; 8B39 B1 AC .. + cmp #$FF ; 8B3B C9 FF .. + beq L8B7A ; 8B3D F0 3B .; + tax ; 8B3F AA . + iny ; 8B40 C8 . + lda ($AC),y ; 8B41 B1 AC .. + sta $066E,x ; 8B43 9D 6E 06 .n. + iny ; 8B46 C8 . + lda ($AC),y ; 8B47 B1 AC .. + sta $0673,x ; 8B49 9D 73 06 .s. + iny ; 8B4C C8 . + lda ($AC),y ; 8B4D B1 AC .. + sta $0678,x ; 8B4F 9D 78 06 .x. + iny ; 8B52 C8 . + lda ($AC),y ; 8B53 B1 AC .. + sta $067D,x ; 8B55 9D 7D 06 .}. + iny ; 8B58 C8 . + lda ($AC),y ; 8B59 B1 AC .. + sta $0682,x ; 8B5B 9D 82 06 ... + iny ; 8B5E C8 . + lda ($AC),y ; 8B5F B1 AC .. + sta $0687,x ; 8B61 9D 87 06 ... + iny ; 8B64 C8 . + tya ; 8B65 98 . + pha ; 8B66 48 H + lda ($AC),y ; 8B67 B1 AC .. + ldy pcolor0_table,x ; 8B69 BC 7B 8B .{. + sta PCOLR0,y ; 8B6C 99 C0 02 ... + pla ; 8B6F 68 h + tay ; 8B70 A8 . + iny ; 8B71 C8 . + lda #$00 ; 8B72 A9 00 .. + sta $0696,x ; 8B74 9D 96 06 ... + jmp L8B39 ; 8B77 4C 39 8B L9. + +; ---------------------------------------------------------------------------- +L8B7A: rts ; 8B7A 60 ` + +; ---------------------------------------------------------------------------- +pcolor0_table: + .byte $07,$00,$01,$02,$03 ; 8B7B 07 00 01 02 03 ..... +; ---------------------------------------------------------------------------- +; show scores, called at end of game, also called after beating level 12 (after WELL DONE). $40 in NMIEN = disable DLI, enable VBI +player_scores_screen: + lda #$40 ; 8B80 A9 40 .@ + sta NMIEN ; 8B82 8D 0E D4 ... + lda #$82 ; 8B85 A9 82 .. + sta dlist_shadow_lo ; 8B87 8D AC 06 ... + lda #$8C ; 8B8A A9 8C .. + sta dlist_shadow_hi ; 8B8C 8D AD 06 ... + ldx #$06 ; 8B8F A2 06 .. +L8B91: lda scores_msg,x ; 8B91 BD 7B 8C .{. + sta $3006,x ; 8B94 9D 06 30 ..0 + dex ; 8B97 CA . + bne L8B91 ; 8B98 D0 F7 .. + ldx current_player ; 8B9A AE FE 06 ... + ldy struct_player_lives_offsets_minus_one,x; 8B9D BC 88 8C ... + ldx #$03 ; 8BA0 A2 03 .. + lda lives ; 8BA2 AD 0A 07 ... + sta $0713,y ; 8BA5 99 13 07 ... +L8BA8: lda $06FF,x ; 8BA8 BD FF 06 ... + sta $070B,y ; 8BAB 99 0B 07 ... + dey ; 8BAE 88 . + dex ; 8BAF CA . + bne L8BA8 ; 8BB0 D0 F6 .. + lda #$00 ; 8BB2 A9 00 .. + sta $AA ; 8BB4 85 AA .. + sta $AB ; 8BB6 85 AB .. + tay ; 8BB8 A8 . + lda number_of_players ; 8BB9 AD F4 06 ... + sta $AE ; 8BBC 85 AE .. + inc $AE ; 8BBE E6 AE .. +; shows PLAYER (backwards loop) +show_reyalp_msg: + ldx #$14 ; 8BC0 A2 14 .. +reyalp_msg_loop: + lda reyalp_msg_minus_one,x ; 8BC2 BD 67 8C .g. + sta $3028,y ; 8BC5 99 28 30 .(0 +; replace 10th char with the ASCII player number +check_10th: + cpx #$0A ; 8BC8 E0 0A .. + bne continue_loop ; 8BCA D0 09 .. + inc $AA ; 8BCC E6 AA .. + lda $AA ; 8BCE A5 AA .. + ora #$10 ; 8BD0 09 10 .. + sta $3028,y ; 8BD2 99 28 30 .(0 +continue_loop: + iny ; 8BD5 C8 . + dex ; 8BD6 CA . + bne reyalp_msg_loop ; 8BD7 D0 E9 .. + sty $AD ; 8BD9 84 AD .. + ldx $AA ; 8BDB A6 AA .. + ldy struct_player_lives_offsets_minus_one,x; 8BDD BC 88 8C ... + lda #$00 ; 8BE0 A9 00 .. +; $AF is the character to show after the score (space for alive, cross for dead) +store_space: + sta $AF ; 8BE2 85 AF .. + lda $0713,y ; 8BE4 B9 13 07 ... + cmp #$FF ; 8BE7 C9 FF .. +; player still has lives left? +check_alive: + bne no_cross ; 8BE9 D0 04 .. +; no, show a cross instead of a space +not_alive: + lda #$5E ; 8BEB A9 5E .^ + sta $AF ; 8BED 85 AF .. +no_cross: + lda L8C84,x ; 8BEF BD 84 8C ... + sta $D3 ; 8BF2 85 D3 .. + lda #$30 ; 8BF4 A9 30 .0 + sta $D4 ; 8BF6 85 D4 .. + ldx #$03 ; 8BF8 A2 03 .. +L8BFA: lda $070B,y ; 8BFA B9 0B 07 ... + sta $CF,x ; 8BFD 95 CF .. + dey ; 8BFF 88 . + dex ; 8C00 CA . + bne L8BFA ; 8C01 D0 F7 .. + jsr xxx_level_something_jv ; 8C03 20 09 80 .. + lda $AF ; 8C06 A5 AF .. + iny ; 8C08 C8 . + sta ($D3),y ; 8C09 91 D3 .. + ldy $AD ; 8C0B A4 AD .. + dec $AE ; 8C0D C6 AE .. + bne show_reyalp_msg ; 8C0F D0 AF .. + lda #$96 ; 8C11 A9 96 .. + sta COLOR3 ; 8C13 8D C7 02 ... + lda #$C6 ; 8C16 A9 C6 .. + sta COLOR0 ; 8C18 8D C4 02 ... + lda #$08 ; 8C1B A9 08 .. + sta COLOR1 ; 8C1D 8D C5 02 ... + lda #$52 ; 8C20 A9 52 .R +; set dlist shadow to scores_screen_dlist +show_scores_screen: + sta dlist_shadow_lo ; 8C22 8D AC 06 ... + lda #$8C ; 8C25 A9 8C .. + sta dlist_shadow_hi ; 8C27 8D AD 06 ... + lda #$8D ; 8C2A A9 8D .. + sta dli_vec_shadow_lo ; 8C2C 8D AE 06 ... + lda #$8C ; 8C2F A9 8C .. +; dli = score_screen_dli_sr +set_score_screen_dli: + sta dli_vec_shadow_hi ; 8C31 8D AF 06 ... + lda #$02 ; 8C34 A9 02 .. + jsr cue_music_jv ; 8C36 20 18 80 .. +; I *think* we're waiting for the music to finish playing... +what_are_we_waiting_for: + lda $0640 ; 8C39 AD 40 06 .@. + ora $0642 ; 8C3C 0D 42 06 .B. + ora $0644 ; 8C3F 0D 44 06 .D. + ora sfx_slot_duration ; 8C42 0D 46 06 .F. + bne what_are_we_waiting_for ; 8C45 D0 F2 .. + sta jiffy_timer_1 ; 8C47 8D 1A 06 ... +; wait 192 jiffies: 3.2 sec (ntsc), 3.84 sec (pal) +wait_3_sec: + lda jiffy_timer_1 ; 8C4A AD 1A 06 ... + cmp #$C0 ; 8C4D C9 C0 .. + bne wait_3_sec ; 8C4F D0 F9 .. + rts ; 8C51 60 ` + +; ---------------------------------------------------------------------------- +; a GR.2-ish DL, with DLIs, screen mem at $3000, for player scores screen +scores_screen_dlist: + .byte $70,$70,$70,$30,$70,$70,$70,$70 ; 8C52 70 70 70 30 70 70 70 70 ppp0pppp + .byte $47,$00,$30,$87,$87,$10,$87,$10 ; 8C5A 47 00 30 87 87 10 87 10 G.0..... + .byte $87,$10,$07,$41,$52 ; 8C62 87 10 07 41 52 ...AR +reyalp_msg_minus_one: + .byte $8C ; 8C67 8C . +; player spelled backwards: ' 0 # REYALP ' +reyalp_msg: + .byte $80,$80,$10,$80,$80,$80,$80,$80 ; 8C68 80 80 10 80 80 80 80 80 ........ + .byte $80,$80,$03,$80,$32,$25,$39,$21 ; 8C70 80 80 03 80 32 25 39 21 ....2%9! + .byte $2C,$30,$80 ; 8C78 2C 30 80 ,0. +; ' SCORES' in color 3 +scores_msg: + .byte $80,$F3,$E3,$EF,$F2,$E5,$F3 ; 8C7B 80 F3 E3 EF F2 E5 F3 ....... +; looks like an empty jump-to-itself dlist +blank_dlist_8c82: + .byte $41,$82 ; 8C82 41 82 A. +L8C84: .byte $8C ; 8C84 8C . +; offsets into screen memory, column 12, rows 2 3 4 5, used by code at $8BEF, loaded in $d3, hi byte in $d4 is $30 +score_offsets: + .byte $34,$48,$5C ; 8C85 34 48 5C 4H\ +struct_player_lives_offsets_minus_one: + .byte $70 ; 8C88 70 p +; lookup table, offset from $713 to lives for indexed player +struct_player_lives_offsets: + .byte $02,$0D,$18,$23 ; 8C89 02 0D 18 23 ...# +; ---------------------------------------------------------------------------- +; used by score screen +score_screen_dli_sr: + pha ; 8C8D 48 H + lda current_player ; 8C8E AD FE 06 ... + sec ; 8C91 38 8 + sbc #$01 ; 8C92 E9 01 .. + sta WSYNC ; 8C94 8D 0A D4 ... + cmp $AB ; 8C97 C5 AB .. + bne L8CA4 ; 8C99 D0 09 .. + lda $062A ; 8C9B AD 2A 06 .*. + sta COLPF0 ; 8C9E 8D 16 D0 ... + jmp L8CAA ; 8CA1 4C AA 8C L.. + +; ---------------------------------------------------------------------------- +L8CA4: lda COLOR0 ; 8CA4 AD C4 02 ... + sta COLPF0 ; 8CA7 8D 16 D0 ... +L8CAA: inc $AB ; 8CAA E6 AB .. + lda $AB ; 8CAC A5 AB .. + and #$03 ; 8CAE 29 03 ). + sta $AB ; 8CB0 85 AB .. + pla ; 8CB2 68 h + rti ; 8CB3 40 @ + +; ---------------------------------------------------------------------------- + brk ; 8CB4 00 . + brk ; 8CB5 00 . + brk ; 8CB6 00 . + brk ; 8CB7 00 . + brk ; 8CB8 00 . + brk ; 8CB9 00 . + brk ; 8CBA 00 . + brk ; 8CBB 00 . +L8CBC: ldx #$03 ; 8CBC A2 03 .. +L8CBE: lda $06FF,x ; 8CBE BD FF 06 ... + cmp score+2,x ; 8CC1 DD 02 07 ... + bcc L8CFA ; 8CC4 90 34 .4 + beq L8CCB ; 8CC6 F0 03 .. + jmp show_l_equals ; 8CC8 4C CE 8C L.. + +; ---------------------------------------------------------------------------- +L8CCB: dex ; 8CCB CA . + bne L8CBE ; 8CCC D0 F0 .. +; L= (for lives display) +show_l_equals: + ldx #$00 ; 8CCE A2 00 .. + clc ; 8CD0 18 . +L8CD1: lda l_equals,x ; 8CD1 BD FD 8C ... + adc $0703,x ; 8CD4 7D 03 07 }.. + sta $0703,x ; 8CD7 9D 03 07 ... + inx ; 8CDA E8 . + php ; 8CDB 08 . + cpx #$03 ; 8CDC E0 03 .. + beq add_extra_life ; 8CDE F0 04 .. + plp ; 8CE0 28 ( + jmp L8CD1 ; 8CE1 4C D1 8C L.. + +; ---------------------------------------------------------------------------- +; plays sfx_extra_life +add_extra_life: + plp ; 8CE4 28 ( + inc lives ; 8CE5 EE 0A 07 ... + lda #$79 ; 8CE8 A9 79 .y + sta sfx_ptr ; 8CEA 8D 3C 06 .<. + lda #$BE ; 8CED A9 BE .. + sta sfx_ptr+1 ; 8CEF 8D 3D 06 .=. + lda #$0C ; 8CF2 A9 0C .. + jsr cue_sfx_jv ; 8CF4 20 06 80 .. + jsr show_lives_icons ; 8CF7 20 BB 86 .. +L8CFA: jmp LB7C0 ; 8CFA 4C C0 B7 L.. + +; ---------------------------------------------------------------------------- +; L= (for lives display) +l_equals: + .byte $4C,$1D,$00 ; 8CFD 4C 1D 00 L.. +; ---------------------------------------------------------------------------- +; just lost your last life +crumble_gameboard: + jsr enable_joystick_jv ; 8D00 20 1B 80 .. + lda #$86 ; 8D03 A9 86 .. + sta AUDC1 ; 8D05 8D 01 D2 ... +L8D08: lda RANDOM ; 8D08 AD 0A D2 ... + and #$70 ; 8D0B 29 70 )p + sta $0801 ; 8D0D 8D 01 08 ... + sta game_display_list ; 8D10 8D 81 08 ... + lda RANDOM ; 8D13 AD 0A D2 ... + sta AUDF1 ; 8D16 8D 00 D2 ... +L8D19: lda RANDOM ; 8D19 AD 0A D2 ... + and #$1F ; 8D1C 29 1F ). + cmp #$0D ; 8D1E C9 0D .. + bcs L8D19 ; 8D20 B0 F7 .. + sta $AA ; 8D22 85 AA .. + asl a ; 8D24 0A . + clc ; 8D25 18 . + adc $AA ; 8D26 65 AA e. + sta $AA ; 8D28 85 AA .. + jsr L8D60 ; 8D2A 20 60 8D `. + inc $AA ; 8D2D E6 AA .. + lda $AA ; 8D2F A5 AA .. + pha ; 8D31 48 H + jsr L8D60 ; 8D32 20 60 8D `. + pla ; 8D35 68 h + jsr L8D60 ; 8D36 20 60 8D `. + inc $AA ; 8D39 E6 AA .. + lda $AA ; 8D3B A5 AA .. + jsr L8D60 ; 8D3D 20 60 8D `. + ldy #$00 ; 8D40 A0 00 .. + tya ; 8D42 98 . +L8D43: ora $3370,y ; 8D43 19 70 33 .p3 + ora $3398,y ; 8D46 19 98 33 ..3 + iny ; 8D49 C8 . + cpy #$28 ; 8D4A C0 28 .( + bne L8D43 ; 8D4C D0 F5 .. + cmp #$00 ; 8D4E C9 00 .. + bne L8D08 ; 8D50 D0 B6 .. + lda #$00 ; 8D52 A9 00 .. + sta AUDF1 ; 8D54 8D 00 D2 ... + sta AUDC1 ; 8D57 8D 01 D2 ... + jsr player_scores_screen ; 8D5A 20 80 8B .. + jmp afterlife ; 8D5D 4C 00 96 L.. + +; ---------------------------------------------------------------------------- +L8D60: clc ; 8D60 18 . + adc #$70 ; 8D61 69 70 ip + sta $AC ; 8D63 85 AC .. + adc #$28 ; 8D65 69 28 i( + sta $AE ; 8D67 85 AE .. + lda #$3D ; 8D69 A9 3D .= + sta $AD ; 8D6B 85 AD .. + sta $AF ; 8D6D 85 AF .. + lda #$57 ; 8D6F A9 57 .W + sta $AB ; 8D71 85 AB .. + ldy #$00 ; 8D73 A0 00 .. +L8D75: lda ($AC),y ; 8D75 B1 AC .. + sta ($AE),y ; 8D77 91 AE .. + sec ; 8D79 38 8 + lda $AC ; 8D7A A5 AC .. + sbc #$28 ; 8D7C E9 28 .( + sta $AC ; 8D7E 85 AC .. + bcs L8D84 ; 8D80 B0 02 .. + dec $AD ; 8D82 C6 AD .. +L8D84: sec ; 8D84 38 8 + lda $AE ; 8D85 A5 AE .. + sbc #$28 ; 8D87 E9 28 .( + sta $AE ; 8D89 85 AE .. + bcs L8D8F ; 8D8B B0 02 .. + dec $AF ; 8D8D C6 AF .. +L8D8F: dec $AB ; 8D8F C6 AB .. + bne L8D75 ; 8D91 D0 E2 .. + tya ; 8D93 98 . + sta ($AE),y ; 8D94 91 AE .. + rts ; 8D96 60 ` + +; ---------------------------------------------------------------------------- + brk ; 8D97 00 . + brk ; 8D98 00 . + brk ; 8D99 00 . + brk ; 8D9A 00 . + brk ; 8D9B 00 . + brk ; 8D9C 00 . + brk ; 8D9D 00 . + brk ; 8D9E 00 . + brk ; 8D9F 00 . +L8DA0: lda level ; 8DA0 AD F6 06 ... + cmp #$0B ; 8DA3 C9 0B .. + beq L8DAA ; 8DA5 F0 03 .. + jmp afterlife ; 8DA7 4C 00 96 L.. + +; ---------------------------------------------------------------------------- +L8DAA: jsr well_done_screen ; 8DAA 20 00 BC .. + lda #$04 ; 8DAD A9 04 .. + sta $0688 ; 8DAF 8D 88 06 ... + jsr player_scores_screen ; 8DB2 20 80 8B .. + jmp afterlife ; 8DB5 4C 00 96 L.. + +; ---------------------------------------------------------------------------- +; move player selected by X reg minus one off the left edge of the screen +hide_player: + lda #$02 ; 8DB8 A9 02 .. + sta HPOSM3,x ; 8DBA 9D 07 D0 ... + sta $067C,x ; 8DBD 9D 7C 06 .|. + lda #$00 ; 8DC0 A9 00 .. + sta $06EA,x ; 8DC2 9D EA 06 ... + rts ; 8DC5 60 ` + +; ---------------------------------------------------------------------------- +; store A to AUDCx (and its ?shadow?) +store_audc: + sta AUDC1,x ; 8DC6 9D 01 D2 ... + sta $0649,x ; 8DC9 9D 49 06 .I. + rts ; 8DCC 60 ` + +; ---------------------------------------------------------------------------- + brk ; 8DCD 00 . +; bonus -= 100; +decrement_time_bonus: + lda work_level_time_bonus ; 8DCE AD 91 07 ... + ora work_level_time_bonus+1 ; 8DD1 0D 92 07 ... + ora work_level_offs_19 ; 8DD4 0D 93 07 ... +; don't decrement if bonus == 0 +check_bonus_0: + beq dec_done ; 8DD7 F0 20 . + lda work_level_time_bonus ; 8DD9 AD 91 07 ... + sec ; 8DDC 38 8 + sbc #$64 ; 8DDD E9 64 .d + sta work_level_time_bonus ; 8DDF 8D 91 07 ... + bcs bonus_lt_256 ; 8DE2 B0 03 .. + dec work_level_time_bonus+1 ; 8DE4 CE 92 07 ... +bonus_lt_256: + jsr L800F ; 8DE7 20 0F 80 .. + lda #$FA ; 8DEA A9 FA .. + sta sfx_slot_tempo ; 8DEC 8D 3E 06 .>. + lda #$8D ; 8DEF A9 8D .. + sta sfx_slot_timer ; 8DF1 8D 3F 06 .?. + lda #$07 ; 8DF4 A9 07 .. + jsr L8003 ; 8DF6 20 03 80 .. +dec_done: + rts ; 8DF9 60 ` + +; ---------------------------------------------------------------------------- +data_8dfa: + .byte $01,$A5,$00,$18,$03,$00 ; 8DFA 01 A5 00 18 03 00 ...... +; ---------------------------------------------------------------------------- +level_finished: + lda #$09 ; 8E00 A9 09 .. + sta player_speed ; 8E02 8D 24 06 .$. + sta $067F ; 8E05 8D 7F 06 ... + lda #$80 ; 8E08 A9 80 .. + sta $D5 ; 8E0A 85 D5 .. + jsr L800F ; 8E0C 20 0F 80 .. +; score += time_bonus; +add_time_bonus: + clc ; 8E0F 18 . + lda work_level_time_bonus ; 8E10 AD 91 07 ... + adc score ; 8E13 6D 00 07 m.. + sta score ; 8E16 8D 00 07 ... + lda work_level_time_bonus+1 ; 8E19 AD 92 07 ... + adc score+1 ; 8E1C 6D 01 07 m.. + sta score+1 ; 8E1F 8D 01 07 ... + bcc lt_64k ; 8E22 90 03 .. + inc score+2 ; 8E24 EE 02 07 ... +lt_64k: lda #$00 ; 8E27 A9 00 .. + sta AUDF1 ; 8E29 8D 00 D2 ... + sta $D5 ; 8E2C 85 D5 .. + sta AUDC1 ; 8E2E 8D 01 D2 ... + sta jiffy_timer_1 ; 8E31 8D 1A 06 ... + sta playing_level ; 8E34 8D 27 06 .'. + jsr L800C ; 8E37 20 0C 80 .. +; 533ms ntsc, 640ms pal +wait_32_jiffies: + lda jiffy_timer_1 ; 8E3A AD 1A 06 ... + cmp #$20 ; 8E3D C9 20 . + bne wait_32_jiffies ; 8E3F D0 F9 .. +; pick random sound effect between 4 and 7 +pick_random_music: + lda RANDOM ; 8E41 AD 0A D2 ... + and #$03 ; 8E44 29 03 ). + clc ; 8E46 18 . + adc #$04 ; 8E47 69 04 i. + jsr cue_music_jv ; 8E49 20 18 80 .. +L8E4C: lda $0640 ; 8E4C AD 40 06 .@. + ora $0642 ; 8E4F 0D 42 06 .B. + ora $0644 ; 8E52 0D 44 06 .D. + ora sfx_slot_duration ; 8E55 0D 46 06 .F. + bne L8E4C ; 8E58 D0 F2 .. + sta jiffy_timer_1 ; 8E5A 8D 1A 06 ... +L8E5D: lda jiffy_timer_1 ; 8E5D AD 1A 06 ... + cmp #$40 ; 8E60 C9 40 .@ + bne L8E5D ; 8E62 D0 F9 .. + jmp end_of_level_bonus ; 8E64 4C 00 B8 L.. + +; ---------------------------------------------------------------------------- + brk ; 8E67 00 . + brk ; 8E68 00 . + lda $0622 ; 8E69 AD 22 06 .". + beq L8E75 ; 8E6C F0 07 .. + lda $0623 ; 8E6E AD 23 06 .#. + cmp #$02 ; 8E71 C9 02 .. + bne L8E76 ; 8E73 D0 01 .. +L8E75: rts ; 8E75 60 ` + +; ---------------------------------------------------------------------------- +L8E76: ldx #$FF ; 8E76 A2 FF .. +L8E78: inx ; 8E78 E8 . + cpx work_level_bullet_chance ; 8E79 EC 8B 07 ... + beq L8E75 ; 8E7C F0 F7 .. + lda $0756,x ; 8E7E BD 56 07 .V. + bne L8EB9 ; 8E81 D0 36 .6 + inc $0756,x ; 8E83 FE 56 07 .V. +L8E86: lda RANDOM ; 8E86 AD 0A D2 ... + and #$03 ; 8E89 29 03 ). + beq L8E86 ; 8E8B F0 F9 .. + tay ; 8E8D A8 . + lda RANDOM ; 8E8E AD 0A D2 ... + sta $069B,x ; 8E91 9D 9B 06 ... + sta $069F,x ; 8E94 9D 9F 06 ... + lda L8F42,y ; 8E97 B9 42 8F .B. + beq L8E9F ; 8E9A F0 03 .. + sta $069B,x ; 8E9C 9D 9B 06 ... +L8E9F: lda L8F45,y ; 8E9F B9 45 8F .E. + beq L8EA7 ; 8EA2 F0 03 .. + sta $069F,x ; 8EA4 9D 9F 06 ... +L8EA7: lda RANDOM ; 8EA7 AD 0A D2 ... + and #$03 ; 8EAA 29 03 ). + tay ; 8EAC A8 . + lda L8F49,y ; 8EAD B9 49 8F .I. + sta $075A,x ; 8EB0 9D 5A 07 .Z. + lda L8F4D,y ; 8EB3 B9 4D 8F .M. + sta $075E,x ; 8EB6 9D 5E 07 .^. +L8EB9: cmp #$02 ; 8EB9 C9 02 .. + beq L8F11 ; 8EBB F0 54 .T + lda $069B,x ; 8EBD BD 9B 06 ... + sec ; 8EC0 38 8 + sbc #$03 ; 8EC1 E9 03 .. + cmp $067E ; 8EC3 CD 7E 06 .~. + beq L8ED6 ; 8EC6 F0 0E .. + lda $069F,x ; 8EC8 BD 9F 06 ... + sec ; 8ECB 38 8 + sbc #$04 ; 8ECC E9 04 .. + cmp $0683 ; 8ECE CD 83 06 ... + beq L8EE4 ; 8ED1 F0 11 .. + jmp L8F11 ; 8ED3 4C 11 8F L.. + +; ---------------------------------------------------------------------------- +L8ED6: ldy #$00 ; 8ED6 A0 00 .. + lda $069F,x ; 8ED8 BD 9F 06 ... + cmp $0683 ; 8EDB CD 83 06 ... + bcs L8EEF ; 8EDE B0 0F .. + iny ; 8EE0 C8 . + jmp L8EEF ; 8EE1 4C EF 8E L.. + +; ---------------------------------------------------------------------------- +L8EE4: ldy #$02 ; 8EE4 A0 02 .. + lda $069B,x ; 8EE6 BD 9B 06 ... + cmp $067E ; 8EE9 CD 7E 06 .~. + bcs L8EEF ; 8EEC B0 01 .. + iny ; 8EEE C8 . +L8EEF: lda L8F51,y ; 8EEF B9 51 8F .Q. + sta $075A,x ; 8EF2 9D 5A 07 .Z. + lda L8F55,y ; 8EF5 B9 55 8F .U. + sta $075E,x ; 8EF8 9D 5E 07 .^. + lda #$59 ; 8EFB A9 59 .Y + sta sfx_slot_tempo ; 8EFD 8D 3E 06 .>. + lda #$8F ; 8F00 A9 8F .. + sta sfx_slot_timer ; 8F02 8D 3F 06 .?. + txa ; 8F05 8A . + pha ; 8F06 48 H + lda #$02 ; 8F07 A9 02 .. + jsr L8003 ; 8F09 20 03 80 .. + pla ; 8F0C 68 h + tax ; 8F0D AA . + inc $0756,x ; 8F0E FE 56 07 .V. +L8F11: lda $069B,x ; 8F11 BD 9B 06 ... + clc ; 8F14 18 . + adc $075A,x ; 8F15 7D 5A 07 }Z. + cmp #$03 ; 8F18 C9 03 .. + bcc code_8f38 ; 8F1A 90 1C .. + cmp #$FD ; 8F1C C9 FD .. + bcs code_8f38 ; 8F1E B0 18 .. + sta $069B,x ; 8F20 9D 9B 06 ... + lda $069F,x ; 8F23 BD 9F 06 ... + clc ; 8F26 18 . + adc $075E,x ; 8F27 7D 5E 07 }^. + cmp #$03 ; 8F2A C9 03 .. + bcc code_8f38 ; 8F2C 90 0A .. + cmp #$CE ; 8F2E C9 CE .. + bcs code_8f38 ; 8F30 B0 06 .. + sta $069F,x ; 8F32 9D 9F 06 ... + jmp L8E78 ; 8F35 4C 78 8E Lx. + +; ---------------------------------------------------------------------------- +code_8f38: + lda #$00 ; 8F38 A9 00 .. + sta $0756,x ; 8F3A 9D 56 07 .V. + sta $069B,x ; 8F3D 9D 9B 06 ... +L8F42 := * + 2 + jmp L8E78 ; 8F40 4C 78 8E Lx. + +; ---------------------------------------------------------------------------- +data_8f43: + .byte $04,$FC ; 8F43 04 FC .. +L8F45: .byte $00,$00,$00,$04 ; 8F45 00 00 00 04 .... +L8F49: .byte $FF,$00,$01,$00 ; 8F49 FF 00 01 00 .... +L8F4D: .byte $00,$FF,$00,$01 ; 8F4D 00 FF 00 01 .... +L8F51: .byte $00,$00,$FD,$03 ; 8F51 00 00 FD 03 .... +L8F55: .byte $FD,$03,$00,$00,$01,$8E,$00,$14 ; 8F55 FD 03 00 00 01 8E 00 14 ........ + .byte $02,$01,$8B,$00,$14,$03,$01,$88 ; 8F5D 02 01 8B 00 14 03 01 88 ........ + .byte $00,$14,$05,$01,$85,$00,$14,$07 ; 8F65 00 14 05 01 85 00 14 07 ........ + .byte $01,$82,$00,$14,$09,$00 ; 8F6D 01 82 00 14 09 00 ...... +; ---------------------------------------------------------------------------- +; did any missile hit a player, or did players 2 or 3 hit a player... +check_collisions_1: + lda collision_save+14 ; 8F73 AD BE 06 ... +L8F76: ora collision_save+15 ; 8F76 0D BF 06 ... +L8F79: ora collision_save+8 ; 8F79 0D B8 06 ... + ora collision_save+9 ; 8F7C 0D B9 06 ... + ora collision_save+10 ; 8F7F 0D BA 06 ... + ora collision_save+11 ; 8F82 0D BB 06 ... + and #$01 ; 8F85 29 01 ). + beq L8F91 ; 8F87 F0 08 .. + lda $0623 ; 8F89 AD 23 06 .#. + bne L8F91 ; 8F8C D0 03 .. + inc $0623 ; 8F8E EE 23 06 .#. +L8F91: rts ; 8F91 60 ` + +; ---------------------------------------------------------------------------- +; setup to play whichever music is in A reg, using 5-byte sfx stuct (a music is a pair of sfx played simultaneously) +cue_music: + sta $D6 ; 8F92 85 D6 .. + asl a ; 8F94 0A . + asl a ; 8F95 0A . + clc ; 8F96 18 . + adc $D6 ; 8F97 65 D6 e. + sta $D6 ; 8F99 85 D6 .. +; y = a * 5; // offset into mus_struct_table +set_y: tay ; 8F9B A8 . + lda mus00_addr1,y ; 8F9C B9 C3 8F ... + sta sfx_ptr ; 8F9F 8D 3C 06 .<. + lda mus00_addr1+1,y ; 8FA2 B9 C4 8F ... + sta sfx_ptr+1 ; 8FA5 8D 3D 06 .=. + lda mus00_len_or_tempo,y ; 8FA8 B9 C7 8F ... + jsr cue_sfx_jv ; 8FAB 20 06 80 .. + ldy $D6 ; 8FAE A4 D6 .. + lda mus00_addr2,y ; 8FB0 B9 C5 8F ... + sta sfx_ptr ; 8FB3 8D 3C 06 .<. + lda mus00_addr2+1,y ; 8FB6 B9 C6 8F ... + sta sfx_ptr+1 ; 8FB9 8D 3D 06 .=. + lda mus00_len_or_tempo,y ; 8FBC B9 C7 8F ... + jsr cue_sfx_jv ; 8FBF 20 06 80 .. + rts ; 8FC2 60 ` + +; ---------------------------------------------------------------------------- +; aka mus_struct_table, 5 bytes per entry +mus00_addr1: + .addr sfx13 ; 8FC3 D0 BF .. +mus00_addr2: + .addr sfx14 ; 8FC5 EA BF .. +; ---------------------------------------------------------------------------- +mus00_len_or_tempo: + .byte $10 ; 8FC7 10 . +; ---------------------------------------------------------------------------- +mus01_addr1: + .addr sfx12 ; 8FC8 BE BF .. +mus01_addr2: + .addr empty_music_entry ; 8FCA FF 8F .. +; ---------------------------------------------------------------------------- +mus01_len_or_tempo: + .byte $07 ; 8FCC 07 . +; ---------------------------------------------------------------------------- +; end of game tune +mus02_addr1: + .addr sfx02 ; 8FCD 8D BE .. +mus02_addr2: + .addr sfx03 ; 8FCF AF BE .. +; ---------------------------------------------------------------------------- +mus02_len_or_tempo: + .byte $10 ; 8FD1 10 . +; ---------------------------------------------------------------------------- +mus03_addr1: + .addr sfx01 ; 8FD2 25 BE %. +mus03_addr2: + .addr sfx00 ; 8FD4 F2 BD .. +; ---------------------------------------------------------------------------- +mus03_len_or_tempo: + .byte $10 ; 8FD6 10 . +; ---------------------------------------------------------------------------- +mus04_addr1: + .addr sfx04 ; 8FD7 D5 BE .. +mus04_addr2: + .addr sfx05 ; 8FD9 ED BE .. +; ---------------------------------------------------------------------------- +mus04_len_or_tempo: + .byte $10 ; 8FDB 10 . +; ---------------------------------------------------------------------------- +mus05_addr1: + .addr sfx06 ; 8FDC 14 BF .. +mus05_addr2: + .addr sfx07 ; 8FDE 30 BF 0. +; ---------------------------------------------------------------------------- +mus05_len_or_tempo: + .byte $10 ; 8FE0 10 . +; ---------------------------------------------------------------------------- +mus06_addr1: + .addr sfx08 ; 8FE1 4A BF J. +mus06_addr2: + .addr sfx09 ; 8FE3 60 BF `. +; ---------------------------------------------------------------------------- +mus06_len_or_tempo: + .byte $10 ; 8FE5 10 . +; ---------------------------------------------------------------------------- +mus07_addr1: + .addr sfx10 ; 8FE6 84 BF .. +mus07_addr2: + .addr sfx11 ; 8FE8 A6 BF .. +; ---------------------------------------------------------------------------- +mus07_len_or_tempo: + .byte $10 ; 8FEA 10 . +; ---------------------------------------------------------------------------- +; tune that plays while level is being drawn +mus08_addr1: + .addr sfx15 ; 8FEB BC BA .. +mus08_addr2: + .addr sfx16 ; 8FED EA BA .. +; ---------------------------------------------------------------------------- +mus08_len_or_tempo: + .byte $10 ; 8FEF 10 . +; ---------------------------------------------------------------------------- +mus09_addr1: + .addr empty_music_entry ; 8FF0 FF 8F .. +mus09_addr2: + .addr empty_music_entry ; 8FF2 FF 8F .. +; ---------------------------------------------------------------------------- +mus09_len_or_tempo: + .byte $01 ; 8FF4 01 . +; ---------------------------------------------------------------------------- +mus10_addr1: + .addr empty_music_entry ; 8FF5 FF 8F .. +mus10_addr2: + .addr empty_music_entry ; 8FF7 FF 8F .. +; ---------------------------------------------------------------------------- +mus10_len_or_tempo: + .byte $01 ; 8FF9 01 . +; ---------------------------------------------------------------------------- +mus11_addr1: + .addr empty_music_entry ; 8FFA FF 8F .. +mus11_addr2: + .addr empty_music_entry ; 8FFC FF 8F .. +; ---------------------------------------------------------------------------- +mus11_len_or_tempo: + .byte $01 ; 8FFE 01 . +; empty music table entries point here +empty_music_entry: + .byte $00 ; 8FFF 00 . +; ---------------------------------------------------------------------------- +; called from cart_entry_point routine +init_game: + lda #$00 ; 9000 A9 00 .. + sta option_key_enabled ; 9002 8D C6 06 ... + sta start_key_enabled ; 9005 8D C8 06 ... + nop ; 9008 EA . + nop ; 9009 EA . + nop ; 900A EA . + nop ; 900B EA . +; this entry point doesn't disable start/option keys +reinit_game: + jsr enable_joystick_jv ; 900C 20 1B 80 .. + lda #$00 ; 900F A9 00 .. + sta $A0 ; 9011 85 A0 .. + sta select_key_vec ; 9013 8D C2 06 ... + lda #$94 ; 9016 A9 94 .. + sta select_key_vec+1 ; 9018 8D C3 06 ... +; set select key vector to ask_num_players at $9400, enable select key +setup_select_key_vec: + sta select_key_enabled ; 901B 8D C7 06 ... + ldx #$08 ; 901E A2 08 .. + lda #$FF ; 9020 A9 FF .. +; seems to try to write $FF bytes to ROM that already contains $FF's (it's the solid block character in the font). possibly left over from early development before conversion to cartridge +try_to_write_rom: + sta block_char_minus_one,x ; 9022 9D 0F 9E ... + dex ; 9025 CA . + bne try_to_write_rom ; 9026 D0 FA .. + ldx #$C0 ; 9028 A2 C0 .. +copy_title_screen: + lda title_screen_data_minus_one,x ; 902A BD CE 91 ... + sta $2FFF,x ; 902D 9D FF 2F ../ + dex ; 9030 CA . + bne copy_title_screen ; 9031 D0 F7 .. + lda #$46 ; 9033 A9 46 .F + sta COLOR1 ; 9035 8D C5 02 ... + lda #$C4 ; 9038 A9 C4 .. + sta COLOR2 ; 903A 8D C6 02 ... + lda #$00 ; 903D A9 00 .. + sta $9C ; 903F 85 9C .. + sta $9D ; 9041 85 9D .. + sta COLOR3 ; 9043 8D C7 02 ... + lda #$B3 ; 9046 A9 B3 .. + sta dlist_shadow_lo ; 9048 8D AC 06 ... + lda #$91 ; 904B A9 91 .. + sta dlist_shadow_hi ; 904D 8D AD 06 ... + lda #$00 ; 9050 A9 00 .. + sta HSCROL ; 9052 8D 04 D4 ... + lda #$A5 ; 9055 A9 A5 .. + sta AUDC1 ; 9057 8D 01 D2 ... + lda #$ED ; 905A A9 ED .. + sta dli_vec_shadow_lo ; 905C 8D AE 06 ... + lda #$92 ; 905F A9 92 .. + sta dli_vec_shadow_hi ; 9061 8D AF 06 ... + lda #$3C ; 9064 A9 3C .< + sta work_level_sub0 ; 9066 8D 82 07 ... + lda #$91 ; 9069 A9 91 .. + sta work_level_sub0+1 ; 906B 8D 83 07 ... +; some ISR is writing to $9c... +wait_until_9c_is_0e: + lda $9C ; 906E A5 9C .. + cmp #$0E ; 9070 C9 0E .. + bne wait_until_9c_is_0e ; 9072 D0 FA .. + lda #$E6 ; 9074 A9 E6 .. + sta work_level_sub0 ; 9076 8D 82 07 ... + lda #$06 ; 9079 A9 06 .. + sta work_level_sub0+1 ; 907B 8D 83 07 ... + lda #$00 ; 907E A9 00 .. + sta sfx_ptr ; 9080 8D 3C 06 .<. + lda #$93 ; 9083 A9 93 .. + sta sfx_ptr+1 ; 9085 8D 3D 06 .=. + jsr cue_sfx_jv ; 9088 20 06 80 .. + lda #$51 ; 908B A9 51 .Q + sta sfx_ptr ; 908D 8D 3C 06 .<. + lda #$93 ; 9090 A9 93 .. + sta sfx_ptr+1 ; 9092 8D 3D 06 .=. + jsr cue_sfx_jv ; 9095 20 06 80 .. + lda #$9C ; 9098 A9 9C .. + sta sfx_ptr ; 909A 8D 3C 06 .<. + lda #$93 ; 909D A9 93 .. + sta sfx_ptr+1 ; 909F 8D 3D 06 .=. + jsr cue_sfx_jv ; 90A2 20 06 80 .. + lda #$D7 ; 90A5 A9 D7 .. + sta sfx_ptr ; 90A7 8D 3C 06 .<. + lda #$93 ; 90AA A9 93 .. + sta sfx_ptr+1 ; 90AC 8D 3D 06 .=. + jsr cue_sfx_jv ; 90AF 20 06 80 .. + lda #$00 ; 90B2 A9 00 .. + sta $9C ; 90B4 85 9C .. + sta $9D ; 90B6 85 9D .. + lda #$07 ; 90B8 A9 07 .. + sta $B9 ; 90BA 85 B9 .. + lda #$72 ; 90BC A9 72 .r + sta work_level_sub0 ; 90BE 8D 82 07 ... + lda #$91 ; 90C1 A9 91 .. + sta work_level_sub0+1 ; 90C3 8D 83 07 ... + ldx #$FF ; 90C6 A2 FF .. +; lot going on here, not understood yet +funky_init_loop: + inx ; 90C8 E8 . + cpx #$02 ; 90C9 E0 02 .. + beq funky_init_loop ; 90CB F0 FB .. + cpx #$05 ; 90CD E0 05 .. + beq L910A ; 90CF F0 39 .9 + ldy L92A3,x ; 90D1 BC A3 92 ... +L90D4: lda $0649,y ; 90D4 B9 49 06 .I. + and #$0F ; 90D7 29 0F ). + beq L90D4 ; 90D9 F0 F9 .. + lda #$00 ; 90DB A9 00 .. + sta $066E,x ; 90DD 9D 6E 06 .n. + lda #$9D ; 90E0 A9 9D .. + sta $0673,x ; 90E2 9D 73 06 .s. + lda #$0A ; 90E5 A9 0A .. + sta $0678,x ; 90E7 9D 78 06 .x. + lda #$01 ; 90EA A9 01 .. + sta $0687,x ; 90EC 9D 87 06 ... + lda #$5C ; 90EF A9 5C .\ + sta $0682,x ; 90F1 9D 82 06 ... + lda L929E,x ; 90F4 BD 9E 92 ... + sta $067D,x ; 90F7 9D 7D 06 .}. + sta $0669,x ; 90FA 9D 69 06 .i. + ldy L92E8,x ; 90FD BC E8 92 ... + lda #$0F ; 9100 A9 0F .. + sta PCOLR0,y ; 9102 99 C0 02 ... + inc $9C ; 9105 E6 9C .. + jmp funky_init_loop ; 9107 4C C8 90 L.. + +; ---------------------------------------------------------------------------- +L910A: lda $9D ; 910A A5 9D .. + cmp #$1D ; 910C C9 1D .. + beq try_to_write_rom_again ; 910E F0 16 .. + cmp #$20 ; 9110 C9 20 . + bcc L910A ; 9112 90 F6 .. + lda #$E6 ; 9114 A9 E6 .. + sta work_level_sub0 ; 9116 8D 82 07 ... + lda #$06 ; 9119 A9 06 .. + sta work_level_sub0+1 ; 911B 8D 83 07 ... + lda #$08 ; 911E A9 08 .. + sta COLOR0 ; 9120 8D C4 02 ... + jmp LB96B ; 9123 4C 6B B9 Lk. + +; ---------------------------------------------------------------------------- +; see comment at try_to_write_rom +try_to_write_rom_again: + ldx #$08 ; 9126 A2 08 .. +L9128: lda L9133,x ; 9128 BD 33 91 .3. + sta block_char_minus_one,x ; 912B 9D 0F 9E ... + dex ; 912E CA . + bne L9128 ; 912F D0 F7 .. +L9133 := * + 2 + jmp L910A ; 9131 4C 0A 91 L.. + +; ---------------------------------------------------------------------------- +data_9134: + .byte $BF,$BF,$CF,$EF,$E7,$DB ; 9134 BF BF CF EF E7 DB ...... +; ---------------------------------------------------------------------------- +; this might be more data for the above table instead of code? +maybe_data: + cmp LADBF,y ; 913A D9 BF AD ... +; this probably really is code +probly_code: + rol a ; 913D 2A * + asl $8D ; 913E 06 8D .. + cpy $02 ; 9140 C4 02 .. + ldy $9C ; 9142 A4 9C .. + cpy #$07 ; 9144 C0 07 .. + beq L9164 ; 9146 F0 1C .. + clc ; 9148 18 . + lda $9D ; 9149 A5 9D .. + adc #$04 ; 914B 69 04 i. + sta $9D ; 914D 85 9D .. + beq L9164 ; 914F F0 13 .. + sta AUDF1 ; 9151 8D 00 D2 ... +L9154: lsr a ; 9154 4A J + lsr a ; 9155 4A J + lsr a ; 9156 4A J + lsr a ; 9157 4A J + ora #$60 ; 9158 09 60 .` + sta COLOR3 ; 915A 8D C7 02 ... + lda L928F,y ; 915D B9 8F 92 ... + sta $3045,y ; 9160 99 45 30 .E0 + rts ; 9163 60 ` + +; ---------------------------------------------------------------------------- +L9164: lda $3045,y ; 9164 B9 45 30 .E0 + and #$3F ; 9167 29 3F )? + sta $3045,y ; 9169 99 45 30 .E0 + inc $9C ; 916C E6 9C .. + iny ; 916E C8 . + jmp L9154 ; 916F 4C 54 91 LT. + +; ---------------------------------------------------------------------------- + lda $062A ; 9172 AD 2A 06 .*. + sta COLOR0 ; 9175 8D C4 02 ... + lda $9C ; 9178 A5 9C .. + cmp #$04 ; 917A C9 04 .. + beq L917F ; 917C F0 01 .. +L917E: rts ; 917E 60 ` + +; ---------------------------------------------------------------------------- +L917F: lda $0649 ; 917F AD 49 06 .I. + and #$0F ; 9182 29 0F ). + bne L917E ; 9184 D0 F8 .. + inc $B9 ; 9186 E6 B9 .. + lda $B9 ; 9188 A5 B9 .. + and #$0F ; 918A 29 0F ). + sta $B9 ; 918C 85 B9 .. + bne L917E ; 918E D0 EE .. + ldx $9D ; 9190 A6 9D .. + ldy #$FF ; 9192 A0 FF .. +L9194: iny ; 9194 C8 . + cpy #$02 ; 9195 C0 02 .. + beq L9194 ; 9197 F0 FB .. + cpy #$05 ; 9199 C0 05 .. + beq L91B0 ; 919B F0 13 .. + lda L92C8,x ; 919D BD C8 92 ... + sta $0687,y ; 91A0 99 87 06 ... + clc ; 91A3 18 . + lda L92A8,x ; 91A4 BD A8 92 ... + adc $067D,y ; 91A7 79 7D 06 y}. + sta $067D,y ; 91AA 99 7D 06 .}. + jmp L9194 ; 91AD 4C 94 91 L.. + +; ---------------------------------------------------------------------------- +L91B0: inc $9D ; 91B0 E6 9D .. + rts ; 91B2 60 ` + +; ---------------------------------------------------------------------------- +; display list for title screen +title_display_list: + .byte $70,$70,$70,$47,$00,$30,$06,$60 ; 91B3 70 70 70 47 00 30 06 60 pppG.0.` + .byte $60,$70,$70,$70,$70,$17,$17,$97 ; 91BB 60 70 70 70 70 17 17 97 `pppp... + .byte $70,$70,$70,$70,$70,$70,$70,$02 ; 91C3 70 70 70 70 70 70 70 02 ppppppp. + .byte $02,$41,$B3 ; 91CB 02 41 B3 .A. +title_screen_data_minus_one: + .byte $91 ; 91CE 91 . +; title screen data +title_screen_data: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 91CF 00 00 00 00 00 00 00 00 ........ + .byte $65,$70,$79,$78,$00,$00,$00,$00 ; 91D7 65 70 79 78 00 00 00 00 epyx.... + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 91DF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$70,$72,$65,$73,$65,$6E ; 91E7 00 00 70 72 65 73 65 6E ..presen + .byte $74,$73,$00,$00,$00,$00,$00,$00 ; 91EF 74 73 00 00 00 00 00 00 ts...... + .byte $00,$00,$00,$82,$82,$82,$82,$82 ; 91F7 00 00 00 82 82 82 82 82 ........ + .byte $82,$82,$82,$82,$82,$82,$82,$82 ; 91FF 82 82 82 82 82 82 82 82 ........ + .byte $82,$82,$82,$82,$82,$00,$00,$00 ; 9207 82 82 82 82 82 00 00 00 ........ + .byte $00,$00,$00,$82,$00,$00,$00,$00 ; 920F 00 00 00 82 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9217 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$82,$00,$00,$00 ; 921F 00 00 00 00 82 00 00 00 ........ + .byte $00,$00,$00,$82,$82,$82,$82,$82 ; 9227 00 00 00 82 82 82 82 82 ........ + .byte $82,$82,$82,$82,$82,$82,$82,$82 ; 922F 82 82 82 82 82 82 82 82 ........ + .byte $82,$82,$82,$82,$82,$00,$00,$00 ; 9237 82 82 82 82 82 00 00 00 ........ + .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 923F 40 40 40 40 40 40 40 40 @@@@@@@@ + .byte $40,$40,$40,$40,$48,$63,$49,$40 ; 9247 40 40 40 40 48 63 49 40 @@@@HcI@ + .byte $51,$59,$58,$53,$40,$62,$79,$40 ; 924F 51 59 58 53 40 62 79 40 QYXS@by@ + .byte $65,$70,$79,$78,$40,$40,$40,$40 ; 9257 65 70 79 78 40 40 40 40 epyx@@@@ + .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 925F 40 40 40 40 40 40 40 40 @@@@@@@@ + .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 9267 40 40 40 40 40 40 40 40 @@@@@@@@ + .byte $63,$72,$65,$61,$74,$65,$64,$40 ; 926F 63 72 65 61 74 65 64 40 created@ + .byte $62,$79,$5A,$40,$72,$61,$6E,$64 ; 9277 62 79 5A 40 72 61 6E 64 byZ@rand + .byte $79,$40,$67,$6C,$6F,$76,$65,$72 ; 927F 79 40 67 6C 6F 76 65 72 y@glover + .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 9287 40 40 40 40 40 40 40 40 @@@@@@@@ +L928F: .byte $EA,$F5,$ED,$F0,$ED,$E1,$EE,$00 ; 928F EA F5 ED F0 ED E1 EE 00 ........ + .byte $EA,$F5,$EE,$E9,$EF,$F2,$00 ; 9297 EA F5 EE E9 EF F2 00 ....... +L929E: .byte $6A,$76,$00,$82,$8E ; 929E 6A 76 00 82 8E jv... +L92A3: .byte $00,$02,$00,$04,$06 ; 92A3 00 02 00 04 06 ..... +L92A8: .byte $02,$02,$FE,$FE,$FE,$FE,$02,$02 ; 92A8 02 02 FE FE FE FE 02 02 ........ + .byte $02,$02,$02,$02,$FE,$FE,$FE,$FE ; 92B0 02 02 02 02 FE FE FE FE ........ + .byte $FE,$FE,$FE,$FE,$02,$02,$02,$02 ; 92B8 FE FE FE FE 02 02 02 02 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 92C0 00 00 00 00 00 00 00 00 ........ +L92C8: .byte $08,$09,$08,$09,$0C,$0D,$0C,$0D ; 92C8 08 09 08 09 0C 0D 0C 0D ........ + .byte $08,$06,$09,$06,$08,$10,$09,$10 ; 92D0 08 06 09 06 08 10 09 10 ........ + .byte $0C,$06,$0D,$06,$0C,$11,$0D,$11 ; 92D8 0C 06 0D 06 0C 11 0D 11 ........ + .byte $12,$13,$14,$15,$04,$04,$04,$04 ; 92E0 12 13 14 15 04 04 04 04 ........ +L92E8: .byte $07,$00,$00,$02,$03,$48,$A9,$94 ; 92E8 07 00 00 02 03 48 A9 94 .....H.. + .byte $8D,$0A,$D4,$8D,$18,$D0,$A9,$CA ; 92F0 8D 0A D4 8D 18 D0 A9 CA ........ + .byte $8D,$17,$D0,$68,$40,$00,$00,$00 ; 92F8 8D 17 D0 68 40 00 00 00 ...h@... + .byte $01,$A0,$02,$0A,$80,$01,$A5,$02 ; 9300 01 A0 02 0A 80 01 A5 02 ........ + .byte $3C,$20,$79,$20,$51,$20,$5B,$08 ; 9308 3C 20 79 20 51 20 5B 08 < y Q [. + .byte $60,$08,$6C,$08,$5B,$08,$60,$10 ; 9310 60 08 6C 08 5B 08 60 10 `.l.[.`. + .byte $79,$10,$5B,$08,$60,$08,$6C,$08 ; 9318 79 10 5B 08 60 08 6C 08 y.[.`.l. + .byte $5B,$08,$60,$10,$79,$10,$79,$20 ; 9320 5B 08 60 10 79 10 79 20 [.`.y.y + .byte $79,$20,$79,$08,$6C,$08,$60,$08 ; 9328 79 20 79 08 6C 08 60 08 y y.l.`. + .byte $51,$08,$3C,$20,$3C,$08,$51,$08 ; 9330 51 08 3C 20 3C 08 51 08 Q.< <.Q. + .byte $60,$08,$51,$08,$79,$20,$79,$08 ; 9338 60 08 51 08 79 20 79 08 `.Q.y y. + .byte $6C,$08,$60,$08,$5B,$08,$51,$08 ; 9340 6C 08 60 08 5B 08 51 08 l.`.[.Q. + .byte $48,$08,$40,$08,$51,$08,$3C,$40 ; 9348 48 08 40 08 51 08 3C 40 H.@.Q.<@ + .byte $00,$01,$A0,$02,$0A,$60,$01,$A3 ; 9350 00 01 A0 02 0A 60 01 A3 .....`.. + .byte $02,$51,$40,$79,$10,$A2,$10,$79 ; 9358 02 51 40 79 10 A2 10 79 .Q@y...y + .byte $10,$6C,$10,$79,$08,$A2,$08,$F3 ; 9360 10 6C 10 79 08 A2 08 F3 .l.y.... + .byte $10,$F3,$20,$79,$08,$A2,$08,$F3 ; 9368 10 F3 20 79 08 A2 08 F3 .. y.... + .byte $10,$A2,$10,$79,$10,$A2,$20,$F3 ; 9370 10 A2 10 79 10 A2 20 F3 ...y.. . + .byte $20,$79,$10,$A2,$10,$79,$10,$A2 ; 9378 20 79 10 A2 10 79 10 A2 y...y.. + .byte $10,$79,$10,$A2,$10,$F3,$10,$F3 ; 9380 10 79 10 A2 10 F3 10 F3 .y...... + .byte $10,$F3,$08,$D9,$08,$C1,$08,$B6 ; 9388 10 F3 08 D9 08 C1 08 B6 ........ + .byte $08,$A2,$08,$90,$08,$80,$08,$A2 ; 9390 08 A2 08 90 08 80 08 A2 ........ + .byte $08,$79,$40,$00,$01,$A0,$02,$0A ; 9398 08 79 40 00 01 A0 02 0A .y@..... + .byte $40,$01,$A4,$02,$60,$60,$01,$A0 ; 93A0 40 01 A4 02 60 60 01 A0 @...``.. + .byte $02,$0A,$10,$01,$A3,$02,$F3,$20 ; 93A8 02 0A 10 01 A3 02 F3 20 ....... + .byte $A2,$30,$A2,$10,$C1,$10,$02,$A6 ; 93B0 A2 30 A2 10 C1 10 02 A6 .0...... + .byte $93,$01,$01,$A0,$02,$0A,$10,$01 ; 93B8 93 01 01 A0 02 0A 10 01 ........ + .byte $A3,$02,$A2,$20,$A2,$20,$F3,$30 ; 93C0 A3 02 A2 20 A2 20 F3 30 ... . .0 + .byte $01,$A0,$02,$0A,$40,$01,$A4,$02 ; 93C8 01 A0 02 0A 40 01 A4 02 ....@... + .byte $79,$10,$A2,$10,$F3,$20,$00,$01 ; 93D0 79 10 A2 10 F3 20 00 01 y.... .. + .byte $A0,$02,$0A,$20,$01,$A4,$02,$79 ; 93D8 A0 02 0A 20 01 A4 02 79 ... ...y + .byte $78,$01,$A0,$02,$0A,$FF,$0A,$FF ; 93E0 78 01 A0 02 0A FF 0A FF x....... + .byte $0A,$40,$00,$00,$00,$00,$00,$00 ; 93E8 0A 40 00 00 00 00 00 00 .@...... + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 93F0 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 93F8 00 00 00 00 00 00 00 00 ........ +; ---------------------------------------------------------------------------- +ask_num_players: + ldx #$FF ; 9400 A2 FF .. + lda #$00 ; 9402 A9 00 .. + sta select_key_enabled ; 9404 8D C7 06 ... + sta level ; 9407 8D F6 06 ... + dec level ; 940A CE F6 06 ... +; clear area where NUMBER OF PLAYERS? will be displayed +anp_clear_loop: + sta $37FF,x ; 940D 9D FF 37 ..7 + dex ; 9410 CA . + bne anp_clear_loop ; 9411 D0 FA .. + jsr enable_joystick_jv ; 9413 20 1B 80 .. + ldx #$2C ; 9416 A2 2C ., +; copy NUMBER OF PLAYERS to screen RAM +anp_copy_loop: + lda numplayer_screen_data_minus_one,x; 9418 BD 9A 95 ... + sta $37FF,x ; 941B 9D FF 37 ..7 + dex ; 941E CA . + bne anp_copy_loop ; 941F D0 F7 .. +; X is now 0 +anp_loop_done: + stx $B7 ; 9421 86 B7 .. + stx $B8 ; 9423 86 B8 .. + stx randomizer_mode ; 9425 8E F3 06 ... + stx COLOR4 ; 9428 8E C8 02 ... + lda #$04 ; 942B A9 04 .. + sta HSCROL ; 942D 8D 04 D4 ... + sta $A0 ; 9430 85 A0 .. + lda #$1A ; 9432 A9 1A .. + sta COLOR3 ; 9434 8D C7 02 ... + lda #$96 ; 9437 A9 96 .. + sta COLOR2 ; 9439 8D C6 02 ... + lda #$C6 ; 943C A9 C6 .. + sta COLOR1 ; 943E 8D C5 02 ... + jsr init_page_7_jv ; 9441 20 24 80 $. +; set dlist shadow to point to numplayer_display_list +setup_numplayer_dlist: + lda #$5F ; 9444 A9 5F ._ + sta dlist_shadow_lo ; 9446 8D AC 06 ... + lda #$95 ; 9449 A9 95 .. + sta dlist_shadow_hi ; 944B 8D AD 06 ... +; set dli vector to point to num_player_dli_service +setup_numplayer_dli_sr: + lda #$78 ; 944E A9 78 .x + sta dli_vec_shadow_lo ; 9450 8D AE 06 ... + lda #$95 ; 9453 A9 95 .. + sta dli_vec_shadow_hi ; 9455 8D AF 06 ... +; we'll jump to $9489 aka option_key_handler when option key is pressed +setup_option_key_vec: + lda #$89 ; 9458 A9 89 .. + sta option_key_vec ; 945A 8D C0 06 ... + lda #$94 ; 945D A9 94 .. + sta option_key_vec+1 ; 945F 8D C1 06 ... + sta option_key_enabled ; 9462 8D C6 06 ... +; we'll jump to $94de aka get_player_speeds when start key is pressed +setup_start_key_vec: + lda #$DE ; 9465 A9 DE .. + sta start_key_vec ; 9467 8D C4 06 ... + lda #$94 ; 946A A9 94 .. + sta start_key_vec+1 ; 946C 8D C5 06 ... +; play sfx_select_key at $95f1 +play_select_key_sfx: + lda #$F1 ; 946F A9 F1 .. + sta sfx_ptr ; 9471 8D 3C 06 .<. + lda #$95 ; 9474 A9 95 .. + sta sfx_ptr+1 ; 9476 8D 3D 06 .=. + jsr cue_sfx_jv ; 9479 20 06 80 .. +; wait for sound to finish playing +wait_sfx: + lda sfx_slot_duration ; 947C AD 46 06 .F. + bne wait_sfx ; 947F D0 FB .. + lda #$01 ; 9481 A9 01 .. + sta start_key_enabled ; 9483 8D C8 06 ... +; initialization done, everything's done in interrupts from here on out +hang_main_thread: + jmp hang_main_thread ; 9486 4C 86 94 L.. + +; ---------------------------------------------------------------------------- +; called via option_key_vec when someone presses option +option_key_handler: + lda #$00 ; 9489 A9 00 .. + sta option_key_enabled ; 948B 8D C6 06 ... + lda $B8 ; 948E A5 B8 .. + clc ; 9490 18 . + adc #$01 ; 9491 69 01 i. + and #$03 ; 9493 29 03 ). + sta $B8 ; 9495 85 B8 .. + tay ; 9497 A8 . + lda number_names_0,y ; 9498 B9 DD 95 ... + sta $381D ; 949B 8D 1D 38 ..8 + lda number_names_1,y ; 949E B9 E1 95 ... + sta $381E ; 94A1 8D 1E 38 ..8 + lda number_names_2,y ; 94A4 B9 E5 95 ... + sta $381F ; 94A7 8D 1F 38 ..8 + lda number_names_3,y ; 94AA B9 E9 95 ... + sta $3820 ; 94AD 8D 20 38 . 8 + lda number_names_4,y ; 94B0 B9 ED 95 ... + sta $3821 ; 94B3 8D 21 38 .!8 + lda num_name_hscrol_table,y ; 94B6 B9 D9 95 ... + sta HSCROL ; 94B9 8D 04 D4 ... +play_opt_key_sfx: + lda #$B0 ; 94BC A9 B0 .. + sta sfx_ptr ; 94BE 8D 3C 06 .<. + lda #$8A ; 94C1 A9 8A .. + sta sfx_ptr+1 ; 94C3 8D 3D 06 .=. + jsr cue_sfx_jv ; 94C6 20 06 80 .. + lda #$00 ; 94C9 A9 00 .. + sta jiffy_timer_1 ; 94CB 8D 1A 06 ... +; wait until it's done playing +wait_opt_key_sfx: + lda jiffy_timer_1 ; 94CE AD 1A 06 ... + cmp #$08 ; 94D1 C9 08 .. + bcc wait_opt_key_sfx ; 94D3 90 F9 .. + sta option_key_enabled ; 94D5 8D C6 06 ... + sta start_key_enabled ; 94D8 8D C8 06 ... + jmp hang_main_thread ; 94DB 4C 86 94 L.. + +; ---------------------------------------------------------------------------- +; loop up to 4 times, ask PLAYER #n SPEED? and wait for number key press +get_player_speeds: + lda $B8 ; 94DE A5 B8 .. + sta $B9 ; 94E0 85 B9 .. + sta $06FF ; 94E2 8D FF 06 ... + sta number_of_players ; 94E5 8D F4 06 ... + lda #$00 ; 94E8 A9 00 .. + sta $B8 ; 94EA 85 B8 .. +; disable start and option keys +disable_start_opt: + sta option_key_enabled ; 94EC 8D C6 06 ... + sta start_key_enabled ; 94EF 8D C8 06 ... + sta $BA ; 94F2 85 BA .. + inc $B9 ; 94F4 E6 B9 .. + inc $BA ; 94F6 E6 BA .. + tay ; 94F8 A8 . +; copy PLAYER #n SPEED? to screen RAM +show_player_speed_prompt: + ldx #$00 ; 94F9 A2 00 .. +psprompt_loop: + lda player_x_speed,x ; 94FB BD C5 95 ... + sta $382C,y ; 94FE 99 2C 38 .,8 + inx ; 9501 E8 . + iny ; 9502 C8 . + cpx #$14 ; 9503 E0 14 .. + bne psprompt_loop ; 9505 D0 F4 .. + lda $BA ; 9507 A5 BA .. + sta current_player ; 9509 8D FE 06 ... + ora #$90 ; 950C 09 90 .. + inc $BA ; 950E E6 BA .. + sta $3821,y ; 9510 99 21 38 .!8 + dec $B9 ; 9513 C6 B9 .. + bne show_player_speed_prompt ; 9515 D0 E2 .. +; set select key vector to ask_num_players at $9400, enable select key +setup_select_key_vec_again: + lda #$00 ; 9517 A9 00 .. + sta select_key_vec ; 9519 8D C2 06 ... + lda #$94 ; 951C A9 94 .. + sta select_key_vec+1 ; 951E 8D C3 06 ... + sta select_key_enabled ; 9521 8D C7 06 ... + dec $BA ; 9524 C6 BA .. + ldy #$12 ; 9526 A0 12 .. + ldx #$00 ; 9528 A2 00 .. +; initialize speed to -1 +init_speed: + lda #$FF ; 952A A9 FF .. + sta speed_value ; 952C 8D F9 06 ... +; wait for keyboard IRQ handler to set a speed <= 8 +wait_for_speed: + lda speed_value ; 952F AD F9 06 ... + cmp #$09 ; 9532 C9 09 .. + bcs wait_for_speed ; 9534 B0 F9 .. + sta $0714,x ; 9536 9D 14 07 ... + pha ; 9539 48 H + clc ; 953A 18 . +; 11-byte per-player struct? +add_11_to_x: + txa ; 953B 8A . + adc #$0B ; 953C 69 0B i. + tax ; 953E AA . + pla ; 953F 68 h +; convert to ASCII digit +speed_to_ascii: + ora #$90 ; 9540 09 90 .. +; show it to the user +display_speed: + sta $382C,y ; 9542 99 2C 38 .,8 + tya ; 9545 98 . + clc ; 9546 18 . + adc #$14 ; 9547 69 14 i. + tay ; 9549 A8 . + inc $B8 ; 954A E6 B8 .. + dec $BA ; 954C C6 BA .. + bne init_speed ; 954E D0 DA .. + inc $06FF ; 9550 EE FF 06 ... + lda $06FF ; 9553 AD FF 06 ... + sta current_player ; 9556 8D FE 06 ... + inc current_player ; 9559 EE FE 06 ... + jmp afterlife ; 955C 4C 00 96 L.. + +; ---------------------------------------------------------------------------- +; display list for 'number of players' screen +numplayer_display_list: + .byte $70,$70,$70,$70,$47,$00,$38,$70 ; 955F 70 70 70 70 47 00 38 70 ppppG.8p + .byte $70,$97,$70,$70,$87,$70,$70,$87 ; 9567 70 97 70 70 87 70 70 87 p.pp.pp. + .byte $70,$70,$87,$70,$70,$07,$41,$5F ; 956F 70 70 87 70 70 07 41 5F pp.pp.A_ + .byte $95 ; 9577 95 . +; ---------------------------------------------------------------------------- +; DLI service routine, changes COLPF2, address gets stored in $6ae/$6af by code at $944e +num_player_dli_service: + pha ; 9578 48 H + lda $B7 ; 9579 A5 B7 .. + cmp $B8 ; 957B C5 B8 .. + sta WSYNC ; 957D 8D 0A D4 ... + bne L9592 ; 9580 D0 10 .. + lda $062A ; 9582 AD 2A 06 .*. + sta COLPF2 ; 9585 8D 18 D0 ... +L9588: inc $B7 ; 9588 E6 B7 .. + lda $B7 ; 958A A5 B7 .. + and #$03 ; 958C 29 03 ). + sta $B7 ; 958E 85 B7 .. + pla ; 9590 68 h + rti ; 9591 40 @ + +; ---------------------------------------------------------------------------- +L9592: lda COLOR2 ; 9592 AD C6 02 ... + sta COLPF2 ; 9595 8D 18 D0 ... +numplayer_screen_data_minus_one:= * + 2 ; 1-indexed loop copies from here+1 + jmp L9588 ; 9598 4C 88 95 L.. + +; ---------------------------------------------------------------------------- +; 'number of players?', gets copied to $3800, see option_key_handler +numplayer_screen_data: + .byte $00,$6E,$75,$6D,$62,$65,$72,$00 ; 959B 00 6E 75 6D 62 65 72 00 .number. + .byte $6F,$66,$00,$70,$6C,$61,$79,$65 ; 95A3 6F 66 00 70 6C 61 79 65 of.playe + .byte $72,$73,$5F,$00,$00,$00,$00,$00 ; 95AB 72 73 5F 00 00 00 00 00 rs_..... + .byte $00,$00,$00,$00,$00,$00,$EF,$EE ; 95B3 00 00 00 00 00 00 EF EE ........ + .byte $E5,$00,$00,$00,$00,$00,$00,$00 ; 95BB E5 00 00 00 00 00 00 00 ........ + .byte $00,$00 ; 95C3 00 00 .. +; ' PLAYER # SPEED? ' in PF2 color +player_x_speed: + .byte $00,$B0,$AC,$A1,$B9,$A5,$B2,$00 ; 95C5 00 B0 AC A1 B9 A5 B2 00 ........ + .byte $83,$80,$80,$B3,$B0,$A5,$A5,$A4 ; 95CD 83 80 80 B3 B0 A5 A5 A4 ........ + .byte $9F,$00,$00,$00 ; 95D5 9F 00 00 00 .... +; used for centering ONE TWO THREE FOUR, see option_key_handler +num_name_hscrol_table: + .byte $04,$04,$04,$00 ; 95D9 04 04 04 00 .... +; space space T space (names ONE TWO THREE FOUR) +number_names_0: + .byte $00,$00,$F4,$00 ; 95DD 00 00 F4 00 .... +; O T H F +number_names_1: + .byte $EF,$F4,$E8,$E6 ; 95E1 EF F4 E8 E6 .... +; N W R O +number_names_2: + .byte $EE,$F7,$F2,$EF ; 95E5 EE F7 F2 EF .... +; E O E U +number_names_3: + .byte $E5,$EF,$E5,$F5 ; 95E9 E5 EF E5 F5 .... +; space space E R +number_names_4: + .byte $00,$00,$E5,$F2 ; 95ED 00 00 E5 F2 .... +; played when select key pressed, 4 notes, descending +sfx_select_key: + .byte $01,$A4,$00,$1D,$08,$3C,$08,$79 ; 95F1 01 A4 00 1D 08 3C 08 79 .....<.y + .byte $08,$F3,$08,$00,$3C,$02,$00 ; 95F9 08 F3 08 00 3C 02 00 ....<.. +; ---------------------------------------------------------------------------- +; multiple code paths jump here. replay level, load next level, or go back to ask_num_players +afterlife: + jsr enable_joystick_jv ; 9600 20 1B 80 .. + jsr L8027 ; 9603 20 27 80 '. + lda $06F8 ; 9606 AD F8 06 ... + beq L960E ; 9609 F0 03 .. + jmp ask_num_players ; 960B 4C 00 94 L.. + +; ---------------------------------------------------------------------------- +L960E: lda $06F7 ; 960E AD F7 06 ... + beq L9616 ; 9611 F0 03 .. + jsr init_next_level ; 9613 20 E8 9B .. +L9616: lda #$00 ; 9616 A9 00 .. + sta bonus_jiffy_timer ; 9618 8D 26 06 .&. + sta $06F5 ; 961B 8D F5 06 ... + sta COLOR4 ; 961E 8D C8 02 ... + jmp L9BD0 ; 9621 4C D0 9B L.. + +; ---------------------------------------------------------------------------- +; only in multiplayer games +show_get_ready_prompt: + ldx current_player ; 9624 AE FE 06 ... + lda color0_table_minus_one,x ; 9627 BD 27 97 .'. + sta COLOR4 ; 962A 8D C8 02 ... + sta COLOR0 ; 962D 8D C4 02 ... + ldy #$14 ; 9630 A0 14 .. +L9632: lda L9713,y ; 9632 B9 13 97 ... + sta $0741,y ; 9635 99 41 07 .A. + dey ; 9638 88 . + bne L9632 ; 9639 D0 F7 .. + lda current_player ; 963B AD FE 06 ... + ora #$10 ; 963E 09 10 .. + sta $074A ; 9640 8D 4A 07 .J. + lda #$00 ; 9643 A9 00 .. + sta $B9 ; 9645 85 B9 .. + sta jiffy_timer_2 ; 9647 8D 1B 06 ... +; 06ac/06ad gets address of get_ready_dlist (why not SDLSTL/H?) +setup_get_ready_dl: + lda #$2C ; 964A A9 2C ., + sta dlist_shadow_lo ; 964C 8D AC 06 ... + lda #$97 ; 964F A9 97 .. + sta dlist_shadow_hi ; 9651 8D AD 06 ... + lda #$E6 ; 9654 A9 E6 .. + sta work_level_sub0 ; 9656 8D 82 07 ... + lda #$96 ; 9659 A9 96 .. + sta work_level_sub0+1 ; 965B 8D 83 07 ... + jsr clear_screen_mem_jv ; 965E 20 1E 80 .. + lda cur_level_map0 ; 9661 AD D6 07 ... + sta dm_progctr ; 9664 85 C0 .. + lda cur_level_map0+1 ; 9666 AD D7 07 ... + sta dm_progctr+1 ; 9669 85 C1 .. + jsr draw_map_jv ; 966B 20 00 80 .. +L966E: lda jiffy_timer_2 ; 966E AD 1B 06 ... + cmp #$F2 ; 9671 C9 F2 .. + bne L966E ; 9673 D0 F9 .. +L9675: ldx #$00 ; 9675 A2 00 .. +; copy level descriptor to $0780 +copy_level_desc_2: + lda cur_level_desc,x ; 9677 BD C0 07 ... + sta work_level_desc,x ; 967A 9D 80 07 ... + inx ; 967D E8 . + cpx #$40 ; 967E E0 40 .@ + bne copy_level_desc_2 ; 9680 D0 F5 .. + lda work_level_sub5 ; 9682 AD A2 07 ... + sta $06E1 ; 9685 8D E1 06 ... + lda work_level_sub5+1 ; 9688 AD A3 07 ... + sta $06E2 ; 968B 8D E2 06 ... + jsr L06E0 ; 968E 20 E0 06 .. + lda #$00 ; 9691 A9 00 .. + sta COLOR4 ; 9693 8D C8 02 ... + sta $06AB ; 9696 8D AB 06 ... + lda work_level_offs_46+1 ; 9699 AD AF 07 ... + sta COLOR0 ; 969C 8D C4 02 ... + lda work_level_offs_46+2 ; 969F AD B0 07 ... + sta COLOR1 ; 96A2 8D C5 02 ... + lda work_level_offs_46+3 ; 96A5 AD B1 07 ... + sta COLOR2 ; 96A8 8D C6 02 ... + lda work_level_offs_46 ; 96AB AD AE 07 ... + sta COLOR3 ; 96AE 8D C7 02 ... + jsr setup_gameboard_dlist_jv ; 96B1 20 15 80 .. + inc $06F5 ; 96B4 EE F5 06 ... + jmp L9BDD ; 96B7 4C DD 9B L.. + +; ---------------------------------------------------------------------------- +; maybe this should be check_level or init_level? +enter_level: + lda #$00 ; 96BA A9 00 .. + tay ; 96BC A8 . + sta $D7 ; 96BD 85 D7 .. + sta $D8 ; 96BF 85 D8 .. + inc level ; 96C1 EE F6 06 ... + lda level ; 96C4 AD F6 06 ... + cmp #$0C ; 96C7 C9 0C .. + bne copy_level_desc ; 96C9 D0 03 .. + jmp ask_num_players ; 96CB 4C 00 94 L.. + +; ---------------------------------------------------------------------------- +; copy level descriptor from levelXX_desc at $A000+(level*$40) to $07c0-$07ff +copy_level_desc: + lsr a ; 96CE 4A J + ror $D7 ; 96CF 66 D7 f. + lsr a ; 96D1 4A J + ror $D7 ; 96D2 66 D7 f. + ora #$A0 ; 96D4 09 A0 .. + sta $D8 ; 96D6 85 D8 .. +sl_loop:lda ($D7),y ; 96D8 B1 D7 .. + sta cur_level_desc,y ; 96DA 99 C0 07 ... + iny ; 96DD C8 . + cpy #$40 ; 96DE C0 40 .@ + bne sl_loop ; 96E0 D0 F6 .. + jsr L802A ; 96E2 20 2A 80 *. + rts ; 96E5 60 ` + +; ---------------------------------------------------------------------------- + lda jiffy_timer_2 ; 96E6 AD 1B 06 ... + cmp #$F0 ; 96E9 C9 F0 .. + bcs L9709 ; 96EB B0 1C .. + and #$1F ; 96ED 29 1F ). + beq L96F2 ; 96EF F0 01 .. + rts ; 96F1 60 ` + +; ---------------------------------------------------------------------------- +L96F2: lda COLOR0 ; 96F2 AD C4 02 ... + cmp #$0F ; 96F5 C9 0F .. + beq L96FF ; 96F7 F0 06 .. + lda #$0F ; 96F9 A9 0F .. + sta COLOR0 ; 96FB 8D C4 02 ... + rts ; 96FE 60 ` + +; ---------------------------------------------------------------------------- +L96FF: ldx current_player ; 96FF AE FE 06 ... + lda color0_table_minus_one,x ; 9702 BD 27 97 .'. + sta COLOR0 ; 9705 8D C4 02 ... + rts ; 9708 60 ` + +; ---------------------------------------------------------------------------- +L9709: lda #$E6 ; 9709 A9 E6 .. + sta work_level_sub0 ; 970B 8D 82 07 ... + lda #$06 ; 970E A9 06 .. + sta work_level_sub0+1 ; 9710 8D 83 07 ... +L9713: rts ; 9713 60 ` + +; ---------------------------------------------------------------------------- +; PLAYER GET READY +get_ready_msg: + .byte $00,$30,$2C,$21,$39,$25,$32,$00 ; 9714 00 30 2C 21 39 25 32 00 .0,!9%2. + .byte $00,$00,$27,$25,$34,$00,$32,$25 ; 971C 00 00 27 25 34 00 32 25 ..'%4.2% + .byte $21,$24,$39 ; 9724 21 24 39 !$9 +color0_table_minus_one: + .byte $00 ; 9727 00 . +color0_table: + .byte $96,$24,$C6,$54 ; 9728 96 24 C6 54 .$.T +; 112 blank scanlines, then one GR.2 line, loaded from $0742 +get_ready_dlist: + .byte $70,$70,$70,$70,$70,$70,$70,$70 ; 972C 70 70 70 70 70 70 70 70 pppppppp + .byte $70,$70,$70,$70,$70,$70,$47,$42 ; 9734 70 70 70 70 70 70 47 42 ppppppGB + .byte $07,$41,$2C,$97 ; 973C 07 41 2C 97 .A,. +; ---------------------------------------------------------------------------- +game_main_loop: + jsr materialize_jumpman ; 9740 20 7B 97 {. +L9743: jsr L8033 ; 9743 20 33 80 3. + lda work_level_num_bombs ; 9746 AD 8A 07 ... + beq got_all_bombs ; 9749 F0 1B .. + lda $0623 ; 974B AD 23 06 .#. + cmp #$02 ; 974E C9 02 .. + bne L9743 ; 9750 D0 F1 .. +L9752: lda $0623 ; 9752 AD 23 06 .#. + cmp #$02 ; 9755 C9 02 .. + beq L9752 ; 9757 F0 F9 .. + lda lives ; 9759 AD 0A 07 ... + cmp #$FF ; 975C C9 FF .. + bne game_main_loop ; 975E D0 E0 .. + jsr call_eol_sub ; 9760 20 6C 97 l. + jmp crumble_gameboard_jv ; 9763 4C 30 80 L0. + +; ---------------------------------------------------------------------------- +got_all_bombs: + jsr call_eol_sub ; 9766 20 6C 97 l. + jmp level_finished_jv ; 9769 4C 2D 80 L-. + +; ---------------------------------------------------------------------------- +call_eol_sub: + lda work_level_sub_eol ; 976C AD A6 07 ... + sta $06E4 ; 976F 8D E4 06 ... + lda work_level_sub_eol+1 ; 9772 AD A7 07 ... + sta $06E5 ; 9775 8D E5 06 ... + jmp L06E3 ; 9778 4C E3 06 L.. + +; ---------------------------------------------------------------------------- +materialize_jumpman: + jsr update_status_window_jv ; 977B 20 12 80 .. + ldx #$04 ; 977E A2 04 .. + lda #$00 ; 9780 A9 00 .. +mj_clear_loop: + sta $0755,x ; 9782 9D 55 07 .U. + sta $069A,x ; 9785 9D 9A 06 ... + sta $06EA,x ; 9788 9D EA 06 ... + sta $06EB,x ; 978B 9D EB 06 ... + dex ; 978E CA . + bne mj_clear_loop ; 978F D0 F1 .. + sta $0697 ; 9791 8D 97 06 ... + sta $0698 ; 9794 8D 98 06 ... + sta PCOLR0 ; 9797 8D C0 02 ... + sta $BA ; 979A 85 BA .. + sta AUDF4 ; 979C 8D 06 D2 ... + lda work_level_y_start ; 979F AD 8C 07 ... + sta $0683 ; 97A2 8D 83 06 ... + lda work_level_x_start ; 97A5 AD 8D 07 ... + sta $067E ; 97A8 8D 7E 06 .~. + lda #$01 ; 97AB A9 01 .. + sta $0688 ; 97AD 8D 88 06 ... + lda #$A5 ; 97B0 A9 A5 .. + sta AUDC4 ; 97B2 8D 07 D2 ... + inc $066A ; 97B5 EE 6A 06 .j. + inc $066B ; 97B8 EE 6B 06 .k. +mj_set_freq_and_color: + inc $BA ; 97BB E6 BA .. + beq mj_done ; 97BD F0 1C .. + lda $BA ; 97BF A5 BA .. + sta AUDF4 ; 97C1 8D 06 D2 ... + lsr a ; 97C4 4A J + lsr a ; 97C5 4A J + lsr a ; 97C6 4A J + lsr a ; 97C7 4A J + sta PCOLR0 ; 97C8 8D C0 02 ... + ldx #$FF ; 97CB A2 FF .. +mj_delay: + dex ; 97CD CA . + nop ; 97CE EA . + nop ; 97CF EA . + nop ; 97D0 EA . + nop ; 97D1 EA . + nop ; 97D2 EA . + nop ; 97D3 EA . + nop ; 97D4 EA . + nop ; 97D5 EA . + bne mj_delay ; 97D6 D0 F5 .. + jmp mj_set_freq_and_color ; 97D8 4C BB 97 L.. + +; ---------------------------------------------------------------------------- +mj_done:lda #$00 ; 97DB A9 00 .. + sta AUDF4 ; 97DD 8D 06 D2 ... + sta AUDC4 ; 97E0 8D 07 D2 ... + sta $0623 ; 97E3 8D 23 06 .#. + lda initial_speed ; 97E6 AD 25 06 .%. + sta player_speed ; 97E9 8D 24 06 .$. + inc playing_level ; 97EC EE 27 06 .'. + rts ; 97EF 60 ` + +; ---------------------------------------------------------------------------- + brk ; 97F0 00 . + brk ; 97F1 00 . + brk ; 97F2 00 . + brk ; 97F3 00 . + brk ; 97F4 00 . + brk ; 97F5 00 . + brk ; 97F6 00 . + brk ; 97F7 00 . + brk ; 97F8 00 . + brk ; 97F9 00 . + brk ; 97FA 00 . + brk ; 97FB 00 . + brk ; 97FC 00 . + brk ; 97FD 00 . + brk ; 97FE 00 . + brk ; 97FF 00 . + lda $0621 ; 9800 AD 21 06 .!. + bne L9806 ; 9803 D0 01 .. +L9805: rts ; 9805 60 ` + +; ---------------------------------------------------------------------------- +L9806: lda $0623 ; 9806 AD 23 06 .#. + bne L9805 ; 9809 D0 FA .. + lda $0683 ; 980B AD 83 06 ... + cmp #$C6 ; 980E C9 C6 .. + bcs L982E ; 9810 B0 1C .. + lda $06EB ; 9812 AD EB 06 ... + beq check_collisions_2 ; 9815 F0 03 .. + jmp L99A8 ; 9817 4C A8 99 L.. + +; ---------------------------------------------------------------------------- +; did player 0 or 1 hit the playfield... +check_collisions_2: + lda #$01 ; 981A A9 01 .. + sta $0688 ; 981C 8D 88 06 ... + lda $06ED ; 981F AD ED 06 ... + beq check_collisions_3 ; 9822 F0 0E .. + lda collision_save+4 ; 9824 AD B4 06 ... + ora collision_save+5 ; 9827 0D B5 06 ... + and #$03 ; 982A 29 03 ). + bne check_collisions_3 ; 982C D0 04 .. +L982E: inc $0623 ; 982E EE 23 06 .#. + rts ; 9831 60 ` + +; ---------------------------------------------------------------------------- +; did player 0 or 1 hit the playfield... +check_collisions_3: + lda #$00 ; 9832 A9 00 .. + sta $06ED ; 9834 8D ED 06 ... + lda collision_save+4 ; 9837 AD B4 06 ... + ora collision_save+5 ; 983A 0D B5 06 ... + and #$03 ; 983D 29 03 ). + bne check_trigger_state ; 983F D0 0C .. + inc $06ED ; 9841 EE ED 06 ... + inc $0683 ; 9844 EE 83 06 ... + inc $0683 ; 9847 EE 83 06 ... + jmp L989F ; 984A 4C 9F 98 L.. + +; ---------------------------------------------------------------------------- +; did user press the trigger? +check_trigger_state: + lda trigger_state ; 984D AD 35 06 .5. + bne check_up_down ; 9850 D0 03 .. +; yes, jump to handler +trig_jmp: + jmp trigger_handler ; 9852 4C 85 99 L.. + +; ---------------------------------------------------------------------------- +; did user move joystick up/down? +check_up_down: + lda joystick_state ; 9855 AD 33 06 .3. + cmp #$0E ; 9858 C9 0E .. + beq L9863 ; 985A F0 07 .. + cmp #$0D ; 985C C9 0D .. + beq L9863 ; 985E F0 03 .. +; no, jump over handler +cud_jmp:jmp L9892 ; 9860 4C 92 98 L.. + +; ---------------------------------------------------------------------------- +L9863: lda collision_save+4 ; 9863 AD B4 06 ... + ora collision_save+5 ; 9866 0D B5 06 ... + and #$02 ; 9869 29 02 ). + bne L9870 ; 986B D0 03 .. + jmp L98D0 ; 986D 4C D0 98 L.. + +; ---------------------------------------------------------------------------- +L9870: jsr check_up_down_2 ; 9870 20 3B 99 ;. + bcs L9878 ; 9873 B0 03 .. + jmp L98D0 ; 9875 4C D0 98 L.. + +; ---------------------------------------------------------------------------- +L9878: sta $067E ; 9878 8D 7E 06 .~. + lda player_delta_y ; 987B AD 31 06 .1. + asl a ; 987E 0A . + clc ; 987F 18 . + adc $0683 ; 9880 6D 83 06 m.. + sta $0683 ; 9883 8D 83 06 ... + lda $0620 ; 9886 AD 20 06 . . + clc ; 9889 18 . + adc #$04 ; 988A 69 04 i. + sta $0688 ; 988C 8D 88 06 ... + jmp play_sfx_bounce_2 ; 988F 4C 80 8A L.. + +; ---------------------------------------------------------------------------- +L9892: lda collision_save+4 ; 9892 AD B4 06 ... + ora collision_save+5 ; 9895 0D B5 06 ... + and #$01 ; 9898 29 01 ). + bne L989F ; 989A D0 03 .. + jmp L98D0 ; 989C 4C D0 98 L.. + +; ---------------------------------------------------------------------------- +L989F: lda player_delta_x ; 989F AD 30 06 .0. + beq L98D0 ; 98A2 F0 2C ., + asl a ; 98A4 0A . + ldx #$08 ; 98A5 A2 08 .. + cmp #$02 ; 98A7 C9 02 .. + beq L98AD ; 98A9 F0 02 .. + ldx #$0C ; 98AB A2 0C .. +L98AD: clc ; 98AD 18 . + adc $067E ; 98AE 6D 7E 06 m~. + sta $067E ; 98B1 8D 7E 06 .~. + txa ; 98B4 8A . + clc ; 98B5 18 . + adc $0620 ; 98B6 6D 20 06 m . + sta $0688 ; 98B9 8D 88 06 ... + lda $061F ; 98BC AD 1F 06 ... + bne L98D0 ; 98BF D0 0F .. + lda #$73 ; 98C1 A9 73 .s + sta sfx_slot_tempo ; 98C3 8D 3E 06 .>. + lda #$BE ; 98C6 A9 BE .. + sta sfx_slot_timer ; 98C8 8D 3F 06 .?. + lda #$01 ; 98CB A9 01 .. + jsr L8003 ; 98CD 20 03 80 .. +L98D0: lda collision_save+4 ; 98D0 AD B4 06 ... + ora collision_save+5 ; 98D3 0D B5 06 ... + and #$02 ; 98D6 29 02 ). + beq L98F0 ; 98D8 F0 16 .. + jsr L9971 ; 98DA 20 71 99 q. + bcc L990F ; 98DD 90 30 .0 + inc $0683 ; 98DF EE 83 06 ... + inc $0683 ; 98E2 EE 83 06 ... + lda $061F ; 98E5 AD 1F 06 ... + ora #$02 ; 98E8 09 02 .. + sta $0688 ; 98EA 8D 88 06 ... + jmp L9925 ; 98ED 4C 25 99 L%. + +; ---------------------------------------------------------------------------- +L98F0: lda collision_save+4 ; 98F0 AD B4 06 ... + and #$01 ; 98F3 29 01 ). + beq L990F ; 98F5 F0 18 .. + dec $0683 ; 98F7 CE 83 06 ... + dec $0683 ; 98FA CE 83 06 ... + lda $0688 ; 98FD AD 88 06 ... + cmp #$01 ; 9900 C9 01 .. + bne L990F ; 9902 D0 0B .. + lda $061F ; 9904 AD 1F 06 ... + ora #$02 ; 9907 09 02 .. + sta $0688 ; 9909 8D 88 06 ... + jmp L9925 ; 990C 4C 25 99 L%. + +; ---------------------------------------------------------------------------- +L990F: lda $0688 ; 990F AD 88 06 ... + cmp #$01 ; 9912 C9 01 .. + bne L9925 ; 9914 D0 0F .. + lda collision_save+4 ; 9916 AD B4 06 ... + ora collision_save+5 ; 9919 0D B5 06 ... + and #$02 ; 991C 29 02 ). + beq L9925 ; 991E F0 05 .. + lda #$04 ; 9920 A9 04 .. + sta $0688 ; 9922 8D 88 06 ... +L9925: lda $0688 ; 9925 AD 88 06 ... + sta $0689 ; 9928 8D 89 06 ... + lda $067E ; 992B AD 7E 06 .~. + sta $067F ; 992E 8D 7F 06 ... + lda $0683 ; 9931 AD 83 06 ... + clc ; 9934 18 . + adc #$0A ; 9935 69 0A i. + sta $0684 ; 9937 8D 84 06 ... + rts ; 993A 60 ` + +; ---------------------------------------------------------------------------- +; did user move joystick up/down? +check_up_down_2: + lda joystick_state ; 993B AD 33 06 .3. + cmp #$0D ; 993E C9 0D .. + bne L9949 ; 9940 D0 07 .. + lda $0683 ; 9942 AD 83 06 ... + cmp #$C0 ; 9945 C9 C0 .. + bcs L9967 ; 9947 B0 1E .. +L9949: lda $067E ; 9949 AD 7E 06 .~. + sec ; 994C 38 8 + sbc #$30 ; 994D E9 30 .0 + sta zp_temp1 ; 994F 85 CB .. + ldx #$08 ; 9951 A2 08 .. +L9953: lda work_level_offs_46+3,x ; 9953 BD B1 07 ... + clc ; 9956 18 . + adc #$02 ; 9957 69 02 i. + cmp zp_temp1 ; 9959 C5 CB .. + bcc L9964 ; 995B 90 07 .. + sec ; 995D 38 8 + sbc #$05 ; 995E E9 05 .. + cmp zp_temp1 ; 9960 C5 CB .. + bcc L9969 ; 9962 90 05 .. +L9964: dex ; 9964 CA . + bne L9953 ; 9965 D0 EC .. +L9967: clc ; 9967 18 . + rts ; 9968 60 ` + +; ---------------------------------------------------------------------------- +L9969: lda work_level_offs_46+3,x ; 9969 BD B1 07 ... + clc ; 996C 18 . + adc #$30 ; 996D 69 30 i0 + sec ; 996F 38 8 + rts ; 9970 60 ` + +; ---------------------------------------------------------------------------- +L9971: lda $067E ; 9971 AD 7E 06 .~. + sec ; 9974 38 8 + sbc #$30 ; 9975 E9 30 .0 + ldx #$06 ; 9977 A2 06 .. +L9979: cmp work_level_offs_55+2,x ; 9979 DD B9 07 ... + beq L9983 ; 997C F0 05 .. + dex ; 997E CA . + bne L9979 ; 997F D0 F8 .. + clc ; 9981 18 . + rts ; 9982 60 ` + +; ---------------------------------------------------------------------------- +L9983: sec ; 9983 38 8 + rts ; 9984 60 ` + +; ---------------------------------------------------------------------------- +; handle trigger presses (maybe start a jump) +trigger_handler: + ldx #$04 ; 9985 A2 04 .. + lda joystick_state ; 9987 AD 33 06 .3. + cmp #$0E ; 998A C9 0E .. + beq L99A0 ; 998C F0 12 .. + ldx #$10 ; 998E A2 10 .. + lda player_delta_x ; 9990 AD 30 06 .0. + cmp #$01 ; 9993 C9 01 .. + beq L99A0 ; 9995 F0 09 .. + ldx #$11 ; 9997 A2 11 .. + cmp #$FF ; 9999 C9 FF .. + beq L99A0 ; 999B F0 03 .. + jmp check_up_down ; 999D 4C 55 98 LU. + +; ---------------------------------------------------------------------------- +L99A0: stx $0688 ; 99A0 8E 88 06 ... + lda #$01 ; 99A3 A9 01 .. + jsr cue_music_jv ; 99A5 20 18 80 .. +L99A8: inc $06EB ; 99A8 EE EB 06 ... + lda $06EB ; 99AB AD EB 06 ... + cmp #$16 ; 99AE C9 16 .. + bne L99BD ; 99B0 D0 0B .. +L99B2: lda #$00 ; 99B2 A9 00 .. + sta $06EB ; 99B4 8D EB 06 ... + sta $06ED ; 99B7 8D ED 06 ... + jmp check_collisions_2 ; 99BA 4C 1A 98 L.. + +; ---------------------------------------------------------------------------- +L99BD: ldx $06EB ; 99BD AE EB 06 ... + lda L9A1B,x ; 99C0 BD 1B 9A ... + tay ; 99C3 A8 . + lda $0688 ; 99C4 AD 88 06 ... + cmp #$10 ; 99C7 C9 10 .. + beq L99DD ; 99C9 F0 12 .. + cmp #$11 ; 99CB C9 11 .. + bne L99DB ; 99CD D0 0C .. + tya ; 99CF 98 . + sta zp_temp1+1 ; 99D0 85 CC .. + lda #$00 ; 99D2 A9 00 .. + sec ; 99D4 38 8 + sbc zp_temp1+1 ; 99D5 E5 CC .. + tay ; 99D7 A8 . + jmp L99DD ; 99D8 4C DD 99 L.. + +; ---------------------------------------------------------------------------- +L99DB: ldy #$00 ; 99DB A0 00 .. +L99DD: clc ; 99DD 18 . + tya ; 99DE 98 . + adc $067E ; 99DF 6D 7E 06 m~. + sta $067E ; 99E2 8D 7E 06 .~. + lda L9A31,x ; 99E5 BD 31 9A .1. + clc ; 99E8 18 . + adc $0683 ; 99E9 6D 83 06 m.. + sta $0683 ; 99EC 8D 83 06 ... + txa ; 99EF 8A . + cmp #$08 ; 99F0 C9 08 .. + bcs code_99f7 ; 99F2 B0 03 .. + jmp L9925 ; 99F4 4C 25 99 L%. + +; ---------------------------------------------------------------------------- +code_99f7: + lda collision_save+4 ; 99F7 AD B4 06 ... + ora collision_save+5 ; 99FA 0D B5 06 ... + lsr a ; 99FD 4A J + bcs L99B2 ; 99FE B0 B2 .. + lsr a ; 9A00 4A J + bcc L9A19 ; 9A01 90 16 .. + lda $0688 ; 9A03 AD 88 06 ... + cmp #$04 ; 9A06 C9 04 .. + beq L9A19 ; 9A08 F0 0F .. + jsr L9971 ; 9A0A 20 71 99 q. + bcs L99B2 ; 9A0D B0 A3 .. + jsr check_up_down_2 ; 9A0F 20 3B 99 ;. + bcc L9A19 ; 9A12 90 05 .. + cmp $067E ; 9A14 CD 7E 06 .~. + beq L99B2 ; 9A17 F0 99 .. +L9A19: +L9A1B := * + 2 + jmp L9925 ; 9A19 4C 25 99 L%. + +; ---------------------------------------------------------------------------- +data_9a1c: + .byte $02,$00,$02,$00,$02,$02,$02,$02 ; 9A1C 02 00 02 00 02 02 02 02 ........ + .byte $02,$02,$02,$00,$02,$00,$02,$00 ; 9A24 02 02 02 00 02 00 02 00 ........ + .byte $00,$02,$00,$00,$00 ; 9A2C 00 02 00 00 00 ..... +L9A31: .byte $02,$FE,$FE,$FE,$FE,$FE,$FE,$00 ; 9A31 02 FE FE FE FE FE FE 00 ........ + .byte $00,$00,$02,$02,$02,$02,$02,$02 ; 9A39 00 00 02 02 02 02 02 02 ........ + .byte $02,$02,$02,$02,$02,$02,$00,$00 ; 9A41 02 02 02 02 02 02 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9A49 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9A51 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00 ; 9A59 00 00 00 ... +; ---------------------------------------------------------------------------- +init_page_7: + ldy #$00 ; 9A5C A0 00 .. +L9A5E: ldx #$00 ; 9A5E A2 00 .. +L9A60: lda data_9a71,x ; 9A60 BD 71 9A .q. + sta score,y ; 9A63 99 00 07 ... + inx ; 9A66 E8 . + iny ; 9A67 C8 . + cpx #$0B ; 9A68 E0 0B .. + bne L9A60 ; 9A6A D0 F4 .. + cpy #$37 ; 9A6C C0 37 .7 + bne L9A5E ; 9A6E D0 EE .. + rts ; 9A70 60 ` + +; ---------------------------------------------------------------------------- +; used by code above +data_9a71: + .byte $00,$00,$00,$4C,$1D,$00,$00,$00 ; 9A71 00 00 00 4C 1D 00 00 00 ...L.... + .byte $00,$06,$03 ; 9A79 00 06 03 ... +; ---------------------------------------------------------------------------- +L9A7C: ldx current_player ; 9A7C AE FE 06 ... + lda #$00 ; 9A7F A9 00 .. + clc ; 9A81 18 . +L9A82: dex ; 9A82 CA . + beq L9A8A ; 9A83 F0 05 .. + adc #$0B ; 9A85 69 0B i. + jmp L9A82 ; 9A87 4C 82 9A L.. + +; ---------------------------------------------------------------------------- +L9A8A: tay ; 9A8A A8 . + rts ; 9A8B 60 ` + +; ---------------------------------------------------------------------------- +L9A8C: ldx #$00 ; 9A8C A2 00 .. +L9A8E: lda score,x ; 9A8E BD 00 07 ... + sta $070B,y ; 9A91 99 0B 07 ... + inx ; 9A94 E8 . + iny ; 9A95 C8 . + cpx #$0B ; 9A96 E0 0B .. + bne L9A8E ; 9A98 D0 F4 .. + rts ; 9A9A 60 ` + +; ---------------------------------------------------------------------------- +L9A9B: ldx #$00 ; 9A9B A2 00 .. +L9A9D: lda $070B,y ; 9A9D B9 0B 07 ... + sta score,x ; 9AA0 9D 00 07 ... + inx ; 9AA3 E8 . + iny ; 9AA4 C8 . + cpx #$0B ; 9AA5 E0 0B .. + bne L9A9D ; 9AA7 D0 F4 .. + rts ; 9AA9 60 ` + +; ---------------------------------------------------------------------------- +L9AAA: jsr L9A7C ; 9AAA 20 7C 9A |. + jsr L9A8C ; 9AAD 20 8C 9A .. + lda #$00 ; 9AB0 A9 00 .. + sta $06F7 ; 9AB2 8D F7 06 ... + sta $06F8 ; 9AB5 8D F8 06 ... +L9AB8: inc current_player ; 9AB8 EE FE 06 ... + lda $06FF ; 9ABB AD FF 06 ... + cmp current_player ; 9ABE CD FE 06 ... + bcs L9ACB ; 9AC1 B0 08 .. + lda #$01 ; 9AC3 A9 01 .. + sta current_player ; 9AC5 8D FE 06 ... + sta $06F7 ; 9AC8 8D F7 06 ... +L9ACB: ldx number_of_players ; 9ACB AE F4 06 ... + inx ; 9ACE E8 . + ldy L9AFB,x ; 9ACF BC FB 9A ... +L9AD2: lda $0715,y ; 9AD2 B9 15 07 ... + cmp #$FF ; 9AD5 C9 FF .. + bne L9AE5 ; 9AD7 D0 0C .. + tya ; 9AD9 98 . + sec ; 9ADA 38 8 + sbc #$0B ; 9ADB E9 0B .. + tay ; 9ADD A8 . + dex ; 9ADE CA . + bne L9AD2 ; 9ADF D0 F1 .. + inc $06F8 ; 9AE1 EE F8 06 ... + rts ; 9AE4 60 ` + +; ---------------------------------------------------------------------------- +L9AE5: stx $06FF ; 9AE5 8E FF 06 ... + jsr L9A7C ; 9AE8 20 7C 9A |. + jsr L9A9B ; 9AEB 20 9B 9A .. + lda lives ; 9AEE AD 0A 07 ... + cmp #$FF ; 9AF1 C9 FF .. + beq L9AB8 ; 9AF3 F0 C3 .. + lda $0709 ; 9AF5 AD 09 07 ... + sta initial_speed ; 9AF8 8D 25 06 .%. +L9AFB: rts ; 9AFB 60 ` + +; ---------------------------------------------------------------------------- +data_9afc: + .byte $00,$0B,$16,$21 ; 9AFC 00 0B 16 21 ...! +; ---------------------------------------------------------------------------- +; for some reason there are 2 copies of the display list, at $0800 and $0881 +setup_gameboard_dlist: + ldx #$00 ; 9B00 A2 00 .. + lda dlist_shadow_lo ; 9B02 AD AC 06 ... + bne L9B09 ; 9B05 D0 02 .. + ldx #$81 ; 9B07 A2 81 .. +L9B09: lda #$70 ; 9B09 A9 70 .p + stx $9F ; 9B0B 86 9F .. + ldy #$03 ; 9B0D A0 03 .. + sty $9D ; 9B0F 84 9D .. +L9B11: sta $0800,x ; 9B11 9D 00 08 ... + inx ; 9B14 E8 . + dey ; 9B15 88 . + bne L9B11 ; 9B16 D0 F9 .. + ldy $06AB ; 9B18 AC AB 06 ... +L9B1B: lda gameboard_dlist_data,y ; 9B1B B9 62 9B .b. + sta $0800,x ; 9B1E 9D 00 08 ... + iny ; 9B21 C8 . + inx ; 9B22 E8 . + dec $9D ; 9B23 C6 9D .. + bne L9B1B ; 9B25 D0 F4 .. +L9B27: lda gameboard_dlist_data,y ; 9B27 B9 62 9B .b. + beq L9B3E ; 9B2A F0 12 .. + sta $9D ; 9B2C 85 9D .. + iny ; 9B2E C8 . + lda gameboard_dlist_data,y ; 9B2F B9 62 9B .b. +L9B32: sta $0800,x ; 9B32 9D 00 08 ... + inx ; 9B35 E8 . + dec $9D ; 9B36 C6 9D .. + bne L9B32 ; 9B38 D0 F8 .. + iny ; 9B3A C8 . + jmp L9B27 ; 9B3B 4C 27 9B L'. + +; ---------------------------------------------------------------------------- +L9B3E: lda #$41 ; 9B3E A9 41 .A + sta $0800,x ; 9B40 9D 00 08 ... + inx ; 9B43 E8 . + lda $9F ; 9B44 A5 9F .. + sta $0800,x ; 9B46 9D 00 08 ... + sta dlist_shadow_lo ; 9B49 8D AC 06 ... + inx ; 9B4C E8 . + lda #$08 ; 9B4D A9 08 .. + sta $0800,x ; 9B4F 9D 00 08 ... + sta dlist_shadow_hi ; 9B52 8D AD 06 ... + lda L9B63,y ; 9B55 B9 63 9B .c. + sta dli_vec_shadow_lo ; 9B58 8D AE 06 ... + lda L9B64,y ; 9B5B B9 64 9B .d. + sta dli_vec_shadow_hi ; 9B5E 8D AF 06 ... + rts ; 9B61 60 ` + +; ---------------------------------------------------------------------------- +; this isn't used as-is for a display list, see setup_gameboard_dlist +gameboard_dlist_data: + .byte $4D ; 9B62 4D M +L9B63: .byte $00 ; 9B63 00 . +L9B64: .byte $30,$56,$0D,$01,$8D,$01,$8D,$01 ; 9B64 30 56 0D 01 8D 01 8D 01 0V...... + .byte $06,$01,$86,$00,$72,$9B ; 9B6C 06 01 86 00 72 9B ....r. +; ---------------------------------------------------------------------------- +; changes DLI vector to point to dli_chained_2 +dli_chained_1: + pha ; 9B72 48 H + lda #$54 ; 9B73 A9 54 .T + sta WSYNC ; 9B75 8D 0A D4 ... + sta COLBK ; 9B78 8D 1A D0 ... + lda #$87 ; 9B7B A9 87 .. + sta VDSLST ; 9B7D 8D 00 02 ... + lda #$9B ; 9B80 A9 9B .. + sta VDSLST+1 ; 9B82 8D 01 02 ... + pla ; 9B85 68 h + rti ; 9B86 40 @ + +; ---------------------------------------------------------------------------- +; changes DLI vector to point to dli_chained_3 +dli_chained_2: + pha ; 9B87 48 H + lda #$00 ; 9B88 A9 00 .. + sta WSYNC ; 9B8A 8D 0A D4 ... + sta COLBK ; 9B8D 8D 1A D0 ... + lda $062A ; 9B90 AD 2A 06 .*. + sta COLPF0 ; 9B93 8D 16 D0 ... + lda #$28 ; 9B96 A9 28 .( + sta COLPF1 ; 9B98 8D 17 D0 ... + lda #$AA ; 9B9B A9 AA .. + sta COLPF2 ; 9B9D 8D 18 D0 ... + lda #$0F ; 9BA0 A9 0F .. + sta COLPF3 ; 9BA2 8D 19 D0 ... + lda #$B1 ; 9BA5 A9 B1 .. + sta VDSLST ; 9BA7 8D 00 02 ... + lda #$9B ; 9BAA A9 9B .. + sta VDSLST+1 ; 9BAC 8D 01 02 ... + pla ; 9BAF 68 h + rti ; 9BB0 40 @ + +; ---------------------------------------------------------------------------- +; changes DLI vector to point to dli_chained_1 +dli_chained_3: + pha ; 9BB1 48 H + lda #$54 ; 9BB2 A9 54 .T + sta WSYNC ; 9BB4 8D 0A D4 ... + sta COLBK ; 9BB7 8D 1A D0 ... + lda #$72 ; 9BBA A9 72 .r + sta VDSLST ; 9BBC 8D 00 02 ... + lda #$9B ; 9BBF A9 9B .. + sta VDSLST+1 ; 9BC1 8D 01 02 ... + pla ; 9BC4 68 h + rti ; 9BC5 40 @ + +; ---------------------------------------------------------------------------- + .byte $9B ; 9BC6 9B . + sta VDSLST+1 ; 9BC7 8D 01 02 ... + pla ; 9BCA 68 h + rti ; 9BCB 40 @ + +; ---------------------------------------------------------------------------- + brk ; 9BCC 00 . + brk ; 9BCD 00 . + brk ; 9BCE 00 . + brk ; 9BCF 00 . +L9BD0: lda number_of_players ; 9BD0 AD F4 06 ... + cmp #$00 ; 9BD3 C9 00 .. + beq L9BDA ; 9BD5 F0 03 .. + jmp show_get_ready_prompt ; 9BD7 4C 24 96 L$. + +; ---------------------------------------------------------------------------- +L9BDA: jmp L9675 ; 9BDA 4C 75 96 Lu. + +; ---------------------------------------------------------------------------- +L9BDD: lda #$06 ; 9BDD A9 06 .. + sta $085E ; 9BDF 8D 5E 08 .^. + sta $08DF ; 9BE2 8D DF 08 ... + jmp (work_level_sub6) ; 9BE5 6C A4 07 l.. + +; ---------------------------------------------------------------------------- +; ... +init_next_level: + lda randomizer_mode ; 9BE8 AD F3 06 ... + beq L9BFC ; 9BEB F0 0F .. +; only after beating levels 1-12 in order +randomize_level: + lda RANDOM ; 9BED AD 0A D2 ... + and #$0F ; 9BF0 29 0F ). + cmp #$0C ; 9BF2 C9 0C .. + bcs randomize_level ; 9BF4 B0 F7 .. + sta level ; 9BF6 8D F6 06 ... + dec level ; 9BF9 CE F6 06 ... +L9BFC: jmp enter_level ; 9BFC 4C BA 96 L.. + +; ---------------------------------------------------------------------------- + brk ; 9BFF 00 . +; only use of keyboard is to enter player speed before starting game +keyboard_isr: + txa ; 9C00 8A . + pha ; 9C01 48 H + ldx #$08 ; 9C02 A2 08 .. + lda KBCODE ; 9C04 AD 09 D2 ... +check_keycode: + cmp keycode_table_minus_one,x ; 9C07 DD 18 9C ... + beq store_speed_value ; 9C0A F0 07 .. + dex ; 9C0C CA . + bne check_keycode ; 9C0D D0 F8 .. +keyboard_isr_exit: + pla ; 9C0F 68 h + tax ; 9C10 AA . + pla ; 9C11 68 h + rti ; 9C12 40 @ + +; ---------------------------------------------------------------------------- +store_speed_value: + stx speed_value ; 9C13 8E F9 06 ... +keycode_table_minus_one:= * + 2 + jmp keyboard_isr_exit ; 9C16 4C 0F 9C L.. + +; ---------------------------------------------------------------------------- +keycode_table: + .byte $1F,$1E,$1A,$18,$1D,$1B,$33,$35 ; 9C19 1F 1E 1A 18 1D 1B 33 35 ......35 +; definitions for level graphics objects aka shapes. (girder segment, ladder, rope, etc) +level_gfx: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9C21 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9C29 00 00 00 00 00 00 00 00 ........ + .byte $00,$00 ; 9C31 00 00 .. +; 3 rows of pixels. 1st: 04 = 4 pixels wide, 00 00 = no X/Y offset, 01 01 01 01 = actual pixel data (4 color0 pixels). see level_maps.txt +sh_girder: + .byte $04,$00,$00,$01,$01,$01,$01,$04 ; 9C33 04 00 00 01 01 01 01 04 ........ + .byte $00,$01,$01,$00,$01,$00,$04,$00 ; 9C3B 00 01 01 00 01 00 04 00 ........ + .byte $02,$01,$01,$01,$01,$FF ; 9C43 02 01 01 01 01 FF ...... +sh_blank_4x4: + .byte $04,$00,$00,$00,$00,$00,$00,$04 ; 9C49 04 00 00 00 00 00 00 04 ........ + .byte $00,$01,$00,$00,$00,$00,$04,$00 ; 9C51 00 01 00 00 00 00 04 00 ........ + .byte $02,$00,$00,$00,$00,$FF ; 9C59 02 00 00 00 00 FF ...... +sh_ladder: + .byte $02,$00,$00,$02,$02,$02,$06,$00 ; 9C5F 02 00 00 02 02 02 06 00 ........ + .byte $02,$02,$02,$00,$01,$02,$02,$02 ; 9C67 02 02 02 00 01 02 02 02 ........ + .byte $06,$01,$02,$02,$08,$00,$02,$02 ; 9C6F 06 01 02 02 08 00 02 02 ........ + .byte $02,$02,$02,$02,$02,$02,$02,$02 ; 9C77 02 02 02 02 02 02 02 02 ........ + .byte $00,$03,$02,$02,$02,$06,$03,$02 ; 9C7F 00 03 02 02 02 06 03 02 ........ + .byte $02,$FF ; 9C87 02 FF .. +; dunno what this is yet +sh_9c89:.byte $02,$00,$00,$00,$00,$02,$06,$00 ; 9C89 02 00 00 00 00 02 06 00 ........ + .byte $00,$00,$02,$00,$01,$00,$00,$02 ; 9C91 00 00 02 00 01 00 00 02 ........ + .byte $06,$01,$00,$00,$08,$00,$02,$00 ; 9C99 06 01 00 00 08 00 02 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$02 ; 9CA1 00 00 00 00 00 00 00 02 ........ + .byte $00,$03,$00,$00,$02,$06,$03,$00 ; 9CA9 00 03 00 00 02 06 03 00 ........ + .byte $00,$FF ; 9CB1 00 FF .. +sh_bomb:.byte $04,$00,$00,$00,$03,$03,$00,$04 ; 9CB3 04 00 00 00 03 03 00 04 ........ + .byte $00,$01,$03,$00,$00,$03,$04,$00 ; 9CBB 00 01 03 00 00 03 04 00 ........ + .byte $02,$00,$03,$03,$00,$FF ; 9CC3 02 00 03 03 00 FF ...... +sh_up_rope: + .byte $01,$00,$00,$01,$01,$01,$01,$01 ; 9CC9 01 00 00 01 01 01 01 01 ........ + .byte $01,$00,$02,$01,$01,$01,$03,$01 ; 9CD1 01 00 02 01 01 01 03 01 ........ + .byte $FF ; 9CD9 FF . +sh_down_rope: + .byte $01,$00,$00,$02,$01,$00,$01,$02 ; 9CDA 01 00 00 02 01 00 01 02 ........ + .byte $01,$01,$02,$02,$01,$01,$03,$02 ; 9CE2 01 01 02 02 01 01 03 02 ........ + .byte $FF ; 9CEA FF . +; dunno what this is yet +sh_9ceb:.byte $02,$00,$00,$00,$00,$02,$00,$01 ; 9CEB 02 00 00 00 00 02 00 01 ........ + .byte $00,$00,$02,$00,$02,$00,$00,$02 ; 9CF3 00 00 02 00 02 00 00 02 ........ + .byte $00,$03,$00,$00,$FF ; 9CFB 00 03 00 00 FF ..... +; jumpman's animation frames and other sprites, seem to be 10 bytes per sprite +sprite_table: + .byte $18,$18,$3C,$5A,$3C,$18,$18,$18 ; 9D00 18 18 3C 5A 3C 18 18 18 ..<Z<... + .byte $18,$3C,$1C,$1A,$3C,$58,$38,$18 ; 9D08 18 3C 1C 1A 3C 58 38 18 .<..<X8. + .byte $3C,$24,$14,$14,$38,$58,$3C,$1A ; 9D10 3C 24 14 14 38 58 3C 1A <$..8X<. + .byte $1C,$18,$3C,$24,$28,$28,$99,$5A ; 9D18 1C 18 3C 24 28 28 99 5A ..<$((.Z + .byte $3C,$18,$18,$18,$3C,$24,$42,$C3 ; 9D20 3C 18 18 18 3C 24 42 C3 <...<$B. + .byte $19,$12,$3C,$58,$98,$18,$7C,$C4 ; 9D28 19 12 3C 58 98 18 7C C4 ..<X..|. + .byte $04,$06,$00,$18,$3C,$5A,$99,$18 ; 9D30 04 06 00 18 3C 5A 99 18 ....<Z.. + .byte $3C,$24,$42,$C3,$98,$48,$3C,$1A ; 9D38 3C 24 42 C3 98 48 3C 1A <$B..H<. + .byte $19,$18,$3E,$23,$20,$60,$18,$10 ; 9D40 19 18 3E 23 20 60 18 10 ..># `.. + .byte $3D,$5A,$98,$18,$3C,$24,$22,$33 ; 9D48 3D 5A 98 18 3C 24 22 33 =Z..<$"3 + .byte $18,$10,$38,$5C,$38,$18,$3C,$24 ; 9D50 18 10 38 5C 38 18 3C 24 ..8\8.<$ + .byte $44,$66,$18,$10,$3D,$5A,$98,$18 ; 9D58 44 66 18 10 3D 5A 98 18 Df..=Z.. + .byte $3C,$24,$22,$33,$18,$10,$38,$5C ; 9D60 3C 24 22 33 18 10 38 5C <$"3..8\ + .byte $38,$18,$3C,$24,$44,$66,$18,$08 ; 9D68 38 18 3C 24 44 66 18 08 8.<$Df.. + .byte $BC,$5A,$19,$18,$3C,$24,$44,$CC ; 9D70 BC 5A 19 18 3C 24 44 CC .Z..<$D. + .byte $18,$08,$1C,$3A,$1C,$18,$3C,$24 ; 9D78 18 08 1C 3A 1C 18 3C 24 ...:..<$ + .byte $22,$66,$18,$08,$BC,$5A,$19,$18 ; 9D80 22 66 18 08 BC 5A 19 18 "f...Z.. + .byte $3C,$24,$44,$CC,$18,$08,$1C,$3A ; 9D88 3C 24 44 CC 18 08 1C 3A <$D....: + .byte $1C,$18,$3C,$24,$22,$66,$0C,$19 ; 9D90 1C 18 3C 24 22 66 0C 19 ..<$"f.. + .byte $3E,$58,$58,$18,$3E,$42,$83,$00 ; 9D98 3E 58 58 18 3E 42 83 00 >XX.>B.. + .byte $30,$98,$7C,$1A,$1A,$18,$7C,$42 ; 9DA0 30 98 7C 1A 1A 18 7C 42 0.|...|B + .byte $C1,$00,$99,$5A,$3C,$18,$18,$99 ; 9DA8 C1 00 99 5A 3C 18 18 99 ...Z<... + .byte $FF,$00,$00,$00,$86,$42,$22,$FE ; 9DB0 FF 00 00 00 86 42 22 FE .....B". + .byte $FE,$22,$42,$86,$00,$00,$FF,$99 ; 9DB8 FE 22 42 86 00 00 FF 99 ."B..... + .byte $18,$18,$3C,$5A,$99,$00,$00,$00 ; 9DC0 18 18 3C 5A 99 00 00 00 ..<Z.... + .byte $61,$42,$44,$7F,$7F,$44,$42,$61 ; 9DC8 61 42 44 7F 7F 44 42 61 aBD..DBa + .byte $00,$00,$08,$22,$80,$01,$58,$18 ; 9DD0 00 00 08 22 80 01 58 18 ..."..X. + .byte $3C,$5A,$99,$FF,$10,$44,$01,$80 ; 9DD8 3C 5A 99 FF 10 44 01 80 <Z...D.. + .byte $1A,$18,$3C,$5A,$99,$FF,$00,$00 ; 9DE0 1A 18 3C 5A 99 FF 00 00 ..<Z.... + .byte $3C,$3C,$3C,$E7,$06,$C3,$60,$E3 ; 9DE8 3C 3C 3C E7 06 C3 60 E3 <<<...`. + .byte $76,$E3,$76,$CE,$67,$CE,$67,$83 ; 9DF0 76 E3 76 CE 67 CE 67 83 v.v.g.g. + .byte $C1,$00,$00,$00,$00,$00,$00,$00 ; 9DF8 C1 00 00 00 00 00 00 00 ........ +; GR.1/2 font, 512 bytes +charset:.byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9E00 00 00 00 00 00 00 00 00 ........ + .byte $00,$0C,$19,$3E,$58,$1E,$22 ; 9E08 00 0C 19 3E 58 1E 22 ...>X." +; couple of places in the code try to write here +block_char_minus_one: + .byte $43,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 9E0F 43 FF FF FF FF FF FF FF C....... + .byte $FF,$00,$66,$FF,$66,$66,$FF,$66 ; 9E17 FF 00 66 FF 66 66 FF 66 ..f.ff.f + .byte $00,$18,$3E,$60,$3C,$06,$7C,$18 ; 9E1F 00 18 3E 60 3C 06 7C 18 ..>`<.|. + .byte $00,$00,$7C,$82,$BA,$A2,$BA,$82 ; 9E27 00 00 7C 82 BA A2 BA 82 ..|..... + .byte $7C,$1C,$36,$1C,$38,$6F,$66,$3B ; 9E2F 7C 1C 36 1C 38 6F 66 3B |.6.8of; + .byte $00,$00,$30,$98,$7C,$1A,$78,$44 ; 9E37 00 00 30 98 7C 1A 78 44 ..0.|.xD + .byte $C2,$00,$0E,$1C,$18,$18,$18,$1C ; 9E3F C2 00 0E 1C 18 18 18 1C ........ + .byte $0E,$00,$70,$38,$18,$18,$18,$38 ; 9E47 0E 00 70 38 18 18 18 38 ..p8...8 + .byte $70,$00,$00,$00,$00,$00,$00,$00 ; 9E4F 70 00 00 00 00 00 00 00 p....... + .byte $7E,$00,$18,$18,$18,$7E,$18,$18 ; 9E57 7E 00 18 18 18 7E 18 18 ~....~.. + .byte $18,$00,$00,$00,$00,$00,$18,$18 ; 9E5F 18 00 00 00 00 00 18 18 ........ + .byte $30,$00,$00,$00,$00,$7E,$00,$00 ; 9E67 30 00 00 00 00 7E 00 00 0....~.. + .byte $00,$00,$00,$00,$00,$00,$00,$18 ; 9E6F 00 00 00 00 00 00 00 18 ........ + .byte $18,$00,$06,$0C,$18,$30,$60,$40 ; 9E77 18 00 06 0C 18 30 60 40 .....0`@ + .byte $00,$00,$3C,$66,$66,$66,$66,$66 ; 9E7F 00 00 3C 66 66 66 66 66 ..<fffff + .byte $3C,$00,$18,$38,$18,$18,$18,$18 ; 9E87 3C 00 18 38 18 18 18 18 <..8.... + .byte $7E,$00,$3C,$66,$06,$0C,$18,$30 ; 9E8F 7E 00 3C 66 06 0C 18 30 ~.<f...0 + .byte $7E,$00,$3C,$66,$06,$1C,$06,$66 ; 9E97 7E 00 3C 66 06 1C 06 66 ~.<f...f + .byte $3C,$00,$0C,$1C,$3C,$6C,$7E,$0C ; 9E9F 3C 00 0C 1C 3C 6C 7E 0C <...<l~. + .byte $0C,$00,$7E,$60,$60,$7C,$06,$06 ; 9EA7 0C 00 7E 60 60 7C 06 06 ..~``|.. + .byte $7C,$00,$3C,$66,$60,$7C,$66,$66 ; 9EAF 7C 00 3C 66 60 7C 66 66 |.<f`|ff + .byte $3C,$00,$7E,$06,$0C,$18,$30,$30 ; 9EB7 3C 00 7E 06 0C 18 30 30 <.~...00 + .byte $30,$00,$3C,$66,$66,$3C,$66,$66 ; 9EBF 30 00 3C 66 66 3C 66 66 0.<ff<ff + .byte $3C,$00,$3C,$66,$66,$3E,$06,$66 ; 9EC7 3C 00 3C 66 66 3E 06 66 <.<ff>.f + .byte $3C,$00,$00,$18,$18,$00,$18,$18 ; 9ECF 3C 00 00 18 18 00 18 18 <....... + .byte $00,$00,$00,$18,$18,$00,$18,$18 ; 9ED7 00 00 00 18 18 00 18 18 ........ + .byte $30,$06,$0C,$18,$30,$18,$0C,$06 ; 9EDF 30 06 0C 18 30 18 0C 06 0...0... + .byte $00,$00,$00,$00,$7E,$00,$7E,$00 ; 9EE7 00 00 00 00 7E 00 7E 00 ....~.~. + .byte $00,$00,$10,$7C,$10,$10,$10,$38 ; 9EEF 00 00 10 7C 10 10 10 38 ...|...8 + .byte $7C,$00,$3C,$66,$66,$0C,$18,$00 ; 9EF7 7C 00 3C 66 66 0C 18 00 |.<ff... + .byte $18,$00,$3C,$66,$6E,$6E,$60,$3E ; 9EFF 18 00 3C 66 6E 6E 60 3E ..<fnn`> + .byte $00,$00,$18,$3C,$66,$66,$7E,$66 ; 9F07 00 00 18 3C 66 66 7E 66 ...<ff~f + .byte $66,$00,$7C,$66,$66,$7C,$66,$66 ; 9F0F 66 00 7C 66 66 7C 66 66 f.|ff|ff + .byte $7C,$00,$3C,$66,$60,$60,$60,$66 ; 9F17 7C 00 3C 66 60 60 60 66 |.<f```f + .byte $3C,$00,$7C,$66,$66,$66,$66,$66 ; 9F1F 3C 00 7C 66 66 66 66 66 <.|fffff + .byte $7C,$00,$7E,$60,$60,$78,$60,$60 ; 9F27 7C 00 7E 60 60 78 60 60 |.~``x`` + .byte $7E,$00,$7E,$60,$60,$78,$60,$60 ; 9F2F 7E 00 7E 60 60 78 60 60 ~.~``x`` + .byte $60,$00,$3C,$66,$60,$60,$6E,$66 ; 9F37 60 00 3C 66 60 60 6E 66 `.<f``nf + .byte $3C,$00,$66,$66,$66,$7E,$66,$66 ; 9F3F 3C 00 66 66 66 7E 66 66 <.fff~ff + .byte $66,$00,$3C,$18,$18,$18,$18,$18 ; 9F47 66 00 3C 18 18 18 18 18 f.<..... + .byte $3C,$00,$06,$06,$06,$06,$66,$66 ; 9F4F 3C 00 06 06 06 06 66 66 <.....ff + .byte $3C,$00,$66,$6C,$78,$70,$78,$6C ; 9F57 3C 00 66 6C 78 70 78 6C <.flxpxl + .byte $66,$00,$60,$60,$60,$60,$60,$60 ; 9F5F 66 00 60 60 60 60 60 60 f.`````` + .byte $7E,$00,$63,$77,$7F,$6B,$63,$63 ; 9F67 7E 00 63 77 7F 6B 63 63 ~.cw.kcc + .byte $63,$00,$66,$66,$76,$7E,$6E,$66 ; 9F6F 63 00 66 66 76 7E 6E 66 c.ffv~nf + .byte $66,$00,$3C,$66,$66,$66,$66,$66 ; 9F77 66 00 3C 66 66 66 66 66 f.<fffff + .byte $3C,$00,$7C,$66,$66,$7C,$60,$60 ; 9F7F 3C 00 7C 66 66 7C 60 60 <.|ff|`` + .byte $60,$00,$3C,$66,$66,$66,$66,$6C ; 9F87 60 00 3C 66 66 66 66 6C `.<ffffl + .byte $36,$00,$7C,$66,$66,$7C,$6C,$66 ; 9F8F 36 00 7C 66 66 7C 6C 66 6.|ff|lf + .byte $66,$00,$3C,$66,$60,$3C,$06,$66 ; 9F97 66 00 3C 66 60 3C 06 66 f.<f`<.f + .byte $3C,$00,$7E,$18,$18,$18,$18,$18 ; 9F9F 3C 00 7E 18 18 18 18 18 <.~..... + .byte $18,$00,$66,$66,$66,$66,$66,$66 ; 9FA7 18 00 66 66 66 66 66 66 ..ffffff + .byte $3C,$00,$66,$66,$66,$66,$66,$3C ; 9FAF 3C 00 66 66 66 66 66 3C <.fffff< + .byte $18,$00,$63,$63,$63,$6B,$7F,$77 ; 9FB7 18 00 63 63 63 6B 7F 77 ..ccck.w + .byte $63,$00,$66,$66,$3C,$3C,$3C,$66 ; 9FBF 63 00 66 66 3C 3C 3C 66 c.ff<<<f + .byte $66,$00,$66,$66,$66,$3C,$18,$18 ; 9FC7 66 00 66 66 66 3C 18 18 f.fff<.. + .byte $18,$00,$7E,$06,$0C,$18,$30,$60 ; 9FCF 18 00 7E 06 0C 18 30 60 ..~...0` + .byte $7E,$00,$00,$00,$00,$00,$00,$00 ; 9FD7 7E 00 00 00 00 00 00 00 ~....... + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9FDF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9FE7 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; 9FEF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00 ; 9FF7 00 00 00 ... +; ---------------------------------------------------------------------------- +; main entry point, note cartstart_left and cartstart_right point to the same address +cartstart_right: + .addr cart_entry_point ; 9FFA C0 8A .. +; ---------------------------------------------------------------------------- +; 0 here means 'cartridge present' +cartpresent_right: + .byte $00 ; 9FFC 00 . +; 4 here means init & start the cart, no disk boot, non-diagnostic +cartoptions_right: + .byte $04 ; 9FFD 04 . +; ---------------------------------------------------------------------------- +; points to a CLC/RTS do-nothing routine (same as cartinit_left) +cartinit_right: + .addr cart_start_stub ; 9FFE FE 8A .. +; ---------------------------------------------------------------------------- +; 64-byte level descriptors, 12 of them (1 per level). first 2 bytes are level number in screencodes +level00_desc: + .byte $10,$11 ; A000 10 11 .. +; ---------------------------------------------------------------------------- +; a subroutine +level00_sub0: + .addr L0000 ; A002 00 00 .. +; a subroutine +level00_sub1: + .addr L0000 ; A004 00 00 .. +; a subroutine +level00_sub2: + .addr L0000 ; A006 00 00 .. +; a subroutine +level00_sub3: + .addr check_collisions_1 ; A008 73 8F s. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level00_num_bombs: + .byte $0C ; A00A 0C . +; 0 = no bullets +level00_bullet_chance: + .byte $01 ; A00B 01 . +; jumpman starting Y position +level00_y_start: + .byte $A0 ; A00C A0 . +; jumpman starting X position +level00_x_start: + .byte $7C ; A00D 7C | +; points to $0600 +level00_offs_14: + .byte $00,$06 ; A00E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level00_points_per_bomb: + .byte $64 ; A010 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level00_time_bonus: + .word $03E8 ; A011 E8 03 .. +; ---------------------------------------------------------------------------- +; always $00 +level00_offs_19: + .byte $00 ; A013 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level00_unkn_table0: + .addr L06DF ; A014 DF 06 .. +; map data +level00_map0: + .addr level00_map ; A016 00 A3 .. +; map data +level00_map1: + .addr LA366 ; A018 66 A3 f. +; map data +level00_map2: + .addr LA38B ; A01A 8B A3 .. +; unknown, pointer to a ROM table or $0000 +level00_unkn_table1: + .addr LA3A4 ; A01C A4 A3 .. +; ---------------------------------------------------------------------------- +; always $0000 +level00_offs_30: + .byte $00,$00 ; A01E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level00_sub4: + .addr L06E6 ; A020 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level00_sub5: + .addr L06E6 ; A022 E6 06 .. +; always $9740 aka game_main_loop +level00_sub6: + .addr game_main_loop ; A024 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level00_sub_eol: + .addr L06E6 ; A026 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level00_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A028 00 00 00 00 00 00 ...... +; unknown +level00_offs_46: + .byte $CA,$96,$18,$5A,$0C,$24,$4C,$74 ; A02E CA 96 18 5A 0C 24 4C 74 ...Z.$Lt + .byte $8C ; A036 8C . +; unknown, always $00 $00 $00 +level00_offs_55: + .byte $00,$00,$00 ; A037 00 00 00 ... +; unknown, not a ROM address +level00_offs_58: + .byte $1A,$7E ; A03A 1A 7E .~ +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level00_offs_60: + .byte $00,$00,$00,$00 ; A03C 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level01_desc: + .byte $10,$12 ; A040 10 12 .. +; ---------------------------------------------------------------------------- +; a subroutine +level01_sub0: + .addr LA4DD ; A042 DD A4 .. +; a subroutine +level01_sub1: + .addr LA509 ; A044 09 A5 .. +; a subroutine +level01_sub2: + .addr L0000 ; A046 00 00 .. +; a subroutine +level01_sub3: + .addr LA53D ; A048 3D A5 =. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level01_num_bombs: + .byte $10 ; A04A 10 . +; 0 = no bullets +level01_bullet_chance: + .byte $02 ; A04B 02 . +; jumpman starting Y position +level01_y_start: + .byte $20 ; A04C 20 +; jumpman starting X position +level01_x_start: + .byte $7C ; A04D 7C | +; points to $0600 +level01_offs_14: + .byte $00,$06 ; A04E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level01_points_per_bomb: + .byte $64 ; A050 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level01_time_bonus: + .word $07D0 ; A051 D0 07 .. +; ---------------------------------------------------------------------------- +; always $00 +level01_offs_19: + .byte $00 ; A053 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level01_unkn_table0: + .addr LA5C2 ; A054 C2 A5 .. +; map data +level01_map0: + .addr LA3E0 ; A056 E0 A3 .. +; map data +level01_map1: + .addr LA446 ; A058 46 A4 F. +; map data +level01_map2: + .addr LA477 ; A05A 77 A4 w. +; unknown, pointer to a ROM table or $0000 +level01_unkn_table1: + .addr L0000 ; A05C 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level01_offs_30: + .byte $00,$00 ; A05E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level01_sub4: + .addr LA498 ; A060 98 A4 .. +; $06E6 for some levels, or else a ROM subroutine +level01_sub5: + .addr L8036 ; A062 36 80 6. +; always $9740 aka game_main_loop +level01_sub6: + .addr game_main_loop ; A064 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level01_sub_eol: + .addr L06E6 ; A066 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level01_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A068 00 00 00 00 00 00 ...... +; unknown +level01_offs_46: + .byte $6A,$08,$C6,$1A,$18,$4C,$80,$00 ; A06E 6A 08 C6 1A 18 4C 80 00 j....L.. + .byte $00 ; A076 00 . +; unknown, always $00 $00 $00 +level01_offs_55: + .byte $00,$00,$00 ; A077 00 00 00 ... +; unknown, not a ROM address +level01_offs_58: + .byte $02,$94 ; A07A 02 94 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level01_offs_60: + .byte $00,$00,$00,$00 ; A07C 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level02_desc: + .byte $10,$13 ; A080 10 13 .. +; ---------------------------------------------------------------------------- +; a subroutine +level02_sub0: + .addr LA6BD ; A082 BD A6 .. +; a subroutine +level02_sub1: + .addr L0000 ; A084 00 00 .. +; a subroutine +level02_sub2: + .addr L0000 ; A086 00 00 .. +; a subroutine +level02_sub3: + .addr LA724 ; A088 24 A7 $. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level02_num_bombs: + .byte $0C ; A08A 0C . +; 0 = no bullets +level02_bullet_chance: + .byte $00 ; A08B 00 . +; jumpman starting Y position +level02_y_start: + .byte $40 ; A08C 40 @ +; jumpman starting X position +level02_x_start: + .byte $B4 ; A08D B4 . +; points to $0600 +level02_offs_14: + .byte $00,$06 ; A08E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level02_points_per_bomb: + .byte $64 ; A090 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level02_time_bonus: + .word $09C4 ; A091 C4 09 .. +; ---------------------------------------------------------------------------- +; always $00 +level02_offs_19: + .byte $00 ; A093 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level02_unkn_table0: + .addr LA66D ; A094 6D A6 m. +; map data +level02_map0: + .addr LA5F0 ; A096 F0 A5 .. +; map data +level02_map1: + .addr LA62F ; A098 2F A6 /. +; map data +level02_map2: + .addr LA654 ; A09A 54 A6 T. +; unknown, pointer to a ROM table or $0000 +level02_unkn_table1: + .addr L0000 ; A09C 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level02_offs_30: + .byte $00,$00 ; A09E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level02_sub4: + .addr L06E6 ; A0A0 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level02_sub5: + .addr LA68C ; A0A2 8C A6 .. +; always $9740 aka game_main_loop +level02_sub6: + .addr game_main_loop ; A0A4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level02_sub_eol: + .addr L06E6 ; A0A6 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level02_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A0A8 00 00 00 00 00 00 ...... +; unknown +level02_offs_46: + .byte $1A,$C6,$96,$1A,$0C,$8C,$00,$00 ; A0AE 1A C6 96 1A 0C 8C 00 00 ........ + .byte $00 ; A0B6 00 . +; unknown, always $00 $00 $00 +level02_offs_55: + .byte $00,$00,$00 ; A0B7 00 00 00 ... +; unknown, not a ROM address +level02_offs_58: + .byte $00,$00 ; A0BA 00 00 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level02_offs_60: + .byte $00,$00,$00,$00 ; A0BC 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level03_desc: + .byte $10,$14 ; A0C0 10 14 .. +; ---------------------------------------------------------------------------- +; a subroutine +level03_sub0: + .addr LA836 ; A0C2 36 A8 6. +; a subroutine +level03_sub1: + .addr L0000 ; A0C4 00 00 .. +; a subroutine +level03_sub2: + .addr L0000 ; A0C6 00 00 .. +; a subroutine +level03_sub3: + .addr LA827 ; A0C8 27 A8 '. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level03_num_bombs: + .byte $10 ; A0CA 10 . +; 0 = no bullets +level03_bullet_chance: + .byte $00 ; A0CB 00 . +; jumpman starting Y position +level03_y_start: + .byte $C0 ; A0CC C0 . +; jumpman starting X position +level03_x_start: + .byte $7C ; A0CD 7C | +; points to $0600 +level03_offs_14: + .byte $00,$06 ; A0CE 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level03_points_per_bomb: + .byte $64 ; A0D0 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level03_time_bonus: + .word $07D0 ; A0D1 D0 07 .. +; ---------------------------------------------------------------------------- +; always $00 +level03_offs_19: + .byte $00 ; A0D3 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level03_unkn_table0: + .addr L06DF ; A0D4 DF 06 .. +; map data +level03_map0: + .addr LA790 ; A0D6 90 A7 .. +; map data +level03_map1: + .addr LA7D5 ; A0D8 D5 A7 .. +; map data +level03_map2: + .addr LA806 ; A0DA 06 A8 .. +; unknown, pointer to a ROM table or $0000 +level03_unkn_table1: + .addr L0000 ; A0DC 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level03_offs_30: + .byte $00,$00 ; A0DE 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level03_sub4: + .addr L06E6 ; A0E0 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level03_sub5: + .addr L8036 ; A0E2 36 80 6. +; always $9740 aka game_main_loop +level03_sub6: + .addr game_main_loop ; A0E4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level03_sub_eol: + .addr L06E6 ; A0E6 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level03_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A0E8 00 00 00 00 00 00 ...... +; unknown +level03_offs_46: + .byte $CA,$96,$18,$5A,$4C,$18,$2C,$80 ; A0EE CA 96 18 5A 4C 18 2C 80 ...ZL.,. + .byte $6C ; A0F6 6C l +; unknown, always $00 $00 $00 +level03_offs_55: + .byte $00,$00,$00 ; A0F7 00 00 00 ... +; unknown, not a ROM address +level03_offs_58: + .byte $00,$00 ; A0FA 00 00 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level03_offs_60: + .byte $00,$00,$00,$00 ; A0FC 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level04_desc: + .byte $10,$15 ; A100 10 15 .. +; ---------------------------------------------------------------------------- +; a subroutine +level04_sub0: + .addr L0000 ; A102 00 00 .. +; a subroutine +level04_sub1: + .addr L0000 ; A104 00 00 .. +; a subroutine +level04_sub2: + .addr L0000 ; A106 00 00 .. +; a subroutine +level04_sub3: + .addr check_collisions_1 ; A108 73 8F s. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level04_num_bombs: + .byte $0E ; A10A 0E . +; 0 = no bullets +level04_bullet_chance: + .byte $02 ; A10B 02 . +; jumpman starting Y position +level04_y_start: + .byte $C0 ; A10C C0 . +; jumpman starting X position +level04_x_start: + .byte $34 ; A10D 34 4 +; points to $0600 +level04_offs_14: + .byte $00,$06 ; A10E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level04_points_per_bomb: + .byte $64 ; A110 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level04_time_bonus: + .word $07D0 ; A111 D0 07 .. +; ---------------------------------------------------------------------------- +; always $00 +level04_offs_19: + .byte $00 ; A113 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level04_unkn_table0: + .addr L06DF ; A114 DF 06 .. +; map data +level04_map0: + .addr LAAD0 ; A116 D0 AA .. +; map data +level04_map1: + .addr LAB42 ; A118 42 AB B. +; map data +level04_map2: + .addr LAB6D ; A11A 6D AB m. +; unknown, pointer to a ROM table or $0000 +level04_unkn_table1: + .addr LAB8A ; A11C 8A AB .. +; ---------------------------------------------------------------------------- +; always $0000 +level04_offs_30: + .byte $00,$00 ; A11E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level04_sub4: + .addr L06E6 ; A120 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level04_sub5: + .addr L06E6 ; A122 E6 06 .. +; always $9740 aka game_main_loop +level04_sub6: + .addr game_main_loop ; A124 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level04_sub_eol: + .addr L06E6 ; A126 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level04_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A128 00 00 00 00 00 00 ...... +; unknown +level04_offs_46: + .byte $6A,$08,$C6,$1A,$0C,$22,$84,$8E ; A12E 6A 08 C6 1A 0C 22 84 8E j....".. + .byte $00 ; A136 00 . +; unknown, always $00 $00 $00 +level04_offs_55: + .byte $00,$00,$00 ; A137 00 00 00 ... +; unknown, not a ROM address +level04_offs_58: + .byte $96,$00 ; A13A 96 00 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level04_offs_60: + .byte $00,$00,$00,$00 ; A13C 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level05_desc: + .byte $10,$16 ; A140 10 16 .. +; ---------------------------------------------------------------------------- +; a subroutine +level05_sub0: + .addr LAA3A ; A142 3A AA :. +; a subroutine +level05_sub1: + .addr LAA35 ; A144 35 AA 5. +; a subroutine +level05_sub2: + .addr LAA55 ; A146 55 AA U. +; a subroutine +level05_sub3: + .addr LAABC ; A148 BC AA .. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level05_num_bombs: + .byte $10 ; A14A 10 . +; 0 = no bullets +level05_bullet_chance: + .byte $00 ; A14B 00 . +; jumpman starting Y position +level05_y_start: + .byte $80 ; A14C 80 . +; jumpman starting X position +level05_x_start: + .byte $34 ; A14D 34 4 +; points to $0600 +level05_offs_14: + .byte $00,$06 ; A14E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level05_points_per_bomb: + .byte $64 ; A150 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level05_time_bonus: + .word $05DC ; A151 DC 05 .. +; ---------------------------------------------------------------------------- +; always $00 +level05_offs_19: + .byte $00 ; A153 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level05_unkn_table0: + .addr L06DF ; A154 DF 06 .. +; map data +level05_map0: + .addr LA920 ; A156 20 A9 . +; map data +level05_map1: + .addr LA974 ; A158 74 A9 t. +; map data +level05_map2: + .addr LA9A5 ; A15A A5 A9 .. +; unknown, pointer to a ROM table or $0000 +level05_unkn_table1: + .addr L0000 ; A15C 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level05_offs_30: + .byte $00,$00 ; A15E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level05_sub4: + .addr LAA73 ; A160 73 AA s. +; $06E6 for some levels, or else a ROM subroutine +level05_sub5: + .addr LA9C6 ; A162 C6 A9 .. +; always $9740 aka game_main_loop +level05_sub6: + .addr game_main_loop ; A164 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level05_sub_eol: + .addr L06E6 ; A166 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level05_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A168 00 00 00 00 00 00 ...... +; unknown +level05_offs_46: + .byte $56,$C6,$96,$28,$04,$30,$68,$94 ; A16E 56 C6 96 28 04 30 68 94 V..(.0h. + .byte $00 ; A176 00 . +; unknown, always $00 $00 $00 +level05_offs_55: + .byte $00,$00,$00 ; A177 00 00 00 ... +; unknown, not a ROM address +level05_offs_58: + .byte $4C,$FF ; A17A 4C FF L. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level05_offs_60: + .byte $FF,$FF,$FF,$FF ; A17C FF FF FF FF .... +; first 2 bytes are level number in screencodes +level06_desc: + .byte $10,$17 ; A180 10 17 .. +; ---------------------------------------------------------------------------- +; a subroutine +level06_sub0: + .addr LAD68 ; A182 68 AD h. +; a subroutine +level06_sub1: + .addr L0000 ; A184 00 00 .. +; a subroutine +level06_sub2: + .addr L0000 ; A186 00 00 .. +; a subroutine +level06_sub3: + .addr check_collisions_1 ; A188 73 8F s. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level06_num_bombs: + .byte $0E ; A18A 0E . +; 0 = no bullets +level06_bullet_chance: + .byte $03 ; A18B 03 . +; jumpman starting Y position +level06_y_start: + .byte $C0 ; A18C C0 . +; jumpman starting X position +level06_x_start: + .byte $7C ; A18D 7C | +; points to $0600 +level06_offs_14: + .byte $00,$06 ; A18E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level06_points_per_bomb: + .byte $64 ; A190 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level06_time_bonus: + .word $05DC ; A191 DC 05 .. +; ---------------------------------------------------------------------------- +; always $00 +level06_offs_19: + .byte $00 ; A193 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level06_unkn_table0: + .addr L06DF ; A194 DF 06 .. +; map data +level06_map0: + .addr LAC60 ; A196 60 AC `. +; map data +level06_map1: + .addr LACBA ; A198 BA AC .. +; map data +level06_map2: + .addr LACE5 ; A19A E5 AC .. +; unknown, pointer to a ROM table or $0000 +level06_unkn_table1: + .addr LAD02 ; A19C 02 AD .. +; ---------------------------------------------------------------------------- +; always $0000 +level06_offs_30: + .byte $00,$00 ; A19E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level06_sub4: + .addr L06E6 ; A1A0 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level06_sub5: + .addr L8036 ; A1A2 36 80 6. +; always $9740 aka game_main_loop +level06_sub6: + .addr game_main_loop ; A1A4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level06_sub_eol: + .addr L06E6 ; A1A6 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level06_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A1A8 00 00 00 00 00 00 ...... +; unknown +level06_offs_46: + .byte $CA,$96,$18,$5A,$0C,$4C,$8C,$00 ; A1AE CA 96 18 5A 0C 4C 8C 00 ...Z.L.. + .byte $00 ; A1B6 00 . +; unknown, always $00 $00 $00 +level06_offs_55: + .byte $00,$00,$00 ; A1B7 00 00 00 ... +; unknown, not a ROM address +level06_offs_58: + .byte $1C,$7E ; A1BA 1C 7E .~ +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level06_offs_60: + .byte $00,$00,$00,$00 ; A1BC 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level07_desc: + .byte $10,$18 ; A1C0 10 18 .. +; ---------------------------------------------------------------------------- +; a subroutine +level07_sub0: + .addr LAF1C ; A1C2 1C AF .. +; a subroutine +level07_sub1: + .addr L0000 ; A1C4 00 00 .. +; a subroutine +level07_sub2: + .addr L0000 ; A1C6 00 00 .. +; a subroutine +level07_sub3: + .addr check_collisions_1 ; A1C8 73 8F s. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level07_num_bombs: + .byte $0C ; A1CA 0C . +; 0 = no bullets +level07_bullet_chance: + .byte $02 ; A1CB 02 . +; jumpman starting Y position +level07_y_start: + .byte $20 ; A1CC 20 +; jumpman starting X position +level07_x_start: + .byte $7C ; A1CD 7C | +; points to $0600 +level07_offs_14: + .byte $00,$06 ; A1CE 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level07_points_per_bomb: + .byte $64 ; A1D0 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level07_time_bonus: + .word $05DC ; A1D1 DC 05 .. +; ---------------------------------------------------------------------------- +; always $00 +level07_offs_19: + .byte $00 ; A1D3 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level07_unkn_table0: + .addr LAE8A ; A1D4 8A AE .. +; map data +level07_map0: + .addr LADE0 ; A1D6 E0 AD .. +; map data +level07_map1: + .addr LAE4C ; A1D8 4C AE L. +; map data +level07_map2: + .addr LAE71 ; A1DA 71 AE q. +; unknown, pointer to a ROM table or $0000 +level07_unkn_table1: + .addr L0000 ; A1DC 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level07_offs_30: + .byte $00,$00 ; A1DE 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level07_sub4: + .addr LAF23 ; A1E0 23 AF #. +; $06E6 for some levels, or else a ROM subroutine +level07_sub5: + .addr LAE9B ; A1E2 9B AE .. +; always $9740 aka game_main_loop +level07_sub6: + .addr game_main_loop ; A1E4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level07_sub_eol: + .addr LAF58 ; A1E6 58 AF X. +; ---------------------------------------------------------------------------- +; all zeroes +level07_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A1E8 00 00 00 00 00 00 ...... +; unknown +level07_offs_46: + .byte $6A,$08,$C6,$1A,$0C,$30,$68,$8C ; A1EE 6A 08 C6 1A 0C 30 68 8C j....0h. + .byte $00 ; A1F6 00 . +; unknown, always $00 $00 $00 +level07_offs_55: + .byte $00,$00,$00 ; A1F7 00 00 00 ... +; unknown, not a ROM address +level07_offs_58: + .byte $40,$56 ; A1FA 40 56 @V +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level07_offs_60: + .byte $00,$00,$00,$00 ; A1FC 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level08_desc: + .byte $10,$19 ; A200 10 19 .. +; ---------------------------------------------------------------------------- +; a subroutine +level08_sub0: + .addr LB140 ; A202 40 B1 @. +; a subroutine +level08_sub1: + .addr L0000 ; A204 00 00 .. +; a subroutine +level08_sub2: + .addr L0000 ; A206 00 00 .. +; a subroutine +level08_sub3: + .addr L0000 ; A208 00 00 .. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level08_num_bombs: + .byte $08 ; A20A 08 . +; 0 = no bullets +level08_bullet_chance: + .byte $00 ; A20B 00 . +; jumpman starting Y position +level08_y_start: + .byte $C0 ; A20C C0 . +; jumpman starting X position +level08_x_start: + .byte $9E ; A20D 9E . +; points to $0600 +level08_offs_14: + .byte $00,$06 ; A20E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level08_points_per_bomb: + .byte $64 ; A210 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level08_time_bonus: + .word $07D0 ; A211 D0 07 .. +; ---------------------------------------------------------------------------- +; always $00 +level08_offs_19: + .byte $00 ; A213 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level08_unkn_table0: + .addr L06DF ; A214 DF 06 .. +; map data +level08_map0: + .addr LB0A2 ; A216 A2 B0 .. +; map data +level08_map1: + .addr LB072 ; A218 72 B0 r. +; map data +level08_map2: + .addr LB0A3 ; A21A A3 B0 .. +; unknown, pointer to a ROM table or $0000 +level08_unkn_table1: + .addr L0000 ; A21C 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level08_offs_30: + .byte $00,$00 ; A21E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level08_sub4: + .addr LB121 ; A220 21 B1 !. +; $06E6 for some levels, or else a ROM subroutine +level08_sub5: + .addr LB0C4 ; A222 C4 B0 .. +; always $9740 aka game_main_loop +level08_sub6: + .addr game_main_loop ; A224 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level08_sub_eol: + .addr L06E6 ; A226 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level08_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A228 00 00 00 00 00 00 ...... +; unknown +level08_offs_46: + .byte $1A,$C6,$96,$28,$0C,$3C,$00,$00 ; A22E 1A C6 96 28 0C 3C 00 00 ...(.<.. + .byte $8C ; A236 8C . +; unknown, always $00 $00 $00 +level08_offs_55: + .byte $00,$00,$00 ; A237 00 00 00 ... +; unknown, not a ROM address +level08_offs_58: + .byte $80,$00 ; A23A 80 00 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level08_offs_60: + .byte $00,$00,$00,$00 ; A23C 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level09_desc: + .byte $11,$10 ; A240 11 10 .. +; ---------------------------------------------------------------------------- +; a subroutine +level09_sub0: + .addr LB27E ; A242 7E B2 ~. +; a subroutine +level09_sub1: + .addr L0000 ; A244 00 00 .. +; a subroutine +level09_sub2: + .addr L0000 ; A246 00 00 .. +; a subroutine +level09_sub3: + .addr LB2E0 ; A248 E0 B2 .. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level09_num_bombs: + .byte $0C ; A24A 0C . +; 0 = no bullets +level09_bullet_chance: + .byte $02 ; A24B 02 . +; jumpman starting Y position +level09_y_start: + .byte $C0 ; A24C C0 . +; jumpman starting X position +level09_x_start: + .byte $3C ; A24D 3C < +; points to $0600 +level09_offs_14: + .byte $00,$06 ; A24E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level09_points_per_bomb: + .byte $64 ; A250 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level09_time_bonus: + .word $05DC ; A251 DC 05 .. +; ---------------------------------------------------------------------------- +; always $00 +level09_offs_19: + .byte $00 ; A253 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level09_unkn_table0: + .addr LB275 ; A254 75 B2 u. +; map data +level09_map0: + .addr LB1E0 ; A256 E0 B1 .. +; map data +level09_map1: + .addr LB237 ; A258 37 B2 7. +; map data +level09_map2: + .addr LB25C ; A25A 5C B2 \. +; unknown, pointer to a ROM table or $0000 +level09_unkn_table1: + .addr L0000 ; A25C 00 00 .. +; ---------------------------------------------------------------------------- +; always $0000 +level09_offs_30: + .byte $00,$00 ; A25E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level09_sub4: + .addr LB2FD ; A260 FD B2 .. +; $06E6 for some levels, or else a ROM subroutine +level09_sub5: + .addr L8036 ; A262 36 80 6. +; always $9740 aka game_main_loop +level09_sub6: + .addr game_main_loop ; A264 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level09_sub_eol: + .addr L06E6 ; A266 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level09_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A268 00 00 00 00 00 00 ...... +; unknown +level09_offs_46: + .byte $CA,$96,$18,$5A,$0C,$40,$8C,$00 ; A26E CA 96 18 5A 0C 40 8C 00 ...Z.@.. + .byte $00 ; A276 00 . +; unknown, always $00 $00 $00 +level09_offs_55: + .byte $00,$00,$00 ; A277 00 00 00 ... +; unknown, not a ROM address +level09_offs_58: + .byte $62,$00 ; A27A 62 00 b. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level09_offs_60: + .byte $00,$00,$00,$00 ; A27C 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level10_desc: + .byte $11,$11 ; A280 11 11 .. +; ---------------------------------------------------------------------------- +; a subroutine +level10_sub0: + .addr LB457 ; A282 57 B4 W. +; a subroutine +level10_sub1: + .addr LB581 ; A284 81 B5 .. +; a subroutine +level10_sub2: + .addr L0000 ; A286 00 00 .. +; a subroutine +level10_sub3: + .addr LB57C ; A288 7C B5 |. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level10_num_bombs: + .byte $0F ; A28A 0F . +; 0 = no bullets +level10_bullet_chance: + .byte $00 ; A28B 00 . +; jumpman starting Y position +level10_y_start: + .byte $B6 ; A28C B6 . +; jumpman starting X position +level10_x_start: + .byte $C4 ; A28D C4 . +; points to $0600 +level10_offs_14: + .byte $00,$06 ; A28E 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level10_points_per_bomb: + .byte $64 ; A290 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level10_time_bonus: + .word $03E8 ; A291 E8 03 .. +; ---------------------------------------------------------------------------- +; always $00 +level10_offs_19: + .byte $00 ; A293 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level10_unkn_table0: + .addr data_table_b50b ; A294 0B B5 .. +; map data +level10_map0: + .addr LB320 ; A296 20 B3 . +; map data +level10_map1: + .addr LB38F ; A298 8F B3 .. +; map data +level10_map2: + .addr LB3BD ; A29A BD B3 .. +; unknown, pointer to a ROM table or $0000 +level10_unkn_table1: + .addr LB3DC ; A29C DC B3 .. +; ---------------------------------------------------------------------------- +; always $0000 +level10_offs_30: + .byte $00,$00 ; A29E 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level10_sub4: + .addr LB44C ; A2A0 4C B4 L. +; $06E6 for some levels, or else a ROM subroutine +level10_sub5: + .addr L8036 ; A2A2 36 80 6. +; always $9740 aka game_main_loop +level10_sub6: + .addr game_main_loop ; A2A4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level10_sub_eol: + .addr L06E6 ; A2A6 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level10_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A2A8 00 00 00 00 00 00 ...... +; unknown +level10_offs_46: + .byte $6A,$08,$C6,$1A,$0C,$30,$54,$8C ; A2AE 6A 08 C6 1A 0C 30 54 8C j....0T. + .byte $00 ; A2B6 00 . +; unknown, always $00 $00 $00 +level10_offs_55: + .byte $00,$00,$00 ; A2B7 00 00 00 ... +; unknown, not a ROM address +level10_offs_58: + .byte $00,$66 ; A2BA 00 66 .f +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level10_offs_60: + .byte $00,$00,$00,$00 ; A2BC 00 00 00 00 .... +; first 2 bytes are level number in screencodes +level11_desc: + .byte $11,$12 ; A2C0 11 12 .. +; ---------------------------------------------------------------------------- +; a subroutine +level11_sub0: + .addr LB691 ; A2C2 91 B6 .. +; a subroutine +level11_sub1: + .addr LB69B ; A2C4 9B B6 .. +; a subroutine +level11_sub2: + .addr LB709 ; A2C6 09 B7 .. +; a subroutine +level11_sub3: + .addr check_collisions_1 ; A2C8 73 8F s. +; ---------------------------------------------------------------------------- +; number of bombs to pick up on this level +level11_num_bombs: + .byte $0E ; A2CA 0E . +; 0 = no bullets +level11_bullet_chance: + .byte $00 ; A2CB 00 . +; jumpman starting Y position +level11_y_start: + .byte $C0 ; A2CC C0 . +; jumpman starting X position +level11_x_start: + .byte $7C ; A2CD 7C | +; points to $0600 +level11_offs_14: + .byte $00,$06 ; A2CE 00 06 .. +; points awarded per bomb pickup (always $64 aka 100) +level11_points_per_bomb: + .byte $64 ; A2D0 64 d +; ---------------------------------------------------------------------------- +; amount of time bonus at start of level +level11_time_bonus: + .word $09C4 ; A2D1 C4 09 .. +; ---------------------------------------------------------------------------- +; always $00 +level11_offs_19: + .byte $00 ; A2D3 00 . +; ---------------------------------------------------------------------------- +; pointer to ROM table or $06xx +level11_unkn_table0: + .addr LB658 ; A2D4 58 B6 X. +; map data +level11_map0: + .addr LB590 ; A2D6 90 B5 .. +; map data +level11_map1: + .addr LB5D2 ; A2D8 D2 B5 .. +; map data +level11_map2: + .addr LB5FD ; A2DA FD B5 .. +; unknown, pointer to a ROM table or $0000 +level11_unkn_table1: + .addr LB61A ; A2DC 1A B6 .. +; ---------------------------------------------------------------------------- +; always $0000 +level11_offs_30: + .byte $00,$00 ; A2DE 00 00 .. +; ---------------------------------------------------------------------------- +; $06E6 for most levels, or else a ROM subroutine +level11_sub4: + .addr L06E6 ; A2E0 E6 06 .. +; $06E6 for some levels, or else a ROM subroutine +level11_sub5: + .addr L8036 ; A2E2 36 80 6. +; always $9740 aka game_main_loop +level11_sub6: + .addr game_main_loop ; A2E4 40 97 @. +; called at end of level (all bombs picked up). $06E6 for all but level07 +level11_sub_eol: + .addr L06E6 ; A2E6 E6 06 .. +; ---------------------------------------------------------------------------- +; all zeroes +level11_offs_40: + .byte $00,$00,$00,$00,$00,$00 ; A2E8 00 00 00 00 00 00 ...... +; unknown +level11_offs_46: + .byte $08,$C6,$96,$28,$0C,$2A,$4C,$6A ; A2EE 08 C6 96 28 0C 2A 4C 6A ...(.*Lj + .byte $8C ; A2F6 8C . +; unknown, always $00 $00 $00 +level11_offs_55: + .byte $00,$00,$00 ; A2F7 00 00 00 ... +; unknown, not a ROM address +level11_offs_58: + .byte $00,$00 ; A2FA 00 00 .. +; unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00 +level11_offs_60: + .byte $00,$00,$00,$00 ; A2FC 00 00 00 00 .... +; level map data starts here +level00_map: + .byte $FE,$33,$9C,$FD,$04,$00,$44,$05 ; A300 FE 33 9C FD 04 00 44 05 .3....D. + .byte $06,$04,$15,$0A,$74,$15,$0A,$24 ; A308 06 04 15 0A 74 15 0A 24 ....t..$ + .byte $22,$02,$74,$22,$02,$24,$25,$16 ; A310 22 02 74 22 02 24 25 16 ".t".$%. + .byte $04,$45,$04,$44,$45,$06,$8C,$45 ; A318 04 45 04 44 45 06 8C 45 .E.DE..E + .byte $04,$04,$55,$08,$34,$55,$0E,$7C ; A320 04 04 55 08 34 55 0E 7C ..U.4U.| + .byte $55,$08,$FD,$04,$FF,$34,$09,$04 ; A328 55 08 FD 04 FF 34 09 04 U....4.. + .byte $5C,$44,$0A,$FD,$04,$01,$5C,$06 ; A330 5C 44 0A FD 04 01 5C 06 \D....\. + .byte $04,$1C,$3B,$0A,$FE,$5F,$9C,$FD ; A338 04 1C 3B 0A FE 5F 9C FD ..;.._.. + .byte $00,$04,$0C,$41,$05,$8C,$41,$05 ; A340 00 04 0C 41 05 8C 41 05 ...A..A. + .byte $24,$01,$05,$74,$01,$05,$4C,$01 ; A348 24 01 05 74 01 05 4C 01 $..t..L. + .byte $15,$FE,$C9,$9C,$06,$18,$0A,$99 ; A350 15 FE C9 9C 06 18 0A 99 ........ + .byte $18,$0A,$FE,$DA,$9C,$1D,$38,$06 ; A358 18 0A FE DA 9C 1D 38 06 ......8. + .byte $81,$38,$06,$FE,$B3,$9C ; A360 81 38 06 FE B3 9C .8.... +LA366: .byte $04,$12,$01,$38,$02,$01,$64,$02 ; A366 04 12 01 38 02 01 64 02 ...8..d. + .byte $01,$98,$12,$01,$44,$22,$01,$58 ; A36E 01 98 12 01 44 22 01 58 ....D".X + .byte $22,$01,$04,$42,$01,$98,$42,$01 ; A376 22 01 04 42 01 98 42 01 "..B..B. + .byte $04,$52,$01,$38,$52,$01,$64,$52 ; A37E 04 52 01 38 52 01 64 52 .R.8R.dR + .byte $01,$98,$52,$01,$FF ; A386 01 98 52 01 FF ..R.. +LA38B: .byte $24,$00,$62,$10,$82,$20,$C4,$00 ; A38B 24 00 62 10 82 20 C4 00 $.b.. .. + .byte $66,$30,$86,$40,$2A,$00,$CA,$00 ; A393 66 30 86 40 2A 00 CA 00 f0.@*... + .byte $2C,$00,$6C,$00,$8C,$00,$CC,$00 ; A39B 2C 00 6C 00 8C 00 CC 00 ,.l..... + .byte $FF ; A3A3 FF . +LA3A4: .byte $00,$00,$AE,$A3,$B8,$A3,$C2,$A3 ; A3A4 00 00 AE A3 B8 A3 C2 A3 ........ + .byte $CC,$A3,$FE,$49,$9C,$FD,$04,$01 ; A3AC CC A3 FE 49 9C FD 04 01 ...I.... + .byte $64,$08,$02,$FF,$FE,$49,$9C,$FD ; A3B4 64 08 02 FF FE 49 9C FD d....I.. + .byte $04,$FF,$34,$09,$02,$FF,$FE,$49 ; A3BC 04 FF 34 09 02 FF FE 49 ..4....I + .byte $9C,$FD,$04,$00,$2C,$25,$05,$FF ; A3C4 9C FD 04 00 2C 25 05 FF ....,%.. + .byte $FE,$49,$9C,$FD,$04,$00,$60,$25 ; A3CC FE 49 9C FD 04 00 60 25 .I....`% + .byte $05,$FF,$00,$00,$00,$00,$00,$00 ; A3D4 05 FF 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00 ; A3DC 00 00 00 00 .... +LA3E0: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; A3E0 FE 33 9C FD 04 00 04 05 .3...... + .byte $08,$34,$05,$0E,$7C,$05,$08,$14 ; A3E8 08 34 05 0E 7C 05 08 14 .4..|... + .byte $15,$04,$34,$15,$04,$5C,$15,$04 ; A3F0 15 04 34 15 04 5C 15 04 ..4..\.. + .byte $7C,$15,$04,$04,$25,$10,$5C,$25 ; A3F8 7C 15 04 04 25 10 5C 25 |...%.\% + .byte $10,$20,$3C,$07,$64,$3C,$07,$04 ; A400 10 20 3C 07 64 3C 07 04 . <.d<.. + .byte $55,$09,$38,$55,$0C,$78,$55,$09 ; A408 55 09 38 55 0C 78 55 09 U.8U.xU. + .byte $FD,$04,$FF,$04,$19,$04,$80,$3B ; A410 FD 04 FF 04 19 04 80 3B .......; + .byte $07,$FD,$04,$01,$8C,$16,$04,$04 ; A418 07 FD 04 01 8C 16 04 04 ........ + .byte $35,$07,$FE,$5F,$9C,$FD,$00,$04 ; A420 35 07 FE 5F 9C FD 00 04 5.._.... + .byte $18,$01,$05,$4C,$01,$15,$80,$01 ; A428 18 01 05 4C 01 15 80 01 ...L.... + .byte $05,$FE,$C9,$9C,$19,$3C,$05,$85 ; A430 05 FE C9 9C 19 3C 05 85 .....<.. + .byte $3C,$05,$FE,$DA,$9C,$05,$30,$08 ; A438 3C 05 FE DA 9C 05 30 08 <.....0. + .byte $99,$30,$08,$FE,$B3,$9C ; A440 99 30 08 FE B3 9C .0.... +LA446: .byte $04,$02,$01,$38,$02,$01,$64,$02 ; A446 04 02 01 38 02 01 64 02 ...8..d. + .byte $01,$98,$02,$01,$04,$12,$01,$38 ; A44E 01 98 02 01 04 12 01 38 .......8 + .byte $12,$01,$64,$12,$01,$98,$12,$01 ; A456 12 01 64 12 01 98 12 01 ..d..... + .byte $20,$22,$01,$7C,$22,$01,$38,$32 ; A45E 20 22 01 7C 22 01 38 32 ".|".82 + .byte $01,$64,$32,$01,$04,$52,$01,$38 ; A466 01 64 32 01 04 52 01 38 .d2..R.8 + .byte $52,$01,$64,$52,$01,$98,$52,$01 ; A46E 52 01 64 52 01 98 52 01 R.dR..R. + .byte $FF ; A476 FF . +LA477: .byte $22,$00,$62,$00,$82,$00,$C2,$00 ; A477 22 00 62 00 82 00 C2 00 ".b..... + .byte $24,$00,$64,$00,$84,$00,$C4,$00 ; A47F 24 00 64 00 84 00 C4 00 $.d..... + .byte $46,$00,$A6,$00,$68,$00,$88,$00 ; A487 46 00 A6 00 68 00 88 00 F...h... + .byte $2C,$00,$6C,$00,$8C,$00,$CC,$00 ; A48F 2C 00 6C 00 8C 00 CC 00 ,.l..... + .byte $FF ; A497 FF . +; ---------------------------------------------------------------------------- +LA498: ldy $B2 ; A498 A4 B2 .. + lda data_table_a542,y ; A49A B9 42 A5 .B. + clc ; A49D 18 . + adc #$30 ; A49E 69 30 i0 + sta $0680 ; A4A0 8D 80 06 ... + lda LA543,y ; A4A3 B9 43 A5 .C. + asl a ; A4A6 0A . + adc #$20 ; A4A7 69 20 i + sta $0685 ; A4A9 8D 85 06 ... + lda LA582,y ; A4AC B9 82 A5 ... + sta $068A ; A4AF 8D 8A 06 ... + lda LA583,y ; A4B2 B9 83 A5 ... + sta PCOLR2 ; A4B5 8D C2 02 ... + lda LA562,y ; A4B8 B9 62 A5 .b. + clc ; A4BB 18 . + adc #$30 ; A4BC 69 30 i0 + sta $0681 ; A4BE 8D 81 06 ... + lda LA563,y ; A4C1 B9 63 A5 .c. + asl a ; A4C4 0A . + adc #$20 ; A4C5 69 20 i + sta $0686 ; A4C7 8D 86 06 ... + lda LA5A2,y ; A4CA B9 A2 A5 ... + sta $068B ; A4CD 8D 8B 06 ... + lda LA5A3,y ; A4D0 B9 A3 A5 ... + sta PCOLR3 ; A4D3 8D C3 02 ... + sta $066C ; A4D6 8D 6C 06 .l. + sta $066D ; A4D9 8D 6D 06 .m. + rts ; A4DC 60 ` + +; ---------------------------------------------------------------------------- +LA4DD: lda $0623 ; A4DD AD 23 06 .#. + bne LA4FF ; A4E0 D0 1D .. + lda $0621 ; A4E2 AD 21 06 .!. + bne LA4E8 ; A4E5 D0 01 .. + rts ; A4E7 60 ` + +; ---------------------------------------------------------------------------- +LA4E8: ldx #$01 ; A4E8 A2 01 .. + lda collision_save+14 ; A4EA AD BE 06 ... + and #$03 ; A4ED 29 03 ). + bne LA505 ; A4EF D0 14 .. + inx ; A4F1 E8 . + lda collision_save+15 ; A4F2 AD BF 06 ... + and #$03 ; A4F5 29 03 ). + bne LA505 ; A4F7 D0 0C .. + lda initial_speed ; A4F9 AD 25 06 .%. + sta player_speed ; A4FC 8D 24 06 .$. +LA4FF: lda #$00 ; A4FF A9 00 .. + sta $0770 ; A501 8D 70 07 .p. + rts ; A504 60 ` + +; ---------------------------------------------------------------------------- +LA505: stx $0770 ; A505 8E 70 07 .p. + rts ; A508 60 ` + +; ---------------------------------------------------------------------------- +LA509: ldx $0770 ; A509 AE 70 07 .p. + bne LA50F ; A50C D0 01 .. + rts ; A50E 60 ` + +; ---------------------------------------------------------------------------- +LA50F: lda RANDOM ; A50F AD 0A D2 ... + sta COLPM1,x ; A512 9D 13 D0 ... + sta COLPM0 ; A515 8D 12 D0 ... + lda #$08 ; A518 A9 08 .. + sta player_speed ; A51A 8D 24 06 .$. + lda #$2D ; A51D A9 2D .- + sta sfx_slot_tempo ; A51F 8D 3E 06 .>. + lda #$A5 ; A522 A9 A5 .. + sta sfx_slot_timer ; A524 8D 3F 06 .?. + lda #$01 ; A527 A9 01 .. + jsr L8003 ; A529 20 03 80 .. + rts ; A52C 60 ` + +; ---------------------------------------------------------------------------- +; dunno, referenced by routine at $A50F +sfx_a52d: + .byte $01,$81,$00,$0A,$02,$01,$81,$00 ; A52D 01 81 00 0A 02 01 81 00 ........ + .byte $32,$02,$01,$81,$00,$1E,$02,$00 ; A535 32 02 01 81 00 1E 02 00 2....... +; ---------------------------------------------------------------------------- +LA53D: lda #$00 ; A53D A9 00 .. + jmp L8F79 ; A53F 4C 79 8F Ly. + +; ---------------------------------------------------------------------------- +; dunno, referenced by routine at $A498 +data_table_a542: + .byte $0C ; A542 0C . +LA543: .byte $05,$18,$09,$58,$05,$80,$15,$18 ; A543 05 18 09 58 05 80 15 18 ...X.... + .byte $09,$28,$25,$4C,$1D,$80,$09,$18 ; A54B 09 28 25 4C 1D 80 09 18 .(%L.... + .byte $15,$70,$25,$2C,$3C,$4C,$45,$0C ; A553 15 70 25 2C 3C 4C 45 0C .p%,<LE. + .byte $55,$20,$55,$4C,$4D,$8C,$55 ; A55B 55 20 55 4C 4D 8C 55 U ULM.U +LA562: .byte $18 ; A562 18 . +LA563: .byte $15,$40,$05,$80,$09,$8C,$05,$18 ; A563 15 40 05 80 09 8C 05 18 .@...... + .byte $09,$4C,$0D,$70,$25,$80,$09,$28 ; A56B 09 4C 0D 70 25 80 09 28 .L.p%..( + .byte $25,$80,$15,$4C,$35,$6C,$3C,$0C ; A573 25 80 15 4C 35 6C 3C 0C %..L5l<. + .byte $55,$4C,$4D,$78,$55,$8C,$55 ; A57B 55 4C 4D 78 55 8C 55 ULMxU.U +LA582: .byte $01 ; A582 01 . +LA583: .byte $08,$02,$C6,$01,$08,$01,$08,$02 ; A583 08 02 C6 01 08 01 08 02 ........ + .byte $C6,$01,$08,$02,$C6,$02,$C6,$01 ; A58B C6 01 08 02 C6 02 C6 01 ........ + .byte $08,$01,$08,$01,$08,$02,$C6,$01 ; A593 08 01 08 01 08 02 C6 01 ........ + .byte $08,$01,$08,$02,$C6,$01,$08 ; A59B 08 01 08 02 C6 01 08 ....... +LA5A2: .byte $01 ; A5A2 01 . +LA5A3: .byte $08,$01,$08,$02,$C6,$01,$08,$02 ; A5A3 08 01 08 02 C6 01 08 02 ........ + .byte $C6,$02,$C6,$01,$08,$02,$C6,$01 ; A5AB C6 02 C6 01 08 02 C6 01 ........ + .byte $08,$01,$08,$02,$C6,$01,$08,$01 ; A5B3 08 01 08 02 C6 01 08 01 ........ + .byte $08,$02,$C6,$01,$08,$01,$08 ; A5BB 08 02 C6 01 08 01 08 ....... +LA5C2: .byte $03,$D3,$A5,$08,$00,$00,$01,$00 ; A5C2 03 D3 A5 08 00 00 01 00 ........ + .byte $04,$D3,$A5,$08,$00,$00,$01,$00 ; A5CA 04 D3 A5 08 00 00 01 00 ........ + .byte $FF,$FF,$FF,$AA,$AA,$FF,$FF,$00 ; A5D2 FF FF FF AA AA FF FF 00 ........ + .byte $00,$C3,$C3,$C3,$C3,$FF,$FF,$C3 ; A5DA 00 C3 C3 C3 C3 FF FF C3 ........ + .byte $C3,$00,$00,$00,$00,$00,$00,$00 ; A5E2 C3 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00 ; A5EA 00 00 00 00 00 00 ...... +LA5F0: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; A5F0 FE 33 9C FD 04 00 04 05 .3...... + .byte $06,$84,$05,$06,$04,$15,$06,$84 ; A5F8 06 84 05 06 04 15 06 84 ........ + .byte $15,$06,$04,$25,$0C,$6C,$25,$0C ; A600 15 06 04 25 0C 6C 25 0C ...%.l%. + .byte $04,$35,$0C,$6C,$35,$0C,$04,$45 ; A608 04 35 0C 6C 35 0C 04 45 .5.l5..E + .byte $04,$24,$45,$04,$6C,$45,$04,$8C ; A610 04 24 45 04 6C 45 04 8C .$E.lE.. + .byte $45,$04,$04,$55,$06,$84,$55,$06 ; A618 45 04 04 55 06 84 55 06 E..U..U. + .byte $FE,$5F,$9C,$FD,$00,$04,$0C,$01 ; A620 FE 5F 9C FD 00 04 0C 01 ._...... + .byte $05,$8C,$01,$05,$FE,$B3,$9C ; A628 05 8C 01 05 FE B3 9C ....... +LA62F: .byte $04,$02,$01,$04,$12,$01,$04,$22 ; A62F 04 02 01 04 12 01 04 22 ......." + .byte $01,$04,$32,$01,$04,$42,$01,$04 ; A637 01 04 32 01 04 42 01 04 ..2..B.. + .byte $52,$01,$98,$02,$01,$98,$12,$01 ; A63F 52 01 98 02 01 98 12 01 R....... + .byte $98,$22,$01,$98,$32,$01,$98,$42 ; A647 98 22 01 98 32 01 98 42 ."..2..B + .byte $01,$98,$52,$01,$FF ; A64F 01 98 52 01 FF ..R.. +LA654: .byte $22,$00,$24,$00,$26,$00,$28,$00 ; A654 22 00 24 00 26 00 28 00 ".$.&.(. + .byte $2A,$00,$2C,$00,$C2,$00,$C4,$00 ; A65C 2A 00 2C 00 C2 00 C4 00 *.,..... + .byte $C6,$00,$C8,$00,$CA,$00,$CC,$00 ; A664 C6 00 C8 00 CA 00 CC 00 ........ + .byte $FF ; A66C FF . +LA66D: .byte $00,$00,$00,$01,$7A,$01,$01,$66 ; A66D 00 00 00 01 7A 01 01 66 ....z..f + .byte $03,$86,$A6,$06,$4C,$4A,$01,$66 ; A675 03 86 A6 06 4C 4A 01 66 ....LJ.f + .byte $04,$86,$A6,$06,$A4,$CA,$01,$66 ; A67D 04 86 A6 06 A4 CA 01 66 .......f +; horizontally moving platforms from level02 +dw_platform_player: + .byte $FF,$FF,$FF,$AA,$55,$FF,$FF ; A685 FF FF FF AA 55 FF FF ....U.. +; ---------------------------------------------------------------------------- +LA68C: jsr L8036 ; A68C 20 36 80 6. + lda #$06 ; A68F A9 06 .. + sta $0760 ; A691 8D 60 07 .`. + ldy #$2A ; A694 A0 2A .* +LA696: ldx #$06 ; A696 A2 06 .. +LA698: lda LA781,x ; A698 BD 81 A7 ... + sta $2B00,y ; A69B 99 00 2B ..+ + iny ; A69E C8 . + dex ; A69F CA . + bne LA698 ; A6A0 D0 F6 .. + tya ; A6A2 98 . + clc ; A6A3 18 . + adc #$1A ; A6A4 69 1A i. + tay ; A6A6 A8 . + dec $0760 ; A6A7 CE 60 07 .`. + bne LA696 ; A6AA D0 EA .. + lda #$FF ; A6AC A9 FF .. + sta SIZEM ; A6AE 8D 0C D0 ... + stx $068C ; A6B1 8E 8C 06 ... + lda #$01 ; A6B4 A9 01 .. + sta SIZEP2 ; A6B6 8D 0A D0 ... + sta SIZEP3 ; A6B9 8D 0B D0 ... +LA6BC: rts ; A6BC 60 ` + +; ---------------------------------------------------------------------------- +LA6BD: lda $06F5 ; A6BD AD F5 06 ... + beq LA6BC ; A6C0 F0 FA .. + cmp #$01 ; A6C2 C9 01 .. + bne LA6DC ; A6C4 D0 16 .. + inc $06F5 ; A6C6 EE F5 06 ... + inc $0669 ; A6C9 EE 69 06 .i. + inc $066C ; A6CC EE 6C 06 .l. + inc $066D ; A6CF EE 6D 06 .m. + lda #$01 ; A6D2 A9 01 .. + sta $0770 ; A6D4 8D 70 07 .p. + lda #$FF ; A6D7 A9 FF .. + sta $0771 ; A6D9 8D 71 07 .q. +LA6DC: lda $0623 ; A6DC AD 23 06 .#. + cmp #$02 ; A6DF C9 02 .. + beq LA6BC ; A6E1 F0 D9 .. + lda $0622 ; A6E3 AD 22 06 .". + beq LA6BC ; A6E6 F0 D4 .. + ldx #$02 ; A6E8 A2 02 .. +LA6EA: inx ; A6EA E8 . + cpx #$05 ; A6EB E0 05 .. + beq LA70F ; A6ED F0 20 . + clc ; A6EF 18 . + lda $067D,x ; A6F0 BD 7D 06 .}. + adc $076D,x ; A6F3 7D 6D 07 }m. + sta $067D,x ; A6F6 9D 7D 06 .}. + cmp #$4B ; A6F9 C9 4B .K + beq LA701 ; A6FB F0 04 .. + cmp #$A4 ; A6FD C9 A4 .. + bne LA6EA ; A6FF D0 E9 .. +LA701: lda $076D,x ; A701 BD 6D 07 .m. + eor #$FF ; A704 49 FF I. + sta $076D,x ; A706 9D 6D 07 .m. + inc $076D,x ; A709 FE 6D 07 .m. + jmp LA6EA ; A70C 4C EA A6 L.. + +; ---------------------------------------------------------------------------- +LA70F: lda $2BCF ; A70F AD CF 2B ..+ + sta $2B0E ; A712 8D 0E 2B ..+ + ldy #$CF ; A715 A0 CF .. + ldx #$CE ; A717 A2 CE .. +LA719: lda $2B00,x ; A719 BD 00 2B ..+ + sta $2B00,y ; A71C 99 00 2B ..+ + dex ; A71F CA . + dey ; A720 88 . + bne LA719 ; A721 D0 F6 .. + rts ; A723 60 ` + +; ---------------------------------------------------------------------------- +LA724: lda $0623 ; A724 AD 23 06 .#. + cmp #$02 ; A727 C9 02 .. + beq LA778 ; A729 F0 4D .M + lda $0622 ; A72B AD 22 06 .". + beq LA778 ; A72E F0 48 .H + lda $0778 ; A730 AD 78 07 .x. + beq LA73D ; A733 F0 08 .. + lda #$00 ; A735 A9 00 .. + sta $06ED ; A737 8D ED 06 ... + sta $0778 ; A73A 8D 78 07 .x. +LA73D: lda collision_save+8 ; A73D AD B8 06 ... + ora collision_save+9 ; A740 0D B9 06 ... + ora collision_save+10 ; A743 0D BA 06 ... + ora collision_save+11 ; A746 0D BB 06 ... + tax ; A749 AA . + ora collision_save+14 ; A74A 0D BE 06 ... + ora collision_save+15 ; A74D 0D BF 06 ... + tay ; A750 A8 . + and #$01 ; A751 29 01 ). + beq LA760 ; A753 F0 0B .. + lda collision_save+4 ; A755 AD B4 06 ... + ora #$01 ; A758 09 01 .. + sta collision_save+4 ; A75A 8D B4 06 ... + inc $0683 ; A75D EE 83 06 ... +LA760: tya ; A760 98 . + and #$02 ; A761 29 02 ). + beq LA779 ; A763 F0 14 .. + lda collision_save+5 ; A765 AD B5 06 ... + ora #$01 ; A768 09 01 .. + sta collision_save+5 ; A76A 8D B5 06 ... + txa ; A76D 8A . + and #$02 ; A76E 29 02 ). + beq LA778 ; A770 F0 06 .. + inc $0683 ; A772 EE 83 06 ... + sta $0778 ; A775 8D 78 07 .x. +LA778: rts ; A778 60 ` + +; ---------------------------------------------------------------------------- +LA779: lda $0683 ; A779 AD 83 06 ... + and #$FE ; A77C 29 FE ). + sta $0683 ; A77E 8D 83 06 ... +LA781: rts ; A781 60 ` + +; ---------------------------------------------------------------------------- +; the dumbwaiters from level02. stored upside-down. +dumbwaiter_player: + .byte $18,$3C,$7E,$FF,$FF,$FF,$00,$00 ; A782 18 3C 7E FF FF FF 00 00 .<~..... + .byte $00,$00,$00,$00,$00,$00 ; A78A 00 00 00 00 00 00 ...... +LA790: .byte $FE,$33,$9C,$FD,$04,$00,$40,$05 ; A790 FE 33 9C FD 04 00 40 05 .3....@. + .byte $08,$18,$15,$0A,$04,$25,$14,$18 ; A798 08 18 15 0A 04 25 14 18 .....%.. + .byte $35,$0A,$2C,$45,$0A,$04,$55,$0F ; A7A0 35 0A 2C 45 0A 04 55 0F 5.,E..U. + .byte $60,$55,$0F,$4C,$15,$0F,$60,$25 ; A7A8 60 55 0F 4C 15 0F 60 25 `U.L..`% + .byte $0F,$4C,$35,$0F,$60,$45,$05,$FE ; A7B0 0F 4C 35 0F 60 45 05 FE .L5.`E.. + .byte $5F,$9C,$FD,$00,$04,$4C,$01,$05 ; A7B8 5F 9C FD 00 04 4C 01 05 _....L.. + .byte $4C,$21,$05,$4C,$41,$05,$18,$11 ; A7C0 4C 21 05 4C 41 05 18 11 L!.LA... + .byte $05,$80,$11,$05,$2C,$31,$05,$6C ; A7C8 05 80 11 05 2C 31 05 6C ....,1.l + .byte $31,$05,$FE,$B3,$9C ; A7D0 31 05 FE B3 9C 1.... +LA7D5: .byte $40,$02,$01,$5C,$02,$01,$24,$12 ; A7D5 40 02 01 5C 02 01 24 12 @..\..$. + .byte $01,$3C,$12,$01,$60,$12,$01,$78 ; A7DD 01 3C 12 01 60 12 01 78 .<..`..x + .byte $12,$01,$04,$22,$01,$3C,$22,$01 ; A7E5 12 01 04 22 01 3C 22 01 ...".<". + .byte $60,$22,$01,$98,$22,$01,$18,$32 ; A7ED 60 22 01 98 22 01 18 32 `".."..2 + .byte $01,$84,$32,$01,$3C,$42,$01,$60 ; A7F5 01 84 32 01 3C 42 01 60 ..2.<B.` + .byte $42,$01,$04,$52,$01,$98,$52,$01 ; A7FD 42 01 04 52 01 98 52 01 B..R..R. + .byte $FF ; A805 FF . +LA806: .byte $62,$00,$82,$00,$44,$00,$64,$00 ; A806 62 00 82 00 44 00 64 00 b...D.d. + .byte $84,$00,$A4,$00,$26,$00,$66,$00 ; A80E 84 00 A4 00 26 00 66 00 ....&.f. + .byte $86,$00,$C6,$00,$48,$00,$A8,$00 ; A816 86 00 C6 00 48 00 A8 00 ....H... + .byte $6A,$00,$8A,$00,$2C,$00,$CC,$00 ; A81E 6A 00 8A 00 2C 00 CC 00 j...,... + .byte $FF ; A826 FF . +; ---------------------------------------------------------------------------- +LA827: lda $0619 ; A827 AD 19 06 ... + asl a ; A82A 0A . + asl a ; A82B 0A . + asl a ; A82C 0A . + asl a ; A82D 0A . + ora #$08 ; A82E 09 08 .. + sta COLOR3 ; A830 8D C7 02 ... + jmp check_collisions_1 ; A833 4C 73 8F Ls. + +; ---------------------------------------------------------------------------- +LA836: lda $0623 ; A836 AD 23 06 .#. + cmp #$02 ; A839 C9 02 .. + beq LA842 ; A83B F0 05 .. + lda $0622 ; A83D AD 22 06 .". + bne LA843 ; A840 D0 01 .. +LA842: rts ; A842 60 ` + +; ---------------------------------------------------------------------------- +LA843: ldx #$05 ; A843 A2 05 .. +LA845: dex ; A845 CA . + beq LA842 ; A846 F0 FA .. + lda $075F,x ; A848 BD 5F 07 ._. + bne LA865 ; A84B D0 18 .. + lda RANDOM ; A84D AD 0A D2 ... + and #$1F ; A850 29 1F ). + bne LA845 ; A852 D0 F1 .. + inc $075F,x ; A854 FE 5F 07 ._. + lda #$00 ; A857 A9 00 .. + sta $069E,x ; A859 9D 9E 06 ... + lda $067E ; A85C AD 7E 06 .~. + clc ; A85F 18 . + adc #$03 ; A860 69 03 i. + sta $069A,x ; A862 9D 9A 06 ... +LA865: lda $0763,x ; A865 BD 63 07 .c. + bne LA89E ; A868 D0 34 .4 + lda dli_vec_shadow_hi,x ; A86A BD AF 06 ... + and #$01 ; A86D 29 01 ). + beq LA89E ; A86F F0 2D .- + lda $067E ; A871 AD 7E 06 .~. + clc ; A874 18 . + adc #$03 ; A875 69 03 i. + ldy #$01 ; A877 A0 01 .. + cmp $069A,x ; A879 DD 9A 06 ... + beq LA882 ; A87C F0 04 .. + iny ; A87E C8 . + bcc LA882 ; A87F 90 01 .. + iny ; A881 C8 . +LA882: tya ; A882 98 . + sta $0763,x ; A883 9D 63 07 .c. + lda #$00 ; A886 A9 00 .. + sta $0767,x ; A888 9D 67 07 .g. + txa ; A88B 8A . + pha ; A88C 48 H + lda #$0D ; A88D A9 0D .. + sta sfx_slot_tempo ; A88F 8D 3E 06 .>. + lda #$A9 ; A892 A9 A9 .. + sta sfx_slot_timer ; A894 8D 3F 06 .?. + lda #$03 ; A897 A9 03 .. + jsr L8003 ; A899 20 03 80 .. + pla ; A89C 68 h + tax ; A89D AA . +LA89E: lda $0763,x ; A89E BD 63 07 .c. + bne LA8C1 ; A8A1 D0 1E .. +LA8A3: clc ; A8A3 18 . + lda $069E,x ; A8A4 BD 9E 06 ... + adc #$02 ; A8A7 69 02 i. + cmp #$CE ; A8A9 C9 CE .. + bcs LA8B3 ; A8AB B0 06 .. + sta $069E,x ; A8AD 9D 9E 06 ... + jmp LA845 ; A8B0 4C 45 A8 LE. + +; ---------------------------------------------------------------------------- +LA8B3: lda #$00 ; A8B3 A9 00 .. + sta $069A,x ; A8B5 9D 9A 06 ... + sta $075F,x ; A8B8 9D 5F 07 ._. + sta $0763,x ; A8BB 9D 63 07 .c. + jmp LA845 ; A8BE 4C 45 A8 LE. + +; ---------------------------------------------------------------------------- +LA8C1: lda $0767,x ; A8C1 BD 67 07 .g. + cmp #$08 ; A8C4 C9 08 .. + bne LA8D4 ; A8C6 D0 0C .. + lda #$00 ; A8C8 A9 00 .. + sta $0763,x ; A8CA 9D 63 07 .c. + cpx #$03 ; A8CD E0 03 .. + bcc LA8A3 ; A8CF 90 D2 .. + jmp LA865 ; A8D1 4C 65 A8 Le. + +; ---------------------------------------------------------------------------- +LA8D4: tay ; A8D4 A8 . + clc ; A8D5 18 . + lda $069E,x ; A8D6 BD 9E 06 ... + adc LA905,y ; A8D9 79 05 A9 y.. + sta $069E,x ; A8DC 9D 9E 06 ... + lda data_table_a8fd,y ; A8DF B9 FD A8 ... + tay ; A8E2 A8 . + beq LA8EF ; A8E3 F0 0A .. + tay ; A8E5 A8 . + lda $0763,x ; A8E6 BD 63 07 .c. + cmp #$03 ; A8E9 C9 03 .. + beq LA8EF ; A8EB F0 02 .. + ldy #$FE ; A8ED A0 FE .. +LA8EF: tya ; A8EF 98 . + clc ; A8F0 18 . + adc $069A,x ; A8F1 7D 9A 06 }.. + sta $069A,x ; A8F4 9D 9A 06 ... + inc $0767,x ; A8F7 FE 67 07 .g. + jmp LA845 ; A8FA 4C 45 A8 LE. + +; ---------------------------------------------------------------------------- +; dunno, referenced by routine at $A8D4 +data_table_a8fd: + .byte $00,$02,$02,$02,$02,$02,$02,$00 ; A8FD 00 02 02 02 02 02 02 00 ........ +LA905: .byte $FE,$FE,$FE,$00,$00,$02,$02,$02 ; A905 FE FE FE 00 00 02 02 02 ........ + .byte $01,$83,$00,$0A,$03,$00,$00,$00 ; A90D 01 83 00 0A 03 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; A915 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00 ; A91D 00 00 00 ... +LA920: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; A920 FE 33 9C FD 04 00 04 05 .3...... + .byte $04,$24,$05,$04,$44,$05,$06,$6C ; A928 04 24 05 04 44 05 06 6C .$..D..l + .byte $05,$04,$8C,$05,$04,$30,$16,$04 ; A930 05 04 8C 05 04 30 16 04 .....0.. + .byte $60,$16,$04,$04,$25,$09,$78,$25 ; A938 60 16 04 04 25 09 78 25 `...%.x% + .byte $09,$04,$35,$09,$40,$35,$08,$78 ; A940 09 04 35 09 40 35 08 78 ..5.@5.x + .byte $35,$09,$40,$45,$02,$58,$45,$02 ; A948 35 09 40 45 02 58 45 02 5.@E.XE. + .byte $04,$55,$05,$28,$55,$06,$4C,$55 ; A950 04 55 05 28 55 06 4C 55 .U.(U.LU + .byte $02,$60,$55,$06,$88,$55,$05,$FE ; A958 02 60 55 06 88 55 05 FE .`U..U.. + .byte $5F,$9C,$FD,$00,$04,$04,$01,$09 ; A960 5F 9C FD 00 04 04 01 09 _....... + .byte $94,$01,$09,$30,$19,$0F,$68,$19 ; A968 94 01 09 30 19 0F 68 19 ...0..h. + .byte $0F,$FE,$B3,$9C ; A970 0F FE B3 9C .... +LA974: .byte $24,$02,$01,$44,$02,$01,$58,$02 ; A974 24 02 01 44 02 01 58 02 $..D..X. + .byte $01,$78,$02,$01,$44,$12,$01,$58 ; A97C 01 78 02 01 44 12 01 58 .x..D..X + .byte $12,$01,$24,$22,$01,$78,$22,$01 ; A984 12 01 24 22 01 78 22 01 ..$".x". + .byte $40,$32,$01,$5C,$32,$01,$40,$42 ; A98C 40 32 01 5C 32 01 40 42 @2.\2.@B + .byte $01,$5C,$42,$01,$04,$52,$01,$3C ; A994 01 5C 42 01 04 52 01 3C .\B..R.< + .byte $52,$01,$60,$52,$01,$98,$52,$01 ; A99C 52 01 60 52 01 98 52 01 R.`R..R. + .byte $FF ; A9A4 FF . +LA9A5: .byte $42,$00,$62,$00,$82,$00,$A2,$00 ; A9A5 42 00 62 00 82 00 A2 00 B.b..... + .byte $64,$00,$84,$00,$46,$00,$A6,$00 ; A9AD 64 00 84 00 46 00 A6 00 d...F... + .byte $68,$00,$88,$00,$6A,$00,$8A,$00 ; A9B5 68 00 88 00 6A 00 8A 00 h...j... + .byte $2C,$00,$6C,$00,$8C,$00,$CC,$00 ; A9BD 2C 00 6C 00 8C 00 CC 00 ,.l..... + .byte $FF ; A9C5 FF . +LA9C6: .byte $20 ; A9C6 20 +; ---------------------------------------------------------------------------- + rol $80,x ; A9C7 36 80 6. + lda #$02 ; A9C9 A9 02 .. + sta $0770 ; A9CB 8D 70 07 .p. + sta $0772 ; A9CE 8D 72 07 .r. + lda #$FE ; A9D1 A9 FE .. + sta $0771 ; A9D3 8D 71 07 .q. + sta $0773 ; A9D6 8D 73 07 .s. + ldx #$05 ; A9D9 A2 05 .. + lda #$00 ; A9DB A9 00 .. +LA9DD: sta HPOSP3,x ; A9DD 9D 03 D0 ... + dex ; A9E0 CA . + bne LA9DD ; A9E1 D0 FA .. + lda #$C0 ; A9E3 A9 C0 .. + jsr LAA0C ; A9E5 20 0C AA .. + lda #$C0 ; A9E8 A9 C0 .. + jsr LAA0C ; A9EA 20 0C AA .. + lda #$30 ; A9ED A9 30 .0 + jsr LAA0C ; A9EF 20 0C AA .. + lda #$30 ; A9F2 A9 30 .0 + jsr LAA0C ; A9F4 20 0C AA .. + lda #$0C ; A9F7 A9 0C .. + jsr LAA0C ; A9F9 20 0C AA .. + lda #$0C ; A9FC A9 0C .. + jsr LAA0C ; A9FE 20 0C AA .. + lda #$03 ; AA01 A9 03 .. + jsr LAA0C ; AA03 20 0C AA .. + lda #$03 ; AA06 A9 03 .. + jsr LAA0C ; AA08 20 0C AA .. + rts ; AA0B 60 ` + +; ---------------------------------------------------------------------------- +LAA0C: sta dm_progctr ; AA0C 85 C0 .. +LAA0E: lda RANDOM ; AA0E AD 0A D2 ... + cmp #$AC ; AA11 C9 AC .. + bcs LAA0E ; AA13 B0 F9 .. + tay ; AA15 A8 . + ldx #$1E ; AA16 A2 1E .. +LAA18: lda $2B00,y ; AA18 B9 00 2B ..+ + ora dm_progctr ; AA1B 05 C0 .. + sta $2B00,y ; AA1D 99 00 2B ..+ + iny ; AA20 C8 . + dex ; AA21 CA . + bne LAA18 ; AA22 D0 F4 .. + rts ; AA24 60 ` + +; ---------------------------------------------------------------------------- +LAA25: lda $076F ; AA25 AD 6F 07 .o. + cmp #$04 ; AA28 C9 04 .. + bne LAA2D ; AA2A D0 01 .. + rts ; AA2C 60 ` + +; ---------------------------------------------------------------------------- +LAA2D: tax ; AA2D AA . + inc $0774,x ; AA2E FE 74 07 .t. + inc $076F ; AA31 EE 6F 07 .o. + rts ; AA34 60 ` + +; ---------------------------------------------------------------------------- +LAA35: lda $0622 ; AA35 AD 22 06 .". + bne LAA3B ; AA38 D0 01 .. +LAA3A: rts ; AA3A 60 ` + +; ---------------------------------------------------------------------------- +LAA3B: ldx #$05 ; AA3B A2 05 .. +LAA3D: dex ; AA3D CA . + beq LAA3A ; AA3E F0 FA .. + lda $0773,x ; AA40 BD 73 07 .s. + beq LAA3D ; AA43 F0 F8 .. + lda $0777,x ; AA45 BD 77 07 .w. + clc ; AA48 18 . + adc $076F,x ; AA49 7D 6F 07 }o. + sta $0777,x ; AA4C 9D 77 07 .w. + sta HPOSP3,x ; AA4F 9D 03 D0 ... + jmp LAA3D ; AA52 4C 3D AA L=. + +; ---------------------------------------------------------------------------- +LAA55: lda $0622 ; AA55 AD 22 06 .". + beq LAA3A ; AA58 F0 E0 .. + ldx #$05 ; AA5A A2 05 .. +LAA5C: dex ; AA5C CA . + beq LAA3A ; AA5D F0 DB .. + lda collision_save+7,x ; AA5F BD B7 06 ... + and #$01 ; AA62 29 01 ). + beq LAA5C ; AA64 F0 F6 .. + lda $067E ; AA66 AD 7E 06 .~. + clc ; AA69 18 . + adc $076F,x ; AA6A 7D 6F 07 }o. + sta $067E ; AA6D 8D 7E 06 .~. + jmp LAA5C ; AA70 4C 5C AA L\. + +; ---------------------------------------------------------------------------- +LAA73: inc $0764 ; AA73 EE 64 07 .d. + lda $0764 ; AA76 AD 64 07 .d. + and #$01 ; AA79 29 01 ). + beq LAA82 ; AA7B F0 05 .. + lda #$90 ; AA7D A9 90 .. + jmp LAA84 ; AA7F 4C 84 AA L.. + +; ---------------------------------------------------------------------------- +LAA82: lda #$A6 ; AA82 A9 A6 .. +LAA84: sta dm_progctr ; AA84 85 C0 .. + lda #$AA ; AA86 A9 AA .. + sta dm_progctr+1 ; AA88 85 C1 .. + jsr draw_map_jv ; AA8A 20 00 80 .. + jmp LAA25 ; AA8D 4C 25 AA L%. + +; ---------------------------------------------------------------------------- +; dunno what this is for yet +map_aa90: + .byte $FE,$EB,$9C,$FD,$00,$04,$50,$00 ; AA90 FE EB 9C FD 00 04 50 00 ......P. + .byte $0C,$FE,$33,$9C,$4E,$05,$01,$FE ; AA98 0C FE 33 9C 4E 05 01 FE ..3.N... + .byte $DA,$9C,$50,$00,$0C,$FF ; AAA0 DA 9C 50 00 0C FF ..P... +; referenced by routine at $AA82 +map_aaa6: + .byte $FE,$EB,$9C,$FD,$00,$04,$50,$00 ; AAA6 FE EB 9C FD 00 04 50 00 ......P. + .byte $0C,$FE,$33,$9C,$4E,$05,$01,$FE ; AAAE 0C FE 33 9C 4E 05 01 FE ..3.N... + .byte $C9,$9C,$50,$08,$0A,$FF ; AAB6 C9 9C 50 08 0A FF ..P... +LAABC: .byte $AD,$2A,$06,$8D,$C7,$02,$60,$00 ; AABC AD 2A 06 8D C7 02 60 00 .*....`. + .byte $8D,$C7,$02,$60,$00,$09,$40,$45 ; AAC4 8D C7 02 60 00 09 40 45 ...`..@E + .byte $02,$58,$45,$02 ; AACC 02 58 45 02 .XE. +LAAD0: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; AAD0 FE 33 9C FD 04 00 04 05 .3...... + .byte $02,$1A,$05,$0B,$50,$05,$07,$04 ; AAD8 02 1A 05 0B 50 05 07 04 ....P... + .byte $25,$26,$7C,$33,$08,$20,$3B,$03 ; AAE0 25 26 7C 33 08 20 3B 03 %&|3. ;. + .byte $40,$3B,$03,$60,$3B,$06,$04,$47 ; AAE8 40 3B 03 60 3B 06 04 47 @;.`;..G + .byte $04,$20,$4B,$03,$40,$4B,$03,$60 ; AAF0 04 20 4B 03 40 4B 03 60 . K.@K.` + .byte $4B,$03,$80,$4A,$03,$04,$55,$26 ; AAF8 4B 03 80 4A 03 04 55 26 K..J..U& + .byte $FD,$04,$FF,$2C,$4A,$03,$4C,$4A ; AB00 FD 04 FF 2C 4A 03 4C 4A ...,J.LJ + .byte $03,$6C,$4A,$03,$FD,$04,$01,$14 ; AB08 03 6C 4A 03 FD 04 01 14 .lJ..... + .byte $48,$03,$38,$49,$02,$58,$49,$02 ; AB10 48 03 38 49 02 58 49 02 H.8I.XI. + .byte $78,$49,$02,$FE,$5F,$9C,$FD,$00 ; AB18 78 49 02 FE 5F 9C FD 00 xI.._... + .byte $04,$0C,$21,$0D,$84,$01,$09,$84 ; AB20 04 0C 21 0D 84 01 09 84 ..!..... + .byte $2F,$06,$22,$01,$05,$FE,$C9,$9C ; AB28 2F 06 22 01 05 FE C9 9C /."..... + .byte $3C,$08,$06,$35,$28,$04,$55,$28 ; AB30 3C 08 06 35 28 04 55 28 <..5(.U( + .byte $04,$FE,$DA,$9C,$9A,$30,$08,$FE ; AB38 04 FE DA 9C 9A 30 08 FE .....0.. + .byte $B3,$9C ; AB40 B3 9C .. +LAB42: .byte $04,$02,$01,$44,$02,$01,$24,$16 ; AB42 04 02 01 44 02 01 24 16 ...D..$. + .byte $01,$44,$22,$01,$64,$22,$01,$98 ; AB4A 01 44 22 01 64 22 01 98 .D".d".. + .byte $22,$01,$24,$32,$01,$44,$32,$01 ; AB52 22 01 24 32 01 44 32 01 ".$2.D2. + .byte $64,$32,$01,$24,$52,$01,$44,$52 ; AB5A 64 32 01 24 52 01 44 52 d2.$R.DR + .byte $01,$64,$52,$01,$84,$52,$01,$98 ; AB62 01 64 52 01 84 52 01 98 .dR..R.. + .byte $52,$01,$FF ; AB6A 52 01 FF R.. +LAB6D: .byte $22,$10,$62,$20,$44,$30,$66,$40 ; AB6D 22 10 62 20 44 30 66 40 ".b D0f@ + .byte $86,$50,$C6,$60,$48,$70,$68,$80 ; AB75 86 50 C6 60 48 70 68 80 .P.`Hph. + .byte $88,$90,$4C,$A0,$6C,$B0,$8C,$C0 ; AB7D 88 90 4C A0 6C B0 8C C0 ..L.l... + .byte $AC,$00,$CC,$D0,$FF ; AB85 AC 00 CC D0 FF ..... +LAB8A: .byte $00,$00,$A6,$AB,$B6,$AB,$C0,$AB ; AB8A 00 00 A6 AB B6 AB C0 AB ........ + .byte $D3,$AB,$DD,$AB,$F0,$AB,$FA,$AB ; AB92 D3 AB DD AB F0 AB FA AB ........ + .byte $04,$AC,$0E,$AC,$18,$AC,$22,$AC ; AB9A 04 AC 0E AC 18 AC 22 AC ......". + .byte $2C,$AC,$36,$AC,$FE,$49,$9C,$FD ; ABA2 2C AC 36 AC FE 49 9C FD ,.6..I.. + .byte $04,$00,$04,$05,$02,$FE,$33,$9C ; ABAA 04 00 04 05 02 FE 33 9C ......3. + .byte $20,$22,$03,$FF,$FE,$49,$9C,$FD ; ABB2 20 22 03 FF FE 49 9C FD "...I.. + .byte $04,$00,$3E,$05,$02,$FF,$FE,$89 ; ABBA 04 00 3E 05 02 FF FE 89 ..>..... + .byte $9C,$FD,$00,$04,$22,$11,$01,$FE ; ABC2 9C FD 00 04 22 11 01 FE ...."... + .byte $49,$9C,$FD,$04,$FF,$2C,$4A,$03 ; ABCA 49 9C FD 04 FF 2C 4A 03 I....,J. + .byte $FF,$FE,$49,$9C,$FD,$04,$00,$44 ; ABD2 FF FE 49 9C FD 04 00 44 ..I....D + .byte $25,$03,$FF,$FE,$33,$9C,$FD,$04 ; ABDA 25 03 FF FE 33 9C FD 04 %...3... + .byte $00,$6C,$05,$04,$FE,$89,$9C,$FD ; ABE2 00 6C 05 04 FE 89 9C FD .l...... + .byte $00,$04,$84,$11,$02,$FF,$FE,$49 ; ABEA 00 04 84 11 02 FF FE 49 .......I + .byte $9C,$FD,$04,$00,$6C,$05,$04,$FF ; ABF2 9C FD 04 00 6C 05 04 FF ....l... + .byte $FE,$49,$9C,$FD,$04,$00,$60,$4B ; ABFA FE 49 9C FD 04 00 60 4B .I....`K + .byte $03,$FF,$FE,$49,$9C,$FD,$04,$00 ; AC02 03 FF FE 49 9C FD 04 00 ...I.... + .byte $40,$4B,$03,$FF,$FE,$49,$9C,$FD ; AC0A 40 4B 03 FF FE 49 9C FD @K...I.. + .byte $04,$00,$20,$4B,$03,$FF,$FE,$33 ; AC12 04 00 20 4B 03 FF FE 33 .. K...3 + .byte $9C,$FD,$04,$00,$28,$52,$01,$FF ; AC1A 9C FD 04 00 28 52 01 FF ....(R.. + .byte $FE,$33,$9C,$FD,$04,$00,$48,$52 ; AC22 FE 33 9C FD 04 00 48 52 .3....HR + .byte $01,$FF,$FE,$49,$9C,$FD,$04,$00 ; AC2A 01 FF FE 49 9C FD 04 00 ...I.... + .byte $54,$55,$09,$FF,$FE,$33,$9C,$FD ; AC32 54 55 09 FF FE 33 9C FD TU...3.. + .byte $04,$00,$04,$08,$02,$FE,$5F,$9C ; AC3A 04 00 04 08 02 FE 5F 9C ......_. + .byte $FD,$00,$04,$8E,$01,$09,$FF,$00 ; AC42 FD 00 04 8E 01 09 FF 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AC4A 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AC52 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00 ; AC5A 00 00 00 00 00 00 ...... +LAC60: .byte $FE,$33,$9C,$FD,$04,$00,$3C,$05 ; AC60 FE 33 9C FD 04 00 3C 05 .3....<. + .byte $0A,$04,$0C,$08,$7C,$0C,$08,$04 ; AC68 0A 04 0C 08 7C 0C 08 04 ....|... + .byte $15,$08,$7C,$15,$08,$38,$16,$01 ; AC70 15 08 7C 15 08 38 16 01 ..|..8.. + .byte $64,$16,$01,$2C,$2C,$04,$64,$2C ; AC78 64 16 01 2C 2C 04 64 2C d..,,.d, + .byte $04,$2C,$3C,$04,$64,$3C,$04,$04 ; AC80 04 2C 3C 04 64 3C 04 04 .,<.d<.. + .byte $55,$26,$FD,$04,$FF,$24,$0B,$06 ; AC88 55 26 FD 04 FF 24 0B 06 U&...$.. + .byte $FD,$04,$01,$64,$06,$06,$FE,$5F ; AC90 FD 04 01 64 06 06 FE 5F ...d..._ + .byte $9C,$FD,$00,$04,$0C,$01,$15,$4C ; AC98 9C FD 00 04 0C 01 15 4C .......L + .byte $01,$15,$8C,$01,$15,$FE,$C9,$9C ; ACA0 01 15 8C 01 15 FE C9 9C ........ + .byte $39,$19,$03,$65,$19,$03,$FE,$DA ; ACA8 39 19 03 65 19 03 FE DA 9..e.... + .byte $9C,$1F,$12,$0F,$80,$12,$0F,$FE ; ACB0 9C 1F 12 0F 80 12 0F FE ........ + .byte $B3,$9C ; ACB8 B3 9C .. +LACBA: .byte $04,$02,$01,$3C,$02,$01,$60,$02 ; ACBA 04 02 01 3C 02 01 60 02 ...<..`. + .byte $01,$98,$02,$01,$24,$22,$01,$78 ; ACC2 01 98 02 01 24 22 01 78 ....$".x + .byte $22,$01,$24,$32,$01,$78,$32,$01 ; ACCA 22 01 24 32 01 78 32 01 ".$2.x2. + .byte $24,$42,$01,$78,$42,$01,$04,$52 ; ACD2 24 42 01 78 42 01 04 52 $B.xB..R + .byte $01,$3C,$52,$01,$60,$52,$01,$98 ; ACDA 01 3C 52 01 60 52 01 98 .<R.`R.. + .byte $52,$01,$FF ; ACE2 52 01 FF R.. +LACE5: .byte $22,$10,$62,$20,$82,$30,$C2,$40 ; ACE5 22 10 62 20 82 30 C2 40 ".b .0.@ + .byte $46,$50,$A6,$50,$48,$60,$A8,$60 ; ACED 46 50 A6 50 48 60 A8 60 FP.PH`.` + .byte $4A,$70,$AA,$70,$2C,$80,$6C,$00 ; ACF5 4A 70 AA 70 2C 80 6C 00 Jp.p,.l. + .byte $8C,$00,$CC,$90,$FF ; ACFD 8C 00 CC 90 FF ..... +LAD02: .byte $00,$00,$16,$AD,$16,$AD,$20,$AD ; AD02 00 00 16 AD 16 AD 20 AD ...... . + .byte $20,$AD,$2A,$AD,$34,$AD,$3E,$AD ; AD0A 20 AD 2A AD 34 AD 3E AD .*.4.>. + .byte $48,$AD,$58,$AD,$FE,$49,$9C,$FD ; AD12 48 AD 58 AD FE 49 9C FD H.X..I.. + .byte $04,$FF,$24,$0B,$06,$FF,$FE,$49 ; AD1A 04 FF 24 0B 06 FF FE 49 ..$....I + .byte $9C,$FD,$04,$01,$64,$06,$06,$FF ; AD22 9C FD 04 01 64 06 06 FF ....d... + .byte $FE,$89,$9C,$FD,$00,$04,$4C,$21 ; AD2A FE 89 9C FD 00 04 4C 21 ......L! + .byte $02,$FF,$FE,$89,$9C,$FD,$00,$04 ; AD32 02 FF FE 89 9C FD 00 04 ........ + .byte $4C,$29,$02,$FF,$FE,$89,$9C,$FD ; AD3A 4C 29 02 FF FE 89 9C FD L)...... + .byte $00,$04,$4C,$31,$02,$FF,$FE,$C9 ; AD42 00 04 4C 31 02 FF FE C9 ..L1.... + .byte $9C,$FD,$00,$04,$9A,$18,$0E,$FE ; AD4A 9C FD 00 04 9A 18 0E FE ........ + .byte $89,$9C,$0C,$31,$02,$FF,$FE,$C9 ; AD52 89 9C 0C 31 02 FF FE C9 ...1.... + .byte $9C,$FD,$00,$04,$04,$18,$0E,$FE ; AD5A 9C FD 00 04 04 18 0E FE ........ + .byte $89,$9C,$8C,$31,$02,$FF ; AD62 89 9C 8C 31 02 FF ...1.. +; ---------------------------------------------------------------------------- +LAD68: lda $0622 ; AD68 AD 22 06 .". + bne LAD6E ; AD6B D0 01 .. +LAD6D: rts ; AD6D 60 ` + +; ---------------------------------------------------------------------------- +LAD6E: ldx #$FF ; AD6E A2 FF .. +LAD70: inx ; AD70 E8 . + cpx work_level_bullet_chance ; AD71 EC 8B 07 ... + beq LAD6D ; AD74 F0 F7 .. + lda $0756,x ; AD76 BD 56 07 .V. + cmp #$02 ; AD79 C9 02 .. + beq LAD8B ; AD7B F0 0E .. + sta $076C,x ; AD7D 9D 6C 07 .l. + lda #$00 ; AD80 A9 00 .. + sta $0764,x ; AD82 9D 64 07 .d. + sta $0768,x ; AD85 9D 68 07 .h. + jmp LAD70 ; AD88 4C 70 AD Lp. + +; ---------------------------------------------------------------------------- +LAD8B: cmp $076C,x ; AD8B DD 6C 07 .l. + beq LADA1 ; AD8E F0 11 .. + sta $076C,x ; AD90 9D 6C 07 .l. + lda $075A,x ; AD93 BD 5A 07 .Z. + beq LAD9E ; AD96 F0 06 .. + inc $0768,x ; AD98 FE 68 07 .h. + jmp LADA1 ; AD9B 4C A1 AD L.. + +; ---------------------------------------------------------------------------- +LAD9E: inc $0764,x ; AD9E FE 64 07 .d. +LADA1: lda $0764,x ; ADA1 BD 64 07 .d. + beq code_adb5 ; ADA4 F0 0F .. + and #$0F ; ADA6 29 0F ). + tay ; ADA8 A8 . + lda data_table_adc7,y ; ADA9 B9 C7 AD ... + sta $075A,x ; ADAC 9D 5A 07 .Z. + inc $0764,x ; ADAF FE 64 07 .d. + jmp LAD70 ; ADB2 4C 70 AD Lp. + +; ---------------------------------------------------------------------------- +code_adb5: + lda $0768,x ; ADB5 BD 68 07 .h. + and #$0F ; ADB8 29 0F ). + tay ; ADBA A8 . + lda data_table_adc7,y ; ADBB B9 C7 AD ... +LADBF := * + 1 + sta $075E,x ; ADBE 9D 5E 07 .^. +code_adc1: + inc $0768,x ; ADC1 FE 68 07 .h. + jmp LAD70 ; ADC4 4C 70 AD Lp. + +; ---------------------------------------------------------------------------- +; dunno, referenced by routines at $AD9E and $ADB5 +data_table_adc7: + .byte $00,$01,$02,$03,$04,$03,$02,$01 ; ADC7 00 01 02 03 04 03 02 01 ........ + .byte $00,$FF,$FE,$FD,$FC,$FD,$FE,$FF ; ADCF 00 FF FE FD FC FD FE FF ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; ADD7 00 00 00 00 00 00 00 00 ........ + .byte $00 ; ADDF 00 . +LADE0: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; ADE0 FE 33 9C FD 04 00 04 05 .3...... + .byte $02,$44,$05,$06,$94,$05,$02,$30 ; ADE8 02 44 05 06 94 05 02 30 .D.....0 + .byte $0A,$02,$68,$0A,$02,$28,$21,$04 ; ADF0 0A 02 68 0A 02 28 21 04 ..h..(!. + .byte $68,$21,$04,$04,$25,$06,$84,$25 ; ADF8 68 21 04 04 25 06 84 25 h!..%..% + .byte $06,$04,$45,$10,$5C,$45,$10,$04 ; AE00 06 04 45 10 5C 45 10 04 ..E.\E.. + .byte $55,$06,$2C,$55,$04,$64,$55,$04 ; AE08 55 06 2C 55 04 64 55 04 U.,U.dU. + .byte $84,$55,$06,$FD,$04,$FF,$84,$09 ; AE10 84 55 06 FD 04 FF 84 09 .U...... + .byte $04,$1C,$24,$03,$FD,$04,$01,$0C ; AE18 04 1C 24 03 FD 04 01 0C ..$..... + .byte $06,$04,$78,$22,$03,$FE,$5F,$9C ; AE20 06 04 78 22 03 FE 5F 9C ..x".._. + .byte $FD,$00,$04,$0C,$21,$09,$8C,$21 ; AE28 FD 00 04 0C 21 09 8C 21 ....!..! + .byte $09,$30,$41,$05,$68,$41,$05,$FE ; AE30 09 30 41 05 68 41 05 FE .0A.hA.. + .byte $C9,$9C,$34,$0C,$04,$6B,$0C,$04 ; AE38 C9 9C 34 0C 04 6B 0C 04 ..4..k.. + .byte $FE,$DA,$9C,$44,$02,$10,$5A,$02 ; AE40 FE DA 9C 44 02 10 5A 02 ...D..Z. + .byte $10,$FE,$B3,$9C ; AE48 10 FE B3 9C .... +LAE4C: .byte $04,$02,$01,$98,$02,$01,$04,$22 ; AE4C 04 02 01 98 02 01 04 22 ......." + .byte $01,$98,$22,$01,$18,$34,$01,$84 ; AE54 01 98 22 01 18 34 01 84 .."..4.. + .byte $34,$01,$04,$42,$01,$98,$42,$01 ; AE5C 34 01 04 42 01 98 42 01 4..B..B. + .byte $04,$52,$01,$38,$52,$01,$64,$52 ; AE64 04 52 01 38 52 01 64 52 .R.8R.dR + .byte $01,$98,$52,$01,$FF ; AE6C 01 98 52 01 FF ..R.. +LAE71: .byte $22,$00,$C2,$00,$26,$00,$C6,$00 ; AE71 22 00 C2 00 26 00 C6 00 "...&... + .byte $48,$00,$A8,$00,$2A,$00,$CA,$00 ; AE79 48 00 A8 00 2A 00 CA 00 H...*... + .byte $2C,$00,$6C,$00,$8C,$00,$CC,$00 ; AE81 2C 00 6C 00 8C 00 CC 00 ,.l..... + .byte $FF ; AE89 FF . +LAE8A: .byte $03,$00,$00,$01,$7C,$01,$01,$00 ; AE8A 03 00 00 01 7C 01 01 00 ....|... + .byte $04,$0C,$AF,$10,$86,$00,$01,$0F ; AE92 04 0C AF 10 86 00 01 0F ........ + .byte $FF ; AE9A FF . +LAE9B: .byte $20,$36,$80,$A9,$C0,$8D,$70,$07 ; AE9B 20 36 80 A9 C0 8D 70 07 6....p. + .byte $60 ; AEA3 60 ` +LAEA4: .byte $18,$08,$38,$20,$00,$48,$30,$18 ; AEA4 18 08 38 20 00 48 30 18 ..8 .H0. + .byte $28,$10,$10 ; AEAC 28 10 10 (.. +LAEAF: .byte $40,$29,$21,$11,$19,$11,$09,$01 ; AEAF 40 29 21 11 19 11 09 01 @)!..... + .byte $49,$41,$39,$19,$31 ; AEB7 49 41 39 19 31 IA9.1 +LAEBC: .byte $03,$03,$03,$03,$03,$C3,$C3,$7E ; AEBC 03 03 03 03 03 C3 C3 7E .......~ + .byte $C3,$C3,$C3,$C3,$C3,$C3,$C3,$7E ; AEC4 C3 C3 C3 C3 C3 C3 C3 7E .......~ + .byte $C3,$C3,$E7,$FF,$DB,$C3,$C3,$C3 ; AECC C3 C3 E7 FF DB C3 C3 C3 ........ + .byte $FE,$C3,$C3,$C3,$FE,$C0,$C0,$C0 ; AED4 FE C3 C3 C3 FE C0 C0 C0 ........ + .byte $18,$3C,$66,$C3,$FF,$C3,$C3,$C3 ; AEDC 18 3C 66 C3 FF C3 C3 C3 .<f..... + .byte $C3,$C3,$E3,$F3,$DB,$CF,$C7,$C3 ; AEE4 C3 C3 E3 F3 DB CF C7 C3 ........ + .byte $FF,$C0,$C0,$C0,$F8,$C0,$C0,$FF ; AEEC FF C0 C0 C0 F8 C0 C0 FF ........ + .byte $C3,$66,$3C,$18,$18,$18,$18,$18 ; AEF4 C3 66 3C 18 18 18 18 18 .f<..... + .byte $C3,$C3,$66,$3C,$3C,$66,$C3,$C3 ; AEFC C3 C3 66 3C 3C 66 C3 C3 ..f<<f.. + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AF04 00 00 00 00 00 00 00 00 ........ + .byte $40 ; AF0C 40 @ +; ---------------------------------------------------------------------------- + ldy #$20 ; AF0D A0 20 . + rti ; AF0F 40 @ + +; ---------------------------------------------------------------------------- + cpx #$00 ; AF10 E0 00 .. + sec ; AF12 38 8 + jsr L0830 ; AF13 20 30 08 0. + bmi LAF1C ; AF16 30 04 0. + asl a ; AF18 0A . + asl a ; AF19 0A . + asl a ; AF1A 0A . +; NMOS 6502 illegal opcode, NOP zp +illegal_nop: + .byte $04 ; AF1B 04 . +LAF1C: lda $062A ; AF1C AD 2A 06 .*. + sta PCOLR2 ; AF1F 8D C2 02 ... + rts ; AF22 60 ` + +; ---------------------------------------------------------------------------- +LAF23: lda $B2 ; AF23 A5 B2 .. + lsr a ; AF25 4A J + tax ; AF26 AA . + ldy LAEA4,x ; AF27 BC A4 AE ... + iny ; AF2A C8 . + ldx $0771 ; AF2B AE 71 07 .q. + tya ; AF2E 98 . + sta $0773,x ; AF2F 9D 73 07 .s. + dey ; AF32 88 . + ldx $0770 ; AF33 AE 70 07 .p. + lda #$08 ; AF36 A9 08 .. + sta $0772 ; AF38 8D 72 07 .r. +LAF3B: lda LAEBC,y ; AF3B B9 BC AE ... + sta $2E00,x ; AF3E 9D 00 2E ... + inx ; AF41 E8 . + iny ; AF42 C8 . + dec $0772 ; AF43 CE 72 07 .r. + bne LAF3B ; AF46 D0 F3 .. + inc $0771 ; AF48 EE 71 07 .q. + sec ; AF4B 38 8 + lda $0770 ; AF4C AD 70 07 .p. + sbc #$0A ; AF4F E9 0A .. + sta $0770 ; AF51 8D 70 07 .p. + inc $066C ; AF54 EE 6C 06 .l. + rts ; AF57 60 ` + +; ---------------------------------------------------------------------------- +LAF58: lda work_level_num_bombs ; AF58 AD 8A 07 ... + beq LAF5E ; AF5B F0 01 .. + rts ; AF5D 60 ` + +; ---------------------------------------------------------------------------- +LAF5E: lda #$09 ; AF5E A9 09 .. + sta player_speed ; AF60 8D 24 06 .$. + lda #$00 ; AF63 A9 00 .. + sta playing_level ; AF65 8D 27 06 .'. + ldx #$0C ; AF68 A2 0C .. + stx $066D ; AF6A 8E 6D 06 .m. +LAF6D: lda $0770 ; AF6D AD 70 07 .p. + clc ; AF70 18 . + adc #$0A ; AF71 69 0A i. + sta $0770 ; AF73 8D 70 07 .p. + lda $0772,x ; AF76 BD 72 07 .r. + cmp LAEAF,x ; AF79 DD AF AE ... + beq LAF96 ; AF7C F0 18 .. + lda #$00 ; AF7E A9 00 .. + sta $0681 ; AF80 8D 81 06 ... + jmp LAF92 ; AF83 4C 92 AF L.. + +; ---------------------------------------------------------------------------- +LAF86: lda #$00 ; AF86 A9 00 .. + sta jiffy_timer_1 ; AF88 8D 1A 06 ... +LAF8B: lda jiffy_timer_1 ; AF8B AD 1A 06 ... + cmp #$20 ; AF8E C9 20 . + bne LAF8B ; AF90 D0 F9 .. +LAF92: dex ; AF92 CA . + bne LAF6D ; AF93 D0 D8 .. + rts ; AF95 60 ` + +; ---------------------------------------------------------------------------- +LAF96: lda $0770 ; AF96 AD 70 07 .p. + sta $0686 ; AF99 8D 86 06 ... + lda #$86 ; AF9C A9 86 .. + sta $0681 ; AF9E 8D 81 06 ... + clc ; AFA1 18 . + lda score ; AFA2 AD 00 07 ... + adc #$FA ; AFA5 69 FA i. + sta score ; AFA7 8D 00 07 ... + bcc LAFB4 ; AFAA 90 08 .. + inc score+1 ; AFAC EE 01 07 ... + bne LAFB4 ; AFAF D0 03 .. + inc score+2 ; AFB1 EE 02 07 ... +LAFB4: txa ; AFB4 8A . + pha ; AFB5 48 H + jsr L800C ; AFB6 20 0C 80 .. + lda #$CB ; AFB9 A9 CB .. + sta sfx_ptr ; AFBB 8D 3C 06 .<. + lda #$AF ; AFBE A9 AF .. + sta sfx_ptr+1 ; AFC0 8D 3D 06 .=. + jsr cue_sfx_jv ; AFC3 20 06 80 .. + pla ; AFC6 68 h + tax ; AFC7 AA . + jmp LAF86 ; AFC8 4C 86 AF L.. + +; ---------------------------------------------------------------------------- +; referenced by routine at $AF96 +sfx_afcb: + .byte $01,$A5,$00,$18,$04,$F3,$04,$00 ; AFCB 01 A5 00 18 04 F3 04 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AFD3 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AFDB 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AFE3 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AFEB 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; AFF3 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00 ; AFFB 00 00 00 00 00 ..... +; referenced by routine at $B0C4 +map_b000: + .byte $FE,$33,$9C,$FD,$04,$00,$04,$07 ; B000 FE 33 9C FD 04 00 04 07 .3...... + .byte $06,$24,$07,$02,$6C,$05,$04,$8C ; B008 06 24 07 02 6C 05 04 8C .$..l... + .byte $05,$04,$28,$18,$04,$48,$15,$06 ; B010 05 04 28 18 04 48 15 06 ..(..H.. + .byte $7C,$15,$04,$20,$25,$07,$68,$25 ; B018 7C 15 04 20 25 07 68 25 |.. %.h% + .byte $04,$04,$3B,$05,$28,$3B,$01,$34 ; B020 04 04 3B 05 28 3B 01 34 ..;.(;.4 + .byte $3B,$04,$5C,$45,$08,$8C,$4B,$02 ; B028 3B 04 5C 45 08 8C 4B 02 ;.\E..K. + .byte $04,$55,$06,$38,$4D,$04,$04,$55 ; B030 04 55 06 38 4D 04 04 55 .U.8M..U + .byte $06,$54,$55,$12,$FD,$04,$FF,$58 ; B038 06 54 55 12 FD 04 FF 58 .TU....X + .byte $0A,$05,$1C,$54,$07,$FD,$04,$01 ; B040 0A 05 1C 54 07 FD 04 01 ...T.... + .byte $2C,$08,$06,$3C,$26,$04,$FE,$5F ; B048 2C 08 06 3C 26 04 FE 5F ,..<&.._ + .byte $9C,$FD,$00,$04,$0C,$03,$0E,$3C ; B050 9C FD 00 04 0C 03 0E 3C .......< + .byte $37,$05,$8C,$35,$05,$FE,$C9,$9C ; B058 37 05 8C 35 05 FE C9 9C 7..5.... + .byte $1A,$0A,$06,$5E,$18,$09,$9A,$08 ; B060 1A 0A 06 5E 18 09 9A 08 ...^.... + .byte $0B,$FE,$DA,$9C,$83,$04,$13,$FE ; B068 0B FE DA 9C 83 04 13 FE ........ + .byte $49,$9C ; B070 49 9C I. +LB072: .byte $04 ; B072 04 . +LB073: .byte $02,$01,$24,$02,$01,$44,$02,$01 ; B073 02 01 24 02 01 44 02 01 ..$..D.. + .byte $78,$02,$01,$98,$02,$01,$3C,$12 ; B07B 78 02 01 98 02 01 3C 12 x.....<. + .byte $01,$5C,$12,$01,$7C,$12,$01,$24 ; B083 01 5C 12 01 7C 12 01 24 .\..|..$ + .byte $22,$01,$78,$22,$01,$04,$38,$01 ; B08B 22 01 78 22 01 04 38 01 ".x"..8. + .byte $1C,$46,$01,$78,$42,$01,$04,$52 ; B093 1C 46 01 78 42 01 04 52 .F.xB..R + .byte $01,$58,$52,$01,$98,$52,$01 ; B09B 01 58 52 01 98 52 01 .XR..R. +LB0A2: .byte $FF ; B0A2 FF . +LB0A3: .byte $22,$00,$42,$00,$62,$00,$A2,$00 ; B0A3 22 00 42 00 62 00 A2 00 ".B.b... + .byte $C2,$00,$64,$00,$84,$00,$A4,$00 ; B0AB C2 00 64 00 84 00 A4 00 ..d..... + .byte $46,$00,$A6,$00,$28,$00,$4A,$00 ; B0B3 46 00 A6 00 28 00 4A 00 F...(.J. + .byte $AA,$00,$2C,$00,$8C,$00,$CC,$00 ; B0BB AA 00 2C 00 8C 00 CC 00 ..,..... + .byte $FF ; B0C3 FF . +; ---------------------------------------------------------------------------- +LB0C4: jsr L8036 ; B0C4 20 36 80 6. + lda #$10 ; B0C7 A9 10 .. + sta SAVMSC+1 ; B0C9 85 59 .Y + jsr clear_screen_mem_jv ; B0CB 20 1E 80 .. + lda #$00 ; B0CE A9 00 .. + sta dm_progctr ; B0D0 85 C0 .. + lda #$B0 ; B0D2 A9 B0 .. + sta dm_progctr+1 ; B0D4 85 C1 .. + jsr draw_map_jv ; B0D6 20 00 80 .. + ldx #$07 ; B0D9 A2 07 .. +LB0DB: lda LB119,x ; B0DB BD 19 B1 ... + sta $08FF,x ; B0DE 9D FF 08 ... + dex ; B0E1 CA . + bne LB0DB ; B0E2 D0 F7 .. + lda #$08 ; B0E4 A9 08 .. + sta $AA ; B0E6 85 AA .. +LB0E8: lda RANDOM ; B0E8 AD 0A D2 ... + and #$0F ; B0EB 29 0F ). + sta $AB ; B0ED 85 AB .. + tax ; B0EF AA . + lda $0770,x ; B0F0 BD 70 07 .p. + bne LB0E8 ; B0F3 D0 F3 .. + inc $0770,x ; B0F5 FE 70 07 .p. + txa ; B0F8 8A . + asl a ; B0F9 0A . + clc ; B0FA 18 . + adc $AB ; B0FB 65 AB e. + tay ; B0FD A8 . + lda LB072,y ; B0FE B9 72 B0 .r. + sta $0903 ; B101 8D 03 09 ... + lda LB073,y ; B104 B9 73 B0 .s. + sta $0904 ; B107 8D 04 09 ... + lda #$00 ; B10A A9 00 .. + sta dm_progctr ; B10C 85 C0 .. + lda #$09 ; B10E A9 09 .. + sta dm_progctr+1 ; B110 85 C1 .. + jsr draw_map_jv ; B112 20 00 80 .. + dec $AA ; B115 C6 AA .. + bne LB0E8 ; B117 D0 CF .. +LB119: rts ; B119 60 ` + +; ---------------------------------------------------------------------------- +; dunno what this is for yet +map_b11a: + .byte $FE,$B3,$9C,$00,$00,$01,$FF ; B11A FE B3 9C 00 00 01 FF ....... +; ---------------------------------------------------------------------------- +LB121: lda #$10 ; B121 A9 10 .. + sta SAVMSC+1 ; B123 85 59 .Y + lda #$D9 ; B125 A9 D9 .. + sta dm_progctr ; B127 85 C0 .. + lda #$06 ; B129 A9 06 .. + sta dm_progctr+1 ; B12B 85 C1 .. + jsr draw_map_jv ; B12D 20 00 80 .. + lda #$30 ; B130 A9 30 .0 + sta SAVMSC+1 ; B132 85 59 .Y + lda #$D9 ; B134 A9 D9 .. + sta dm_progctr ; B136 85 C0 .. + jsr draw_map_jv ; B138 20 00 80 .. + lda #$D9 ; B13B A9 D9 .. + sta dm_progctr ; B13D 85 C0 .. + rts ; B13F 60 ` + +; ---------------------------------------------------------------------------- +LB140: lda $0621 ; B140 AD 21 06 .!. + bne LB146 ; B143 D0 01 .. +LB145: rts ; B145 60 ` + +; ---------------------------------------------------------------------------- +LB146: lda $067E ; B146 AD 7E 06 .~. + cmp #$34 ; B149 C9 34 .4 + bcc LB145 ; B14B 90 F8 .. + cmp #$C9 ; B14D C9 C9 .. + bcs LB145 ; B14F B0 F4 .. + lda #$0B ; B151 A9 0B .. + sta $97 ; B153 85 97 .. + lda $067E ; B155 AD 7E 06 .~. + sec ; B158 38 8 + sbc #$33 ; B159 E9 33 .3 + lsr a ; B15B 4A J + lsr a ; B15C 4A J + sta $91 ; B15D 85 91 .. + lda $0683 ; B15F AD 83 06 ... + cmp #$C3 ; B162 C9 C3 .. + bcs LB145 ; B164 B0 DF .. + jsr LB1D2 ; B166 20 D2 B1 .. + sec ; B169 38 8 + sbc #$26 ; B16A E9 26 .& + lsr a ; B16C 4A J + sta $92 ; B16D 85 92 .. + lda #$28 ; B16F A9 28 .( + sta $90 ; B171 85 90 .. + lda #$00 ; B173 A9 00 .. + sta $93 ; B175 85 93 .. + ldx #$08 ; B177 A2 08 .. +LB179: lsr $90 ; B179 46 90 F. + bcc LB180 ; B17B 90 03 .. + clc ; B17D 18 . + adc $92 ; B17E 65 92 e. +LB180: ror a ; B180 6A j + ror $93 ; B181 66 93 f. + dex ; B183 CA . + bne LB179 ; B184 D0 F3 .. + sta $94 ; B186 85 94 .. + clc ; B188 18 . + lda $93 ; B189 A5 93 .. + adc $91 ; B18B 65 91 e. + sta $93 ; B18D 85 93 .. + sta $95 ; B18F 85 95 .. + lda $94 ; B191 A5 94 .. + adc #$10 ; B193 69 10 i. + sta $94 ; B195 85 94 .. + clc ; B197 18 . + lda $94 ; B198 A5 94 .. + adc #$20 ; B19A 69 20 i + sta $96 ; B19C 85 96 .. +LB19E: ldx #$04 ; B19E A2 04 .. + ldy #$00 ; B1A0 A0 00 .. +LB1A2: lda ($93),y ; B1A2 B1 93 .. + sta ($95),y ; B1A4 91 95 .. + iny ; B1A6 C8 . + dex ; B1A7 CA . + bne LB1A2 ; B1A8 D0 F8 .. + clc ; B1AA 18 . + lda $93 ; B1AB A5 93 .. + adc #$28 ; B1AD 69 28 i( + sta $93 ; B1AF 85 93 .. + bcc LB1B5 ; B1B1 90 02 .. + inc $94 ; B1B3 E6 94 .. +LB1B5: clc ; B1B5 18 . + lda $95 ; B1B6 A5 95 .. + adc #$28 ; B1B8 69 28 i( + sta $95 ; B1BA 85 95 .. + bcc LB1C0 ; B1BC 90 02 .. + inc $96 ; B1BE E6 96 .. +LB1C0: lda $93 ; B1C0 A5 93 .. + cmp #$C0 ; B1C2 C9 C0 .. + bne LB1CD ; B1C4 D0 07 .. + lda $94 ; B1C6 A5 94 .. + cmp #$1D ; B1C8 C9 1D .. + bne LB1CD ; B1CA D0 01 .. + rts ; B1CC 60 ` + +; ---------------------------------------------------------------------------- +LB1CD: dec $97 ; B1CD C6 97 .. + bne LB19E ; B1CF D0 CD .. + rts ; B1D1 60 ` + +; ---------------------------------------------------------------------------- +LB1D2: cmp #$26 ; B1D2 C9 26 .& + bcs LB1DE ; B1D4 B0 08 .. + clc ; B1D6 18 . + adc #$02 ; B1D7 69 02 i. + dec $97 ; B1D9 C6 97 .. + jmp LB1D2 ; B1DB 4C D2 B1 L.. + +; ---------------------------------------------------------------------------- +LB1DE: rts ; B1DE 60 ` + +; ---------------------------------------------------------------------------- +; dunno what this is for yet +data_table_b1df: + .byte $00 ; B1DF 00 . +LB1E0: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; B1E0 FE 33 9C FD 04 00 04 05 .3...... + .byte $06,$38,$05,$08,$7C,$05,$06,$24 ; B1E8 06 38 05 08 7C 05 06 24 .8..|..$ + .byte $15,$06,$64,$15,$0E,$04,$2D,$06 ; B1F0 15 06 64 15 0E 04 2D 06 ..d...-. + .byte $38,$35,$0C,$04,$45,$06,$30,$45 ; B1F8 38 35 0C 04 45 06 30 45 85..E.0E + .byte $08,$88,$3C,$05,$04,$55,$08,$38 ; B200 08 88 3C 05 04 55 08 38 ..<..U.8 + .byte $55,$06,$68,$55,$0D,$FD,$04,$01 ; B208 55 06 68 55 0D FD 04 01 U.hU.... + .byte $1C,$2E,$07,$FD,$04,$FF,$64,$45 ; B210 1C 2E 07 FD 04 FF 64 45 ......dE + .byte $09,$FE,$5F,$9C,$FD,$00,$04,$0C ; B218 09 FE 5F 9C FD 00 04 0C .._..... + .byte $01,$0B,$0C,$41,$05,$40,$01,$05 ; B220 01 0B 0C 41 05 40 01 05 ...A.@.. + .byte $40,$31,$05,$8C,$01,$15,$FE,$DA ; B228 40 31 05 8C 01 15 FE DA @1...... + .byte $9C,$66,$30,$04,$FE,$B3,$9C ; B230 9C 66 30 04 FE B3 9C .f0.... +LB237: .byte $04,$02,$01,$38,$02,$01,$7C,$02 ; B237 04 02 01 38 02 01 7C 02 ...8..|. + .byte $01,$38,$12,$01,$64,$12,$01,$98 ; B23F 01 38 12 01 64 12 01 98 .8..d... + .byte $12,$01,$04,$22,$01,$98,$39,$01 ; B247 12 01 04 22 01 98 39 01 ..."..9. + .byte $58,$47,$01,$04,$52,$01,$38,$52 ; B24F 58 47 01 04 52 01 38 52 XG..R.8R + .byte $01,$98,$52,$01,$FF ; B257 01 98 52 01 FF ..R.. +LB25C: .byte $22,$00,$62,$00,$A2,$00,$64,$00 ; B25C 22 00 62 00 A2 00 64 00 ".b...d. + .byte $84,$00,$C4,$00,$26,$00,$C8,$00 ; B264 84 00 C4 00 26 00 C8 00 ....&... + .byte $8A,$00,$2C,$00,$6C,$00,$CC,$00 ; B26C 8A 00 2C 00 6C 00 CC 00 ..,.l... + .byte $FF ; B274 FF . +LB275: .byte $03,$A8,$B2,$0A,$A4,$20,$01,$56 ; B275 03 A8 B2 0A A4 20 01 56 ..... .V + .byte $FF ; B27D FF . +; ---------------------------------------------------------------------------- +LB27E: lda $06F5 ; B27E AD F5 06 ... + sta $066C ; B281 8D 6C 06 .l. + bne LB287 ; B284 D0 01 .. + rts ; B286 60 ` + +; ---------------------------------------------------------------------------- +LB287: inc $0760 ; B287 EE 60 07 .`. + lda $0760 ; B28A AD 60 07 .`. + and #$7F ; B28D 29 7F ). + beq LB292 ; B28F F0 01 .. + rts ; B291 60 ` + +; ---------------------------------------------------------------------------- +LB292: inc $0761 ; B292 EE 61 07 .a. + lda $0761 ; B295 AD 61 07 .a. + and #$07 ; B298 29 07 ). + tax ; B29A AA . + lda LB2D0,x ; B29B BD D0 B2 ... + sta $0680 ; B29E 8D 80 06 ... + lda LB2D8,x ; B2A1 BD D8 B2 ... + sta $0685 ; B2A4 8D 85 06 ... + rts ; B2A7 60 ` + +; ---------------------------------------------------------------------------- +; dunno what this is for yet +data_table_b2a8: + .byte $00,$00,$00,$18,$18,$18,$18,$00 ; B2A8 00 00 00 18 18 18 18 00 ........ + .byte $00,$00,$00,$00,$3C,$24,$24,$24 ; B2B0 00 00 00 00 3C 24 24 24 ....<$$$ + .byte $24,$3C,$00,$00,$00,$7E,$42,$42 ; B2B8 24 3C 00 00 00 7E 42 42 $<...~BB + .byte $42,$42,$42,$42,$7E,$00,$FF,$81 ; B2C0 42 42 42 42 7E 00 FF 81 BBBB~... + .byte $81,$81,$81,$81,$81,$81,$81,$FF ; B2C8 81 81 81 81 81 81 81 FF ........ +LB2D0: .byte $A4,$4C,$52,$70,$86,$86,$A4,$82 ; B2D0 A4 4C 52 70 86 86 A4 82 .LRp.... +LB2D8: .byte $20,$20,$98,$C0,$B4,$80,$68,$40 ; B2D8 20 20 98 C0 B4 80 68 40 ....h@ +; ---------------------------------------------------------------------------- +LB2E0: lda $0619 ; B2E0 AD 19 06 ... + and #$0F ; B2E3 29 0F ). + bne LB2F2 ; B2E5 D0 0B .. + lda $068A ; B2E7 AD 8A 06 ... + and #$03 ; B2EA 29 03 ). + sta $068A ; B2EC 8D 8A 06 ... + inc $068A ; B2EF EE 8A 06 ... +LB2F2: lda $062A ; B2F2 AD 2A 06 .*. + sta PCOLR2 ; B2F5 8D C2 02 ... + lda #$00 ; B2F8 A9 00 .. + jmp L8F79 ; B2FA 4C 79 8F Ly. + +; ---------------------------------------------------------------------------- +LB2FD: lda $0680 ; B2FD AD 80 06 ... + sta $067E ; B300 8D 7E 06 .~. + lda $0685 ; B303 AD 85 06 ... + sta $0683 ; B306 8D 83 06 ... + lda #$19 ; B309 A9 19 .. + sta sfx_ptr ; B30B 8D 3C 06 .<. + lda #$B3 ; B30E A9 B3 .. + sta sfx_ptr+1 ; B310 8D 3D 06 .=. + lda #$07 ; B313 A9 07 .. + jsr cue_sfx_jv ; B315 20 06 80 .. + rts ; B318 60 ` + +; ---------------------------------------------------------------------------- +; referenced by routine at $B2FD +sxf_b319: + .byte $01,$86,$00,$0A,$20,$00,$00 ; B319 01 86 00 0A 20 00 00 .... .. +LB320: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; B320 FE 33 9C FD 04 00 04 05 .3...... + .byte $08,$2C,$07,$15,$84,$05,$06,$1C ; B328 08 2C 07 15 84 05 06 1C .,...... + .byte $15,$03,$48,$15,$0D,$04,$25,$07 ; B330 15 03 48 15 0D 04 25 07 ..H...%. + .byte $30,$2F,$0D,$04,$35,$06,$74,$35 ; B338 30 2F 0D 04 35 06 74 35 0/..5.t5 + .byte $0A,$04,$45,$06,$04,$55,$06,$28 ; B340 0A 04 45 06 04 55 06 28 ..E..U.( + .byte $55,$06,$4C,$55,$06,$84,$50,$06 ; B348 55 06 4C 55 06 84 50 06 U.LU..P. + .byte $FD,$04,$FF,$1C,$34,$05,$70,$55 ; B350 FD 04 FF 1C 34 05 70 55 ....4.pU + .byte $05,$80,$06,$02,$FD,$04,$01,$24 ; B358 05 80 06 02 FD 04 01 24 .......$ + .byte $06,$02,$FE,$5F,$9C,$FD,$00,$04 ; B360 06 02 FE 5F 9C FD 00 04 ..._.... + .byte $0C,$01,$09,$0C,$41,$05,$30,$03 ; B368 0C 01 09 0C 41 05 30 03 ....A.0. + .byte $0B,$54,$2B,$0A,$8C,$01,$0D,$FE ; B370 0B 54 2B 0A 8C 01 0D FE .T+..... + .byte $C9,$9C,$04,$38,$02,$1A,$38,$02 ; B378 C9 9C 04 38 02 1A 38 02 ...8..8. + .byte $33,$32,$07,$74,$38,$05,$FE,$DA ; B380 33 32 07 74 38 05 FE DA 32.t8... + .byte $9C,$6A,$12,$0F,$FE,$B3,$9C ; B388 9C 6A 12 0F FE B3 9C .j..... +LB38F: .byte $04,$02,$01,$3A,$02,$01,$5A,$02 ; B38F 04 02 01 3A 02 01 5A 02 ...:..Z. + .byte $01,$7A,$02,$01,$98,$02,$01,$20 ; B397 01 7A 02 01 98 02 01 20 .z..... + .byte $12,$01,$5A,$12,$01,$04,$22,$01 ; B39F 12 01 5A 12 01 04 22 01 ..Z...". + .byte $3A,$22,$01,$04,$32,$01,$78,$32 ; B3A7 3A 22 01 04 32 01 78 32 :"..2.x2 + .byte $01,$98,$32,$01,$04,$52,$01,$38 ; B3AF 01 98 32 01 04 52 01 38 ..2..R.8 + .byte $52,$01,$60,$52,$01,$FF ; B3B7 52 01 60 52 01 FF R.`R.. +LB3BD: .byte $22,$10,$62,$20,$82,$30,$A2,$40 ; B3BD 22 10 62 20 82 30 A2 40 ".b .0.@ + .byte $C2,$50,$44,$60,$84,$70,$26,$80 ; B3C5 C2 50 44 60 84 70 26 80 .PD`.p&. + .byte $66,$90,$28,$A0,$A8,$B0,$C8,$C0 ; B3CD 66 90 28 A0 A8 B0 C8 C0 f.(..... + .byte $2C,$D0,$6C,$E0,$8C,$F0,$FF ; B3D5 2C D0 6C E0 8C F0 FF ,.l.... +LB3DC: .byte $00,$00,$FC,$B3,$06,$B4,$10,$B4 ; B3DC 00 00 FC B3 06 B4 10 B4 ........ + .byte $06,$B4,$10,$B4,$1A,$B4,$24,$B4 ; B3E4 06 B4 10 B4 1A B4 24 B4 ......$. + .byte $2E,$B4,$38,$B4,$2E,$B4,$38,$B4 ; B3EC 2E B4 38 B4 2E B4 38 B4 ..8...8. + .byte $FC,$B3,$24,$B4,$1A,$B4,$42,$B4 ; B3F4 FC B3 24 B4 1A B4 42 B4 ..$...B. + .byte $FE,$49,$9C,$FD,$04,$00,$48,$15 ; B3FC FE 49 9C FD 04 00 48 15 .I....H. + .byte $03,$FF,$FE,$49,$9C,$FD,$04,$00 ; B404 03 FF FE 49 9C FD 04 00 ...I.... + .byte $46,$07,$03,$FF,$FE,$49,$9C,$FD ; B40C 46 07 03 FF FE 49 9C FD F....I.. + .byte $04,$00,$6A,$07,$03,$FF,$FE,$49 ; B414 04 00 6A 07 03 FF FE 49 ..j....I + .byte $9C,$FD,$04,$00,$0A,$35,$03,$FF ; B41C 9C FD 04 00 0A 35 03 FF .....5.. + .byte $FE,$49,$9C,$FD,$04,$00,$3E,$2F ; B424 FE 49 9C FD 04 00 3E 2F .I....>/ + .byte $04,$FF,$FE,$49,$9C,$FD,$04,$00 ; B42C 04 FF FE 49 9C FD 04 00 ...I.... + .byte $7C,$35,$04,$FF,$FE,$89,$9C,$FD ; B434 7C 35 04 FF FE 89 9C FD |5...... + .byte $00,$04,$54,$3F,$04,$FF,$FE,$89 ; B43C 00 04 54 3F 04 FF FE 89 ..T?.... + .byte $9C,$FD,$00,$04,$8C,$1D,$04,$FF ; B444 9C FD 00 04 8C 1D 04 FF ........ +; ---------------------------------------------------------------------------- +LB44C: lda #$01 ; B44C A9 01 .. + sta $0770 ; B44E 8D 70 07 .p. + lda #$00 ; B451 A9 00 .. + sta $0771 ; B453 8D 71 07 .q. + rts ; B456 60 ` + +; ---------------------------------------------------------------------------- +LB457: lda $0623 ; B457 AD 23 06 .#. + cmp #$02 ; B45A C9 02 .. + bne LB46A ; B45C D0 0C .. + lda #$00 ; B45E A9 00 .. + sta $0770 ; B460 8D 70 07 .p. + sta $0771 ; B463 8D 71 07 .q. + sta $0681 ; B466 8D 81 06 ... + rts ; B469 60 ` + +; ---------------------------------------------------------------------------- +LB46A: lda $0622 ; B46A AD 22 06 .". + bne LB470 ; B46D D0 01 .. +LB46F: rts ; B46F 60 ` + +; ---------------------------------------------------------------------------- +LB470: lda $0770 ; B470 AD 70 07 .p. + beq LB46F ; B473 F0 FA .. + cmp #$09 ; B475 C9 09 .. + beq LB49F ; B477 F0 26 .& + sta $066C ; B479 8D 6C 06 .l. + sta $068A ; B47C 8D 8A 06 ... + inc $0770 ; B47F EE 70 07 .p. + lda $06DC ; B482 AD DC 06 ... + clc ; B485 18 . + adc #$30 ; B486 69 30 i0 + sta $0680 ; B488 8D 80 06 ... + lda $06DD ; B48B AD DD 06 ... + asl a ; B48E 0A . + clc ; B48F 18 . + adc #$20 ; B490 69 20 i + sta $0685 ; B492 8D 85 06 ... + lda $0770 ; B495 AD 70 07 .p. + cmp #$09 ; B498 C9 09 .. + bcc LB46F ; B49A 90 D3 .. + inc $0771 ; B49C EE 71 07 .q. +LB49F: lda $0771 ; B49F AD 71 07 .q. + beq LB46F ; B4A2 F0 CB .. + cmp #$05 ; B4A4 C9 05 .. + beq LB4C1 ; B4A6 F0 19 .. + clc ; B4A8 18 . + adc #$04 ; B4A9 69 04 i. + sta $068B ; B4AB 8D 8B 06 ... + inc $0771 ; B4AE EE 71 07 .q. + lda $0680 ; B4B1 AD 80 06 ... + sta $0681 ; B4B4 8D 81 06 ... + lda $0685 ; B4B7 AD 85 06 ... + sta $0686 ; B4BA 8D 86 06 ... + sta $066D ; B4BD 8D 6D 06 .m. + rts ; B4C0 60 ` + +; ---------------------------------------------------------------------------- +LB4C1: lda $068B ; B4C1 AD 8B 06 ... + and #$03 ; B4C4 29 03 ). + clc ; B4C6 18 . + adc #$04 ; B4C7 69 04 i. + sta $068B ; B4C9 8D 8B 06 ... + inc $068B ; B4CC EE 8B 06 ... + cmp #$07 ; B4CF C9 07 .. + bne LB4E2 ; B4D1 D0 0F .. +cue_woop_sound: + lda #$64 ; B4D3 A9 64 .d + sta sfx_slot_tempo ; B4D5 8D 3E 06 .>. + lda #$B5 ; B4D8 A9 B5 .. + sta sfx_slot_timer ; B4DA 8D 3F 06 .?. + lda #$03 ; B4DD A9 03 .. + jsr L8003 ; B4DF 20 03 80 .. +LB4E2: ldy #$01 ; B4E2 A0 01 .. + lda $0681 ; B4E4 AD 81 06 ... + cmp $067E ; B4E7 CD 7E 06 .~. + bcc LB4EE ; B4EA 90 02 .. + ldy #$FF ; B4EC A0 FF .. +LB4EE: sty $A0 ; B4EE 84 A0 .. + clc ; B4F0 18 . + adc $A0 ; B4F1 65 A0 e. + sta $0681 ; B4F3 8D 81 06 ... + ldy #$01 ; B4F6 A0 01 .. + lda $0686 ; B4F8 AD 86 06 ... + cmp $0683 ; B4FB CD 83 06 ... + bcc LB502 ; B4FE 90 02 .. + ldy #$FF ; B500 A0 FF .. +LB502: sty $A0 ; B502 84 A0 .. + clc ; B504 18 . + adc $A0 ; B505 65 A0 e. + sta $0686 ; B507 8D 86 06 ... + rts ; B50A 60 ` + +; ---------------------------------------------------------------------------- +; dunno what this is for yet +data_table_b50b: + .byte $03,$1C,$B5,$08,$00,$00,$01,$56 ; B50B 03 1C B5 08 00 00 01 56 .......V + .byte $04,$1C,$B5,$08,$00,$00,$05,$1A ; B513 04 1C B5 08 00 00 05 1A ........ + .byte $FF,$00,$00,$18,$18,$24,$24,$18 ; B51B FF 00 00 18 18 24 24 18 .....$$. + .byte $18,$00,$00,$42,$42,$42,$24,$18 ; B523 18 00 00 42 42 42 24 18 ...BBB$. + .byte $18,$00,$00,$00,$00,$66,$A5,$18 ; B52B 18 00 00 00 00 66 A5 18 .....f.. + .byte $18,$00,$00,$00,$00,$00,$00,$3C ; B533 18 00 00 00 00 00 00 3C .......< + .byte $DB,$00,$00,$24,$18,$18,$24,$00 ; B53B DB 00 00 24 18 18 24 00 ...$..$. + .byte $00,$00,$08,$24,$58,$1A,$24,$10 ; B543 00 00 08 24 58 1A 24 10 ...$X.$. + .byte $00,$81,$42,$24,$18,$18,$24,$42 ; B54B 00 81 42 24 18 18 24 42 ..B$..$B + .byte $81,$04,$42,$A4,$18,$18,$25,$42 ; B553 81 04 42 A4 18 18 25 42 ..B...%B + .byte $20,$00,$00,$18,$18,$24,$24,$18 ; B55B 20 00 00 18 18 24 24 18 ....$$. + .byte $18 ; B563 18 . +sfx_woop: + .byte $01,$A2,$00,$F0,$01,$01,$A4,$00 ; B564 01 A2 00 F0 01 01 A4 00 ........ + .byte $DC,$01,$01,$A6,$00,$C8,$02,$01 ; B56C DC 01 01 A6 00 C8 02 01 ........ + .byte $A4,$DC,$01,$01,$A2,$F0,$01,$00 ; B574 A4 DC 01 01 A2 F0 01 00 ........ +; ---------------------------------------------------------------------------- +LB57C: lda #$00 ; B57C A9 00 .. + jmp L8F76 ; B57E 4C 76 8F Lv. + +; ---------------------------------------------------------------------------- +LB581: lda $062A ; B581 AD 2A 06 .*. + sta PCOLR3 ; B584 8D C3 02 ... + rts ; B587 60 ` + +; ---------------------------------------------------------------------------- +zero_filler_8588: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B588 00 00 00 00 00 00 00 00 ........ +LB590: .byte $FE,$33,$9C,$FD,$04,$00,$04,$05 ; B590 FE 33 9C FD 04 00 04 05 .3...... + .byte $08,$3C,$05,$0A,$7C,$05,$08,$04 ; B598 08 3C 05 0A 7C 05 08 04 .<..|... + .byte $25,$26,$04,$43,$26,$04,$55,$06 ; B5A0 25 26 04 43 26 04 55 06 %&.C&.U. + .byte $3C,$55,$0A,$84,$55,$06,$04,$43 ; B5A8 3C 55 0A 84 55 06 04 43 <U..U..C + .byte $06,$FE,$5F,$9C,$FD,$00,$04,$0C ; B5B0 06 FE 5F 9C FD 00 04 0C .._..... + .byte $01,$09,$4C,$01,$09,$8C,$01,$09 ; B5B8 01 09 4C 01 09 8C 01 09 ..L..... + .byte $2A,$1F,$09,$6A,$1F,$09,$0C,$3F ; B5C0 2A 1F 09 6A 1F 09 0C 3F *..j...? + .byte $05,$4C,$3F,$05,$8C,$3F,$05,$FE ; B5C8 05 4C 3F 05 8C 3F 05 FE .L?..?.. + .byte $B3,$9C ; B5D0 B3 9C .. +LB5D2: .byte $04,$02,$01,$20,$02,$01,$3C,$02 ; B5D2 04 02 01 20 02 01 3C 02 ... ..<. + .byte $01,$60,$02,$01,$7C,$02,$01,$98 ; B5DA 01 60 02 01 7C 02 01 98 .`..|... + .byte $02,$01,$04,$22,$01,$98,$22,$01 ; B5E2 02 01 04 22 01 98 22 01 ..."..". + .byte $3C,$36,$01,$60,$36,$01,$04,$52 ; B5EA 3C 36 01 60 36 01 04 52 <6.`6..R + .byte $01,$3C,$52,$01,$60,$52,$01,$98 ; B5F2 01 3C 52 01 60 52 01 98 .<R.`R.. + .byte $52,$01,$FF ; B5FA 52 01 FF R.. +LB5FD: .byte $22,$10,$42,$20,$62,$00,$82,$00 ; B5FD 22 10 42 20 62 00 82 00 ".B b... + .byte $A2,$30,$C2,$40,$26,$00,$C6,$00 ; B605 A2 30 C2 40 26 00 C6 00 .0.@&... + .byte $68,$00,$88,$00,$2C,$00,$6C,$00 ; B60D 68 00 88 00 2C 00 6C 00 h...,.l. + .byte $8C,$00,$CC,$00,$FF ; B615 8C 00 CC 00 FF ..... +LB61A: .byte $00,$00,$24,$B6,$2E,$B6,$3E,$B6 ; B61A 00 00 24 B6 2E B6 3E B6 ..$...>. + .byte $4E,$B6,$FE,$49,$9C,$FD,$04,$00 ; B622 4E B6 FE 49 9C FD 04 00 N..I.... + .byte $78,$43,$02,$FF,$FE,$49,$9C,$FD ; B62A 78 43 02 FF FE 49 9C FD xC...I.. + .byte $04,$00,$3C,$25,$02,$FD,$04,$00 ; B632 04 00 3C 25 02 FD 04 00 ..<%.... + .byte $1C,$25,$02,$FF,$FE,$49,$9C,$FD ; B63A 1C 25 02 FF FE 49 9C FD .%...I.. + .byte $04,$00,$7C,$25,$02,$FD,$04,$00 ; B642 04 00 7C 25 02 FD 04 00 ..|%.... + .byte $5C,$25,$02,$FF,$FE,$49,$9C,$FD ; B64A 5C 25 02 FF FE 49 9C FD \%...I.. + .byte $04,$00,$5C,$43,$02,$FF ; B652 04 00 5C 43 02 FF ..\C.. +LB658: .byte $00,$71,$B6,$08,$40,$02,$01,$08 ; B658 00 71 B6 08 40 02 01 08 .q..@... + .byte $03,$71,$B6,$08,$14,$40,$02,$08 ; B660 03 71 B6 08 14 40 02 08 .q...@.. + .byte $04,$71,$B6,$08,$00,$80,$03,$08 ; B668 04 71 B6 08 00 80 03 08 .q...... + .byte $FF,$47,$EF,$3E,$1E,$1E,$0E,$02 ; B670 FF 47 EF 3E 1E 1E 0E 02 .G.>.... + .byte $05,$40,$EE,$3F,$1E,$1C,$0C,$02 ; B678 05 40 EE 3F 1E 1C 0C 02 .@.?.... + .byte $05,$40,$E0,$38,$1C,$1E,$0D,$02 ; B680 05 40 E0 38 1C 1E 0D 02 .@.8.... + .byte $05,$40,$EE,$3F,$1E,$1C,$0C,$02 ; B688 05 40 EE 3F 1E 1C 0C 02 .@.?.... + .byte $05 ; B690 05 . +LB691: .byte $AD,$21,$06,$D0,$01,$60 ; B691 AD 21 06 D0 01 60 .!...` +; ---------------------------------------------------------------------------- + inc $067E ; B697 EE 7E 06 .~. +LB69A: rts ; B69A 60 ` + +; ---------------------------------------------------------------------------- +LB69B: lda player_speed ; B69B AD 24 06 .$. + cmp #$09 ; B69E C9 09 .. + bcs LB6A9 ; B6A0 B0 07 .. + lda $0623 ; B6A2 AD 23 06 .#. + cmp #$02 ; B6A5 C9 02 .. + bne LB6BA ; B6A7 D0 11 .. +LB6A9: lda $0768 ; B6A9 AD 68 07 .h. + bne LB69A ; B6AC D0 EC .. + inc $0768 ; B6AE EE 68 07 .h. + lda #$00 ; B6B1 A9 00 .. + sta AUDC1 ; B6B3 8D 01 D2 ... + sta AUDF1 ; B6B6 8D 00 D2 ... + rts ; B6B9 60 ` + +; ---------------------------------------------------------------------------- +LB6BA: lda $076F ; B6BA AD 6F 07 .o. + bne LB6DC ; B6BD D0 1D .. + lda #$81 ; B6BF A9 81 .. + sta AUDC1 ; B6C1 8D 01 D2 ... + sta $076C ; B6C4 8D 6C 07 .l. + lda #$00 ; B6C7 A9 00 .. + sta jiffy_timer_2 ; B6C9 8D 1B 06 ... + lda #$04 ; B6CC A9 04 .. + sta $076E ; B6CE 8D 6E 07 .n. + sta $076F ; B6D1 8D 6F 07 .o. + lda RANDOM ; B6D4 AD 0A D2 ... + and #$3F ; B6D7 29 3F )? + sta $076D ; B6D9 8D 6D 07 .m. +LB6DC: lda #$10 ; B6DC A9 10 .. + sta AUDF1 ; B6DE 8D 00 D2 ... + lda jiffy_timer_2 ; B6E1 AD 1B 06 ... + cmp $076D ; B6E4 CD 6D 07 .m. + bne LB702 ; B6E7 D0 19 .. + lda $076E ; B6E9 AD 6E 07 .n. + beq LB6F7 ; B6EC F0 09 .. + inc $076C ; B6EE EE 6C 07 .l. + dec $076E ; B6F1 CE 6E 07 .n. + jmp LB6FD ; B6F4 4C FD B6 L.. + +; ---------------------------------------------------------------------------- +LB6F7: dec $076C ; B6F7 CE 6C 07 .l. + dec $076F ; B6FA CE 6F 07 .o. +LB6FD: lda #$00 ; B6FD A9 00 .. + sta jiffy_timer_2 ; B6FF 8D 1B 06 ... +LB702: lda $076C ; B702 AD 6C 07 .l. + sta AUDC1 ; B705 8D 01 D2 ... + rts ; B708 60 ` + +; ---------------------------------------------------------------------------- +LB709: lda $06F5 ; B709 AD F5 06 ... + cmp #$01 ; B70C C9 01 .. + bne LB71C ; B70E D0 0C .. + inc $0669 ; B710 EE 69 06 .i. + inc $066C ; B713 EE 6C 06 .l. + inc $066D ; B716 EE 6D 06 .m. + inc $06F5 ; B719 EE F5 06 ... +LB71C: lda $0622 ; B71C AD 22 06 .". + bne LB722 ; B71F D0 01 .. +LB721: rts ; B721 60 ` + +; ---------------------------------------------------------------------------- +LB722: ldx #$FF ; B722 A2 FF .. +LB724: inx ; B724 E8 . + cpx #$01 ; B725 E0 01 .. + beq LB724 ; B727 F0 FB .. + cpx #$02 ; B729 E0 02 .. + beq LB724 ; B72B F0 F7 .. + cpx #$05 ; B72D E0 05 .. + beq LB721 ; B72F F0 F0 .. + lda $076C ; B731 AD 6C 07 .l. + and #$0F ; B734 29 0F ). + tay ; B736 A8 . + clc ; B737 18 . + lda $067D,x ; B738 BD 7D 06 .}. + adc wind_table_1,y ; B73B 79 6B B7 yk. + sta $067D,x ; B73E 9D 7D 06 .}. + clc ; B741 18 . + lda $0682,x ; B742 BD 82 06 ... + adc wind_table_2,y ; B745 79 71 B7 yq. + cmp #$C6 ; B748 C9 C6 .. + bcs LB75D ; B74A B0 11 .. + sta $0682,x ; B74C 9D 82 06 ... + lda $0687,x ; B74F BD 87 06 ... + and #$03 ; B752 29 03 ). + sta $0687,x ; B754 9D 87 06 ... + inc $0687,x ; B757 FE 87 06 ... + jmp LB724 ; B75A 4C 24 B7 L$. + +; ---------------------------------------------------------------------------- +LB75D: lda #$02 ; B75D A9 02 .. + sta $067D,x ; B75F 9D 7D 06 .}. + lda RANDOM ; B762 AD 0A D2 ... + sta $0682,x ; B765 9D 82 06 ... + jmp LB724 ; B768 4C 24 B7 L$. + +; ---------------------------------------------------------------------------- +; used in level11 +wind_table_1: + .byte $01,$02,$03,$03,$03,$03 ; B76B 01 02 03 03 03 03 ...... +wind_table_2: + .byte $02,$01,$00,$00,$00,$00,$00,$00 ; B771 02 01 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B779 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B781 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B789 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B791 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B799 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B7A1 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B7A9 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B7B1 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00 ; B7B9 00 00 00 00 00 00 00 ....... +; ---------------------------------------------------------------------------- +LB7C0: lda score+2 ; B7C0 AD 02 07 ... + cmp #$0F ; B7C3 C9 0F .. + bcc LB7EE ; B7C5 90 27 .' + lda score+1 ; B7C7 AD 01 07 ... + cmp #$42 ; B7CA C9 42 .B + bcc LB7EE ; B7CC 90 20 . + lda score ; B7CE AD 00 07 ... + cmp #$40 ; B7D1 C9 40 .@ + bcc LB7EE ; B7D3 90 19 .. + sec ; B7D5 38 8 + lda score ; B7D6 AD 00 07 ... + sbc #$40 ; B7D9 E9 40 .@ + sta score ; B7DB 8D 00 07 ... + lda score+1 ; B7DE AD 01 07 ... + sbc #$42 ; B7E1 E9 42 .B + sta score+1 ; B7E3 8D 01 07 ... + lda score+2 ; B7E6 AD 02 07 ... + sbc #$0F ; B7E9 E9 0F .. + sta score+2 ; B7EB 8D 02 07 ... +LB7EE: jmp L8668 ; B7EE 4C 68 86 Lh. + +; ---------------------------------------------------------------------------- + brk ; B7F1 00 . + brk ; B7F2 00 . + brk ; B7F3 00 . + brk ; B7F4 00 . + brk ; B7F5 00 . + brk ; B7F6 00 . + brk ; B7F7 00 . + brk ; B7F8 00 . + brk ; B7F9 00 . + brk ; B7FA 00 . + brk ; B7FB 00 . + brk ; B7FC 00 . + brk ; B7FD 00 . + brk ; B7FE 00 . + brk ; B7FF 00 . +end_of_level_bonus: + lda level ; B800 AD F6 06 ... + asl a ; B803 0A . + tay ; B804 A8 . + lda mul_25_table,y ; B805 B9 A7 B8 ... + sta $A4 ; B808 85 A4 .. + lda mul_25_table+1,y ; B80A B9 A8 B8 ... + sta $A5 ; B80D 85 A5 .. + lda lives ; B80F AD 0A 07 ... + sta $A6 ; B812 85 A6 .. + inc $A6 ; B814 E6 A6 .. + lda $A4 ; B816 A5 A4 .. + sta $D0 ; B818 85 D0 .. + lda $A5 ; B81A A5 A5 .. + sta $D1 ; B81C 85 D1 .. + lda #$00 ; B81E A9 00 .. + sta work_level_time_bonus ; B820 8D 91 07 ... + sta $D2 ; B823 85 D2 .. + sta work_level_time_bonus+1 ; B825 8D 92 07 ... + lda #$E9 ; B828 A9 E9 .. + sta $D3 ; B82A 85 D3 .. + lda #$3D ; B82C A9 3D .= + sta $D4 ; B82E 85 D4 .. + jsr xxx_level_something_jv ; B830 20 09 80 .. + lda #$78 ; B833 A9 78 .x + sta $3DE9 ; B835 8D E9 3D ..= + jsr L800F ; B838 20 0F 80 .. +add_life_bonus: + clc ; B83B 18 . + lda score ; B83C AD 00 07 ... + adc $A4 ; B83F 65 A4 e. + sta score ; B841 8D 00 07 ... + lda score+1 ; B844 AD 01 07 ... + adc $A5 ; B847 65 A5 e. + sta score+1 ; B849 8D 01 07 ... + bcc LB851 ; B84C 90 03 .. + inc score+2 ; B84E EE 02 07 ... +LB851: clc ; B851 18 . + lda work_level_time_bonus ; B852 AD 91 07 ... + adc $A4 ; B855 65 A4 e. + sta work_level_time_bonus ; B857 8D 91 07 ... + lda work_level_time_bonus+1 ; B85A AD 92 07 ... + adc $A5 ; B85D 65 A5 e. + sta work_level_time_bonus+1 ; B85F 8D 92 07 ... + jsr L800C ; B862 20 0C 80 .. + jsr L800F ; B865 20 0F 80 .. +; play once per life +play_life_bonus_sfx: + lda #$96 ; B868 A9 96 .. + sta sfx_ptr ; B86A 8D 3C 06 .<. + lda #$B8 ; B86D A9 B8 .. + sta sfx_ptr+1 ; B86F 8D 3D 06 .=. + jsr cue_sfx_jv ; B872 20 06 80 .. +LB875: lda sfx_slot_duration ; B875 AD 46 06 .F. + ora $0644 ; B878 0D 44 06 .D. + bne LB875 ; B87B D0 F8 .. + dec $A6 ; B87D C6 A6 .. + bne add_life_bonus ; B87F D0 BA .. + sta jiffy_timer_1 ; B881 8D 1A 06 ... +LB884: lda jiffy_timer_1 ; B884 AD 1A 06 ... + cmp #$20 ; B887 C9 20 . + bne LB884 ; B889 D0 F9 .. + lda randomizer_mode ; B88B AD F3 06 ... + bne LB893 ; B88E D0 03 .. + jmp L8DA0 ; B890 4C A0 8D L.. + +; ---------------------------------------------------------------------------- +LB893: jmp afterlife ; B893 4C 00 96 L.. + +; ---------------------------------------------------------------------------- +; played when adding bonus per life at end of level +sfx_add_life_bonus: + .byte $01,$E4,$00,$18,$02,$3C,$02,$79 ; B896 01 E4 00 18 02 3C 02 79 .....<.y + .byte $02,$F3,$02,$01,$A0,$00,$0A,$14 ; B89E 02 F3 02 01 A0 00 0A 14 ........ + .byte $00 ; B8A6 00 . +; ---------------------------------------------------------------------------- +; multiply by 25 +mul_25_table: + .word $0019,$0032,$004B,$0064 ; B8A7 19 00 32 00 4B 00 64 00 ..2.K.d. + .word $007D,$0096,$00AF,$00C8 ; B8AF 7D 00 96 00 AF 00 C8 00 }....... + .word $00E1,$00FA,$0113,$012C ; B8B7 E1 00 FA 00 13 01 2C 01 ......,. +; ---------------------------------------------------------------------------- +; all zeroes, filler? +zero_filler_b8bf: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8BF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8C7 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8CF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8D7 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8DF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8E7 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8EF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8F7 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B8FF 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B907 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B90F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B917 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B91F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B927 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B92F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B937 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B93F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B947 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B94F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B957 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; B95F 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00 ; B967 00 00 00 00 .... +; ---------------------------------------------------------------------------- +LB96B: lda #$00 ; B96B A9 00 .. + sta jiffy_timer_1 ; B96D 8D 1A 06 ... +LB970: lda jiffy_timer_1 ; B970 AD 1A 06 ... + cmp #$60 ; B973 C9 60 .` + bne LB970 ; B975 D0 F9 .. + lda #$00 ; B977 A9 00 .. + sta FR1 ; B979 85 E0 .. + lda #$00 ; B97B A9 00 .. + sta $06AB ; B97D 8D AB 06 ... + sta $067D ; B980 8D 7D 06 .}. + sta $0681 ; B983 8D 81 06 ... + sta $067E ; B986 8D 7E 06 .~. + sta $0680 ; B989 8D 80 06 ... + lda #$A0 ; B98C A9 A0 .. + sta FR1+1 ; B98E 85 E1 .. + lda #$00 ; B990 A9 00 .. + sta FR1+2 ; B992 85 E2 .. + jsr clear_screen_mem_jv ; B994 20 1E 80 .. + jsr setup_gameboard_dlist_jv ; B997 20 15 80 .. + nop ; B99A EA . + nop ; B99B EA . + nop ; B99C EA . +LB99D: ldy #$16 ; B99D A0 16 .. + lda (FR1),y ; B99F B1 E0 .. + sta dm_progctr ; B9A1 85 C0 .. + iny ; B9A3 C8 . + lda (FR1),y ; B9A4 B1 E0 .. + sta dm_progctr+1 ; B9A6 85 C1 .. + ldy FR1+2 ; B9A8 A4 E2 .. + ldx #$00 ; B9AA A2 00 .. +LB9AC: lda level_names,y ; B9AC B9 00 BB ... + sec ; B9AF 38 8 + sbc #$20 ; B9B0 E9 20 . + sta $3DE8,x ; B9B2 9D E8 3D ..= + iny ; B9B5 C8 . + inx ; B9B6 E8 . + cpx #$14 ; B9B7 E0 14 .. + bne LB9AC ; B9B9 D0 F1 .. + jsr LB9EC ; B9BB 20 EC B9 .. + lda #$00 ; B9BE A9 00 .. + sta jiffy_timer_1 ; B9C0 8D 1A 06 ... + jsr draw_map_jv ; B9C3 20 00 80 .. +LB9C6: lda jiffy_timer_1 ; B9C6 AD 1A 06 ... + cmp #$40 ; B9C9 C9 40 .@ + bne LB9C6 ; B9CB D0 F9 .. + jsr clear_screen_mem_jv ; B9CD 20 1E 80 .. + clc ; B9D0 18 . + lda FR1+2 ; B9D1 A5 E2 .. + adc #$14 ; B9D3 69 14 i. + sta FR1+2 ; B9D5 85 E2 .. + cmp #$F0 ; B9D7 C9 F0 .. + bne LB9DE ; B9D9 D0 03 .. + jmp reinit_game ; B9DB 4C 0C 90 L.. + +; ---------------------------------------------------------------------------- +LB9DE: clc ; B9DE 18 . + lda FR1 ; B9DF A5 E0 .. + adc #$40 ; B9E1 69 40 i@ + sta FR1 ; B9E3 85 E0 .. + bcc LB99D ; B9E5 90 B6 .. + inc FR1+1 ; B9E7 E6 E1 .. + jmp LB99D ; B9E9 4C 9D B9 L.. + +; ---------------------------------------------------------------------------- +LB9EC: ldy #$2F ; B9EC A0 2F ./ + lda (FR1),y ; B9EE B1 E0 .. + sta COLOR0 ; B9F0 8D C4 02 ... + iny ; B9F3 C8 . + lda (FR1),y ; B9F4 B1 E0 .. + sta COLOR1 ; B9F6 8D C5 02 ... + iny ; B9F9 C8 . + lda (FR1),y ; B9FA B1 E0 .. + sta COLOR2 ; B9FC 8D C6 02 ... + rts ; B9FF 60 ` + +; ---------------------------------------------------------------------------- +LBA00: lda #$40 ; BA00 A9 40 .@ + sta NMIEN ; BA02 8D 0E D4 ... + lda #$00 ; BA05 A9 00 .. + sta COLOR3 ; BA07 8D C7 02 ... + sta COLOR0 ; BA0A 8D C4 02 ... + sta COLOR1 ; BA0D 8D C5 02 ... + sta COLOR2 ; BA10 8D C6 02 ... + lda #$30 ; BA13 A9 30 .0 + sta SAVMSC+1 ; BA15 85 59 .Y + jsr clear_screen_mem_jv ; BA17 20 1E 80 .. + lda cur_level_map0 ; BA1A AD D6 07 ... + sta dm_progctr ; BA1D 85 C0 .. + lda cur_level_map0+1 ; BA1F AD D7 07 ... + sta dm_progctr+1 ; BA22 85 C1 .. + jsr draw_map_jv ; BA24 20 00 80 .. + lda #$30 ; BA27 A9 30 .0 + sta SAVMSC+1 ; BA29 85 59 .Y + lda #$00 ; BA2B A9 00 .. + sta $AA ; BA2D 85 AA .. + sta $06AB ; BA2F 8D AB 06 ... + sta COLOR4 ; BA32 8D C8 02 ... + jsr setup_gameboard_dlist_jv ; BA35 20 15 80 .. + lda level ; BA38 AD F6 06 ... + tay ; BA3B A8 . + lda level_name_hscrol_table,y ; BA3C B9 F0 BB ... + sta HSCROL ; BA3F 8D 04 D4 ... + lda #$16 ; BA42 A9 16 .. + sta $085E ; BA44 8D 5E 08 .^. + sta $08DF ; BA47 8D DF 08 ... + lda level ; BA4A AD F6 06 ... + pha ; BA4D 48 H + asl a ; BA4E 0A . + asl a ; BA4F 0A . + asl a ; BA50 0A . + asl a ; BA51 0A . + sta dm_progctr ; BA52 85 C0 .. + pla ; BA54 68 h + asl a ; BA55 0A . + asl a ; BA56 0A . + clc ; BA57 18 . + adc dm_progctr ; BA58 65 C0 e. + tay ; BA5A A8 . + ldx #$00 ; BA5B A2 00 .. +; copy level name into screen RAM +show_level_name: + lda level_names,y ; BA5D B9 00 BB ... + sec ; BA60 38 8 + sbc #$20 ; BA61 E9 20 . + sta $3DEA,x ; BA63 9D EA 3D ..= + inx ; BA66 E8 . + iny ; BA67 C8 . + cpx #$14 ; BA68 E0 14 .. + bne show_level_name ; BA6A D0 F1 .. + lda #$08 ; BA6C A9 08 .. + jsr cue_music_jv ; BA6E 20 18 80 .. +; level is already drawn with all color regs set to black. for each color reg, wait 1 sec before turning it visible. this syncs up with the music because the music was written to sync with this actually +sync_to_music: + jsr wait_1_sec ; BA71 20 9E BA .. + lda cur_level_offs_46+3 ; BA74 AD F1 07 ... + sta COLOR2 ; BA77 8D C6 02 ... + jsr wait_1_sec ; BA7A 20 9E BA .. + lda cur_level_offs_46+2 ; BA7D AD F0 07 ... + sta COLOR1 ; BA80 8D C5 02 ... + jsr wait_1_sec ; BA83 20 9E BA .. + lda cur_level_offs_46+1 ; BA86 AD EF 07 ... + sta COLOR0 ; BA89 8D C4 02 ... + jsr wait_1_sec ; BA8C 20 9E BA .. + lda #$00 ; BA8F A9 00 .. + jsr wait_1_sec ; BA91 20 9E BA .. + jsr enable_joystick_jv ; BA94 20 1B 80 .. + lda #$00 ; BA97 A9 00 .. + tay ; BA99 A8 . + jsr wait_1_sec ; BA9A 20 9E BA .. + rts ; BA9D 60 ` + +; ---------------------------------------------------------------------------- +; actually 64 jiffies, 1.067S ntsc, 1.28s pal +wait_1_sec: + lda #$00 ; BA9E A9 00 .. + sta jiffy_timer_1 ; BAA0 8D 1A 06 ... +keep_waiting: + lda jiffy_timer_1 ; BAA3 AD 1A 06 ... + cmp #$40 ; BAA6 C9 40 .@ + bne keep_waiting ; BAA8 D0 F9 .. + rts ; BAAA 60 ` + +; ---------------------------------------------------------------------------- +; filler? +zero_filler_baab: + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; BAAB 00 00 00 00 00 00 00 00 ........ + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; BAB3 00 00 00 00 00 00 00 00 ........ + .byte $00 ; BABB 00 . +; level intro music, melody +sfx15: .byte $01,$A5,$02,$3C,$10,$2F,$10,$35 ; BABC 01 A5 02 3C 10 2F 10 35 ...<./.5 + .byte $10,$2D,$10,$2F,$08,$2D,$08,$28 ; BAC4 10 2D 10 2F 08 2D 08 28 .-./.-.( + .byte $08,$2F,$08,$35,$08,$2F,$08,$2D ; BACC 08 2F 08 35 08 2F 08 2D ./.5./.- + .byte $08,$35,$08,$3C,$10,$2F,$10,$35 ; BAD4 08 35 08 3C 10 2F 10 35 .5.<./.5 + .byte $10,$2D,$10,$28,$08,$2D,$08,$2F ; BADC 10 2D 10 28 08 2D 08 2F .-.(.-./ + .byte $08,$35,$08,$3C,$10,$00 ; BAE4 08 35 08 3C 10 00 .5.<.. +; level intro music, bass +sfx16: .byte $01,$A7,$02,$F3,$20,$A2,$20,$F3 ; BAEA 01 A7 02 F3 20 A2 20 F3 .... . . + .byte $20,$A2,$20,$F3,$20,$A2,$20,$79 ; BAF2 20 A2 20 F3 20 A2 20 79 . . . y + .byte $10,$A2,$10,$F3,$10,$00 ; BAFA 10 A2 10 F3 10 00 ...... +level_names: + .byte $20,$20,$20,$4E,$4F,$54,$48,$49 ; BB00 20 20 20 4E 4F 54 48 49 NOTHI + .byte $4E,$47,$20,$54,$4F,$20,$49,$54 ; BB08 4E 47 20 54 4F 20 49 54 NG TO IT + .byte $20,$20,$20,$20,$20,$20,$20,$45 ; BB10 20 20 20 20 20 20 20 45 E + .byte $4C,$45,$43,$54,$52,$4F,$43,$55 ; BB18 4C 45 43 54 52 4F 43 55 LECTROCU + .byte $54,$49,$4F,$4E,$20,$20,$20,$20 ; BB20 54 49 4F 4E 20 20 20 20 TION + .byte $20,$20,$20,$20,$20,$44,$55,$4D ; BB28 20 20 20 20 20 44 55 4D DUM + .byte $42,$57,$41,$49,$54,$45,$52,$20 ; BB30 42 57 41 49 54 45 52 20 BWAITER + .byte $20,$20,$20,$20,$20,$20,$20,$20 ; BB38 20 20 20 20 20 20 20 20 + .byte $20,$48,$45,$4C,$4C,$53,$54,$4F ; BB40 20 48 45 4C 4C 53 54 4F HELLSTO + .byte $4E,$45,$53,$20,$20,$20,$20,$20 ; BB48 4E 45 53 20 20 20 20 20 NES + .byte $20,$20,$46,$49,$47,$55,$52,$49 ; BB50 20 20 46 49 47 55 52 49 FIGURI + .byte $54,$53,$20,$52,$45,$56,$45,$4E ; BB58 54 53 20 52 45 56 45 4E TS REVEN + .byte $47,$45,$20,$20,$20,$20,$20,$20 ; BB60 47 45 20 20 20 20 20 20 GE + .byte $20,$20,$20,$57,$41,$4C,$4C,$53 ; BB68 20 20 20 57 41 4C 4C 53 WALLS + .byte $20,$20,$20,$20,$20,$20,$20,$20 ; BB70 20 20 20 20 20 20 20 20 + .byte $20,$20,$20,$20,$20,$20,$5A,$49 ; BB78 20 20 20 20 20 20 5A 49 ZI + .byte $47,$2D,$5A,$41,$47,$20,$20,$20 ; BB80 47 2D 5A 41 47 20 20 20 G-ZAG + .byte $20,$20,$20,$20,$20,$20,$20,$20 ; BB88 20 20 20 20 20 20 20 20 + .byte $20,$53,$50,$45,$4C,$4C,$42,$4F ; BB90 20 53 50 45 4C 4C 42 4F SPELLBO + .byte $55,$4E,$44,$20,$20,$20,$20,$20 ; BB98 55 4E 44 20 20 20 20 20 UND + .byte $20,$20,$20,$20,$20,$20,$42,$4C ; BBA0 20 20 20 20 20 20 42 4C BL + .byte $41,$43,$4B,$4F,$55,$54,$20,$20 ; BBA8 41 43 4B 4F 55 54 20 20 ACKOUT + .byte $20,$20,$20,$20,$48,$45,$52,$45 ; BBB0 20 20 20 20 48 45 52 45 HERE + .byte $54,$48,$45,$52,$45,$45,$56,$45 ; BBB8 54 48 45 52 45 45 56 45 THEREEVE + .byte $52,$59,$57,$48,$45,$52,$45,$20 ; BBC0 52 59 57 48 45 52 45 20 RYWHERE + .byte $20,$20,$20,$20,$20,$48,$41,$54 ; BBC8 20 20 20 20 20 48 41 54 HAT + .byte $43,$48,$4C,$49,$4E,$47,$53,$20 ; BBD0 43 48 4C 49 4E 47 53 20 CHLINGS + .byte $20,$20,$20,$20,$20,$20,$20,$20 ; BBD8 20 20 20 20 20 20 20 20 + .byte $20,$48,$55,$52,$52,$49,$43,$41 ; BBE0 20 48 55 52 52 49 43 41 HURRICA + .byte $4E,$45,$20,$20,$20,$20,$20,$20 ; BBE8 4E 45 20 20 20 20 20 20 NE +; used for centering level name on gameboard +level_name_hscrol_table: + .byte $04,$04,$00,$00,$00,$04,$04,$00 ; BBF0 04 04 00 00 00 04 04 00 ........ + .byte $00,$04,$00,$04,$00,$00,$00,$00 ; BBF8 00 04 00 04 00 00 00 00 ........ +; ---------------------------------------------------------------------------- +; the WELL DONE screen, when you beat all the levels. after this, the game plays random levels. +well_done_screen: + jsr L803C ; BC00 20 3C 80 <. + jsr enable_joystick_jv ; BC03 20 1B 80 .. + jsr clear_screen_mem_jv ; BC06 20 1E 80 .. + lda #$00 ; BC09 A9 00 .. + sta $06AB ; BC0B 8D AB 06 ... + jsr setup_gameboard_dlist_jv ; BC0E 20 15 80 .. + ldy dlist_shadow_lo ; BC11 AC AC 06 ... + lda #$41 ; BC14 A9 41 .A + sta $080A,y ; BC16 99 0A 08 ... + tya ; BC19 98 . + sta $080B,y ; BC1A 99 0B 08 ... + lda #$08 ; BC1D A9 08 .. + sta $080C,y ; BC1F 99 0C 08 ... + lda #$D9 ; BC22 A9 D9 .. + sta dm_progctr ; BC24 85 C0 .. + lda #$BC ; BC26 A9 BC .. + sta dm_progctr+1 ; BC28 85 C1 .. + jsr draw_map_jv ; BC2A 20 00 80 .. + lda #$04 ; BC2D A9 04 .. + sta $0688 ; BC2F 8D 88 06 ... + sta $066A ; BC32 8D 6A 06 .j. + lda #$7C ; BC35 A9 7C .| + sta $067E ; BC37 8D 7E 06 .~. + lda #$20 ; BC3A A9 20 . + sta $0683 ; BC3C 8D 83 06 ... +; load dli_service_2 address into dli shadow +setup_dli_2: + lda #$C7 ; BC3F A9 C7 .. + sta dli_vec_shadow_lo ; BC41 8D AE 06 ... + lda #$BD ; BC44 A9 BD .. + sta dli_vec_shadow_hi ; BC46 8D AF 06 ... + lda #$8D ; BC49 A9 8D .. + sta $0809 ; BC4B 8D 09 08 ... + sta $088A ; BC4E 8D 8A 08 ... +LBC51: lda dli_vec_shadow_hi ; BC51 AD AF 06 ... + bne LBC51 ; BC54 D0 FB .. + lda #$96 ; BC56 A9 96 .. + sta COLOR0 ; BC58 8D C4 02 ... + sta jiffy_timer_1 ; BC5B 8D 1A 06 ... +LBC5E: lda jiffy_timer_1 ; BC5E AD 1A 06 ... + cmp #$20 ; BC61 C9 20 . + bne LBC5E ; BC63 D0 F9 .. + lda #$03 ; BC65 A9 03 .. + jsr cue_music_jv ; BC67 20 18 80 .. + lda #$CD ; BC6A A9 CD .. + sta work_level_sub0 ; BC6C 8D 82 07 ... + lda #$BC ; BC6F A9 BC .. + sta work_level_sub0+1 ; BC71 8D 83 07 ... + lda #$05 ; BC74 A9 05 .. + sta player_speed ; BC76 8D 24 06 .$. + lda #$0D ; BC79 A9 0D .. + sta joystick_disabled ; BC7B 8D 32 06 .2. + lda #$00 ; BC7E A9 00 .. + sta $0623 ; BC80 8D 23 06 .#. + lda #$52 ; BC83 A9 52 .R + sta work_level_sub1 ; BC85 8D 84 07 ... + lda #$BD ; BC88 A9 BD .. + sta work_level_sub1+1 ; BC8A 8D 85 07 ... + lda #$4C ; BC8D A9 4C .L + sta work_level_offs_46+7 ; BC8F 8D B5 07 ... +LBC92: lda work_level_sub1 ; BC92 AD 84 07 ... + cmp #$E6 ; BC95 C9 E6 .. + bne LBC92 ; BC97 D0 F9 .. + lda #$00 ; BC99 A9 00 .. + sta $06AB ; BC9B 8D AB 06 ... + jsr setup_gameboard_dlist_jv ; BC9E 20 15 80 .. + ldx #$0B ; BCA1 A2 0B .. +LBCA3: lda LBDD1,x ; BCA3 BD D1 BD ... + sta $3DE8,x ; BCA6 9D E8 3D ..= + dex ; BCA9 CA . + bne LBCA3 ; BCAA D0 F7 .. + lda #$3D ; BCAC A9 3D .= + sta $D4 ; BCAE 85 D4 .. + lda #$F5 ; BCB0 A9 F5 .. + sta $D3 ; BCB2 85 D3 .. + ldx #$03 ; BCB4 A2 03 .. +LBCB6: lda $06FF,x ; BCB6 BD FF 06 ... + sta $CF,x ; BCB9 95 CF .. + dex ; BCBB CA . + bne LBCB6 ; BCBC D0 F8 .. + jsr xxx_level_something_jv ; BCBE 20 09 80 .. +LBCC1: lda $0663 ; BCC1 AD 63 06 .c. + bne LBCC1 ; BCC4 D0 FB .. + lda level ; BCC6 AD F6 06 ... + inc randomizer_mode ; BCC9 EE F3 06 ... + rts ; BCCC 60 ` + +; ---------------------------------------------------------------------------- +; dunno, but referenced by code at $BC6A +code_bccd: + lda $062A ; BCCD AD 2A 06 .*. + sta COLOR2 ; BCD0 8D C6 02 ... + lda #$02 ; BCD3 A9 02 .. + sta collision_save+4 ; BCD5 8D B4 06 ... + rts ; BCD8 60 ` + +; ---------------------------------------------------------------------------- +; level map used for the WELL DONE screen, when you beat level 12 +well_done_map: + .byte $FE,$A0,$BD,$FD,$00,$04,$0C,$06 ; BCD9 FE A0 BD FD 00 04 0C 06 ........ + .byte $07,$30,$06,$09,$54,$06,$09,$78 ; BCE1 07 30 06 09 54 06 09 78 .0..T..x + .byte $06,$09,$0C,$30,$09,$30,$38,$05 ; BCE9 06 09 0C 30 09 30 38 05 ...0.08. + .byte $54,$30,$09,$78,$30,$09,$FD,$04 ; BCF1 54 30 09 78 30 09 FD 04 T0.x0... + .byte $04,$10,$22,$02,$20,$34,$01,$34 ; BCF9 04 10 22 02 20 34 01 34 ..". 4.4 + .byte $4C,$01,$44,$34,$01,$58,$38,$05 ; BD01 4C 01 44 34 01 58 38 05 L.D4.X8. + .byte $FD,$04,$FC,$1C,$26,$02,$20,$4C ; BD09 FD 04 FC 1C 26 02 20 4C ....&. L + .byte $01,$34,$34,$01,$44,$4C,$01,$FD ; BD11 01 34 34 01 44 4C 01 FD .44.DL.. + .byte $04,$00,$34,$06,$06,$34,$16,$06 ; BD19 04 00 34 06 06 34 16 06 ..4..4.. + .byte $34,$26,$06,$54,$26,$07,$78,$26 ; BD21 34 26 06 54 26 07 78 26 4&.T&.x& + .byte $07,$10,$30,$04,$0C,$50,$05,$38 ; BD29 07 10 30 04 0C 50 05 38 ..0..P.8 + .byte $30,$03,$38,$50,$03,$7C,$30,$06 ; BD31 30 03 38 50 03 7C 30 06 0.8P.|0. + .byte $7C,$40,$06,$7C,$50,$06,$FD,$00 ; BD39 7C 40 06 7C 50 06 FD 00 |@.|P... + .byte $04,$24,$06,$07,$24,$38,$05,$48 ; BD41 04 24 06 07 24 38 05 48 .$..$8.H + .byte $38,$05,$6C,$30,$09,$18,$1A,$03 ; BD49 38 05 6C 30 09 18 1A 03 8.l0.... + .byte $FF ; BD51 FF . +; ---------------------------------------------------------------------------- +; referenced by code at $BC83 +code_bd52: + lda $0621 ; BD52 AD 21 06 .!. + bne LBD58 ; BD55 D0 01 .. + rts ; BD57 60 ` + +; ---------------------------------------------------------------------------- +LBD58: ldy dlist_shadow_lo ; BD58 AC AC 06 ... + lda #$0D ; BD5B A9 0D .. + sta $0809,y ; BD5D 99 09 08 ... + lda #$8D ; BD60 A9 8D .. + sta $080A,y ; BD62 99 0A 08 ... + lda $080B,y ; BD65 B9 0B 08 ... + sta $080C,y ; BD68 99 0C 08 ... + lda #$41 ; BD6B A9 41 .A + sta $080B,y ; BD6D 99 0B 08 ... + lda #$08 ; BD70 A9 08 .. + sta $080D,y ; BD72 99 0D 08 ... + inc dlist_shadow_lo ; BD75 EE AC 06 ... + cpy #$4E ; BD78 C0 4E .N + beq LBD81 ; BD7A F0 05 .. + cpy #$CE ; BD7C C0 CE .. + beq LBD81 ; BD7E F0 01 .. + rts ; BD80 60 ` + +; ---------------------------------------------------------------------------- +LBD81: lda #$E6 ; BD81 A9 E6 .. + sta work_level_sub1 ; BD83 8D 84 07 ... + lda #$06 ; BD86 A9 06 .. + sta work_level_sub1+1 ; BD88 8D 85 07 ... + lda #$09 ; BD8B A9 09 .. + sta player_speed ; BD8D 8D 24 06 .$. + lda #$C6 ; BD90 A9 C6 .. + sta $0683 ; BD92 8D 83 06 ... + lda #$00 ; BD95 A9 00 .. + sta $0621 ; BD97 8D 21 06 .!. + lda #$01 ; BD9A A9 01 .. + sta $0688 ; BD9C 8D 88 06 ... + rts ; BD9F 60 ` + +; ---------------------------------------------------------------------------- +; used to draw the large WELL DONE banner +well_done_shape: + .byte $04,$00,$00,$01,$01,$01,$01,$05 ; BDA0 04 00 00 01 01 01 01 05 ........ + .byte $00,$01,$01,$01,$01,$01,$03,$05 ; BDA8 00 01 01 01 01 01 03 05 ........ + .byte $00,$02,$01,$01,$01,$01,$03,$05 ; BDB0 00 02 01 01 01 01 03 05 ........ + .byte $00,$03,$01,$01,$01,$01,$03,$04 ; BDB8 00 03 01 01 01 01 03 04 ........ + .byte $01,$04,$03,$03,$03,$03,$FF ; BDC0 01 04 03 03 03 03 FF ....... +; ---------------------------------------------------------------------------- +; DLI service routine, changes COLBK, address gets stored in $6ae/$6af by code at $bc3c +dli_service_2: + pha ; BDC7 48 H + lda #$C4 ; BDC8 A9 C4 .. + sta WSYNC ; BDCA 8D 0A D4 ... + sta COLBK ; BDCD 8D 1A D0 ... + pla ; BDD0 68 h +LBDD1: rti ; BDD1 40 @ + +; ---------------------------------------------------------------------------- +; not sure what displays this, but it's screen codes +total_score_msg: + .byte $74,$6F,$74,$61,$6C,$00,$73,$63 ; BDD2 74 6F 74 61 6C 00 73 63 total.sc + .byte $6F,$72,$65,$33,$00,$26,$29,$2C ; BDDA 6F 72 65 33 00 26 29 2C ore3.&), + .byte $25,$33,$00,$00,$00,$00,$00,$00 ; BDE2 25 33 00 00 00 00 00 00 %3...... + .byte $00,$00,$00,$00,$00,$00,$00,$00 ; BDEA 00 00 00 00 00 00 00 00 ........ +sfx00: .byte $01,$A5,$02,$79,$08,$A2,$08,$79 ; BDF2 01 A5 02 79 08 A2 08 79 ...y...y + .byte $08,$A2,$08,$C1,$10,$C1,$10,$F3 ; BDFA 08 A2 08 C1 10 C1 10 F3 ........ + .byte $20,$F3,$20,$02,$F5,$BD,$02,$79 ; BE02 20 F3 20 02 F5 BD 02 79 . ....y + .byte $08,$6C,$08,$60,$08,$5B,$08,$51 ; BE0A 08 6C 08 60 08 5B 08 51 .l.`.[.Q + .byte $08,$5B,$08,$60,$08,$6C,$08,$79 ; BE12 08 5B 08 60 08 6C 08 79 .[.`.l.y + .byte $10,$A2,$10,$F3,$20,$01,$A0,$00 ; BE1A 10 A2 10 F3 20 01 A0 00 .... ... + .byte $0A,$80,$00 ; BE22 0A 80 00 ... +sfx01: .byte $01,$A6,$02,$3C,$20,$51,$20,$48 ; BE25 01 A6 02 3C 20 51 20 48 ...< Q H + .byte $08,$51,$08,$48,$08,$40,$08,$3C ; BE2D 08 51 08 48 08 40 08 3C .Q.H.@.< + .byte $10,$3C,$20,$3C,$10,$51,$10,$51 ; BE35 10 3C 20 3C 10 51 10 51 .< <.Q.Q + .byte $10,$48,$08,$51,$08,$48,$08,$40 ; BE3D 10 48 08 51 08 48 08 40 .H.Q.H.@ + .byte $08,$3C,$20,$3C,$20,$51,$20,$48 ; BE45 08 3C 20 3C 20 51 20 48 .< < Q H + .byte $08,$51,$08,$48,$08,$40,$08,$3C ; BE4D 08 51 08 48 08 40 08 3C .Q.H.@.< + .byte $10,$3C,$10,$3C,$08,$35,$08,$2F ; BE55 10 3C 10 3C 08 35 08 2F .<.<.5./ + .byte $08,$2D,$08,$28,$08,$2D,$08,$2F ; BE5D 08 2D 08 28 08 2D 08 2F .-.(.-./ + .byte $08,$35,$08,$3C,$08,$51,$08,$60 ; BE65 08 35 08 3C 08 51 08 60 .5.<.Q.` + .byte $08,$51,$08,$79,$20,$00,$01,$81 ; BE6D 08 51 08 79 20 00 01 81 .Q.y ... + .byte $00,$32,$01,$00 ; BE75 00 32 01 00 .2.. +sfx_extra_life: + .byte $01,$A8,$00,$05,$02,$0F,$02,$0A ; BE79 01 A8 00 05 02 0F 02 0A ........ + .byte $02,$14,$02,$0F,$02,$19,$02,$14 ; BE81 02 14 02 0F 02 19 02 14 ........ + .byte $02,$1E,$02,$00 ; BE89 02 1E 02 00 .... +; end of game tune, melody +sfx02: .byte $01,$A5,$02,$3C,$10,$51,$10,$3C ; BE8D 01 A5 02 3C 10 51 10 3C ...<.Q.< + .byte $10,$51,$10,$44,$08,$44,$08,$44 ; BE95 10 51 10 44 08 44 08 44 .Q.D.D.D + .byte $08,$44,$08,$44,$10,$5B,$10,$4C ; BE9D 08 44 08 44 10 5B 10 4C .D.D.[.L + .byte $10,$66,$10,$4C,$10,$66,$10,$51 ; BEA5 10 66 10 4C 10 66 10 51 .f.L.f.Q + .byte $40,$00 ; BEAD 40 00 @. +; end of game tune, bass +sfx03: .byte $01,$A4,$02,$79,$10,$A2,$10,$F3 ; BEAF 01 A4 02 79 10 A2 10 F3 ...y.... + .byte $10,$79,$10,$88,$10,$B6,$10,$D9 ; BEB7 10 79 10 88 10 B6 10 D9 .y...... + .byte $10,$88,$10,$99,$10,$CC,$10,$CC ; BEBF 10 88 10 99 10 CC 10 CC ........ + .byte $10,$99,$10,$A2,$08,$99,$08,$A2 ; BEC7 10 99 10 A2 08 99 08 A2 ........ + .byte $08,$99,$08,$A2,$20,$00 ; BECF 08 99 08 A2 20 00 .... . +; end level tune #1, bass +sfx04: .byte $01,$A5,$02,$79,$14,$A2,$14,$79 ; BED5 01 A5 02 79 14 A2 14 79 ...y...y + .byte $14,$A2,$14,$79,$14,$A2,$14,$F3 ; BEDD 14 A2 14 79 14 A2 14 F3 ...y.... + .byte $14,$A2,$14,$02,$D8,$BE,$01,$00 ; BEE5 14 A2 14 02 D8 BE 01 00 ........ +; end level tune #1, melody +sfx05: .byte $01,$A0,$00,$0A,$A0,$01,$A6,$02 ; BEED 01 A0 00 0A A0 01 A6 02 ........ + .byte $51,$0A,$55,$0A,$51,$0A,$4C,$0A ; BEF5 51 0A 55 0A 51 0A 4C 0A Q.U.Q.L. + .byte $51,$0A,$4C,$0A,$48,$0A,$4C,$0A ; BEFD 51 0A 4C 0A 48 0A 4C 0A Q.L.H.L. + .byte $48,$0A,$44,$0A,$48,$0A,$44,$0A ; BF05 48 0A 44 0A 48 0A 44 0A H.D.H.D. + .byte $3C,$0A,$51,$0A,$3C,$14,$00 ; BF0D 3C 0A 51 0A 3C 14 00 <.Q.<.. +; end level tune #2, melody +sfx06: .byte $01,$A6,$02,$79,$20,$60,$14,$51 ; BF14 01 A6 02 79 20 60 14 51 ...y `.Q + .byte $3C,$60,$0A,$5B,$14,$60,$08,$5B ; BF1C 3C 60 0A 5B 14 60 08 5B <`.[.`.[ + .byte $14,$60,$08,$5B,$14,$51,$08,$60 ; BF24 14 60 08 5B 14 51 08 60 .`.[.Q.` + .byte $14,$79,$20,$00 ; BF2C 14 79 20 00 .y . +; end level tune #2, bass +sfx07: .byte $01,$A6,$02,$F3,$0A,$D9,$0A,$C1 ; BF30 01 A6 02 F3 0A D9 0A C1 ........ + .byte $0A,$A2,$14,$79,$1E,$A2,$1E,$C1 ; BF38 0A A2 14 79 1E A2 1E C1 ...y.... + .byte $0A,$B6,$50,$C1,$08,$A2,$14,$F3 ; BF40 0A B6 50 C1 08 A2 14 F3 ..P..... + .byte $20,$00 ; BF48 20 00 . +; end level tune #3, bass +sfx08: .byte $01,$A8,$02,$79,$30,$A2,$20,$79 ; BF4A 01 A8 02 79 30 A2 20 79 ...y0. y + .byte $20,$51,$10,$A2,$30,$6C,$20,$A3 ; BF52 20 51 10 A2 30 6C 20 A3 Q..0l . + .byte $20,$6C,$10,$79,$70,$00 ; BF5A 20 6C 10 79 70 00 l.yp. +; end level tune #3, melody +sfx09: .byte $01,$A5,$02,$79,$10,$60,$10,$51 ; BF60 01 A5 02 79 10 60 10 51 ...y.`.Q + .byte $10,$3C,$20,$35,$10,$3C,$10,$44 ; BF68 10 3C 20 35 10 3C 10 44 .< 5.<.D + .byte $10,$40,$10,$51,$20,$5B,$20,$6C ; BF70 10 40 10 51 20 5B 20 6C .@.Q [ l + .byte $20,$80,$10,$79,$10,$60,$10,$51 ; BF78 20 80 10 79 10 60 10 51 ..y.`.Q + .byte $10,$3C,$40,$00 ; BF80 10 3C 40 00 .<@. +; end level tune #4, melody +sfx10: .byte $01,$A5,$02,$3C,$20,$2D,$12,$32 ; BF84 01 A5 02 3C 20 2D 12 32 ...< -.2 + .byte $20,$3C,$20,$4C,$08,$44,$14,$4C ; BF8C 20 3C 20 4C 08 44 14 4C < L.D.L + .byte $09,$40,$20,$32,$20,$40,$09,$44 ; BF94 09 40 20 32 20 40 09 44 .@ 2 @.D + .byte $09,$4C,$09,$5B,$09,$4C,$09,$5B ; BF9C 09 4C 09 5B 09 4C 09 5B .L.[.L.[ + .byte $48,$00 ; BFA4 48 00 H. +; end level tune #4, bass +sfx11: .byte $01,$A6,$02,$79,$20,$B6,$30,$99 ; BFA6 01 A6 02 79 20 B6 30 99 ...y .0. + .byte $20,$88,$09,$99,$20,$E6,$30,$99 ; BFAE 20 88 09 99 20 E6 30 99 ... .0. + .byte $20,$88,$09,$99,$20,$B6,$3A,$00 ; BFB6 20 88 09 99 20 B6 3A 00 ... .:. +; jumping sound +sfx12: .byte $01,$A5,$00,$79,$04,$60,$04,$51 ; BFBE 01 A5 00 79 04 60 04 51 ...y.`.Q + .byte $04,$3C,$04,$51,$04,$60,$04,$79 ; BFC6 04 3C 04 51 04 60 04 79 .<.Q.`.y + .byte $04,$00 ; BFCE 04 00 .. +; funeral march melody +sfx13: .byte $01,$A5,$01,$3C,$20,$3C,$10,$3C ; BFD0 01 A5 01 3C 20 3C 10 3C ...< <.< + .byte $10,$3C,$20,$32,$10,$35,$10,$35 ; BFD8 10 3C 20 32 10 35 10 35 .< 2.5.5 + .byte $10,$3C,$10,$3C,$10,$40,$10,$3C ; BFE0 10 3C 10 3C 10 40 10 3C .<.<.@.< + .byte $40,$00 ; BFE8 40 00 @. +; funeral march bass +sfx14: .byte $01,$A6,$00,$79,$10,$A2,$10,$02 ; BFEA 01 A6 00 79 10 A2 10 02 ...y.... + .byte $ED,$BF,$06,$F3,$10,$A2,$10,$00 ; BFF2 ED BF 06 F3 10 A2 10 00 ........ +; ---------------------------------------------------------------------------- +; main entry point, note cartstart_left and cartstart_right point to the same address +cartstart_left: + .addr cart_entry_point ; BFFA C0 8A .. +; ---------------------------------------------------------------------------- +; 0 here means 'cartridge present' +cartpresent_left: + .byte $00 ; BFFC 00 . +; 4 here means init & start the cart, no disk boot, non-diagnostic +cartoptions_left: + .byte $04 ; BFFD 04 . +; ---------------------------------------------------------------------------- +; points to a CLC/RTS do-nothing routine (same as cartinit_right) +cartinit_left: + .addr cart_start_stub ; BFFE FE 8A .. diff --git a/jumpmanjr.inc b/jumpmanjr.inc new file mode 100644 index 0000000..7341855 --- /dev/null +++ b/jumpmanjr.inc @@ -0,0 +1,68 @@ +; DO NOT put jumpman-specific addresses here (ROM or working RAM), +; this is only for Atari hardware and OS equates. + +; HW addresses +AUDCTL = $D208 +PMBASE = $D407 +DMACTL = $D400 +PRIOR = $D01B +SKCTL = $D20F +GRACTL = $D01D +DLISTL = $D402 +DLISTH = $D403 +NMIEN = $D40E +IRQEN = $D20E +PORTA = $D300 +TRIG0 = $D010 +CHBASE = $D409 +WSYNC = $D40A +COLPF2 = $D018 +HSCROL = $D404 +COLBK = $D01A +AUDF1_minus_two = $D1FE +AUDF1_minus_one = $D1FF +AUDF1 = $D200 +AUDC1 = $D201 +AUDF2 = $D202 +AUDC2 = $D203 +AUDF3 = $D204 +AUDC3 = $D205 +AUDF4 = $D206 +AUDC4 = $D207 +AUDCTL = $D208 +RANDOM = $D20A +KBCODE = $D209 +CONSOL = $D01F +SDMCTL = $022F +HPOSP3 = $D003 +HPOSM3 = $D007 +HPOSM2 = $D006 +HPOSM1 = $D005 +HPOSM0 = $D004 +GRAFM = $D011 +HITCLR = $D01E +COLPF0 = $D016 +COLPF1 = $D017 +COLPF3 = $D019 +COLPM1 = $D013 +COLPM0 = $D012 +SIZEM = $D00C +SIZEP2 = $D00A +SIZEP3 = $D00B + +; OS addresses +COLOR0 = $02C4 +COLOR1 = $02C5 +COLOR2 = $02C6 +COLOR3 = $02C7 +COLOR4 = $02C8 +PCOLR0 = $02C0 +PCOLR1 = $02C1 +PCOLR2 = $02C2 +PCOLR3 = $02C3 +GPRIOR = $026F +CHBAS = $02F4 +VKEYBD = $0208 +VKEYBD_hi = $0209 +SETVBV = $E45C +XITVBV = $E462 diff --git a/jumpmanjr.info b/jumpmanjr.info new file mode 100644 index 0000000..17dfa03 --- /dev/null +++ b/jumpmanjr.info @@ -0,0 +1,908 @@ +### GENERATED FILE, do not edit, edit main.info and mklevelinfo.pl instead + +# da65 info file for jumpman junior ROM. + +GLOBAL { + OUTPUTNAME "jumpmanjr.dasm"; + INPUTNAME "jumpmanjr.rom"; + STARTADDR $8000; + CPU "6502"; + COMMENTS 4; +}; + +#SEGMENT { START $8000; END $BFFF; NAME "jumpmanjr"; }; + +ASMINC { FILE "jumpmanjr.inc"; }; + +# RANGE { START $whatever; END $whatever; TYPE Code|ByteTable|AddrTable|RtsTable; } + +label { name "cart_start_stub"; addr $8AFE; }; +label { name "cart_entry_point"; addr $8ac0; }; +label { name "check_keycode"; addr $9C07; }; +label { name "store_speed_value"; addr $9C13; }; +label { name "keyboard_isr_exit"; addr $9C0F; }; +label { name "check_consol"; addr $88C8; }; +label { name "ask_num_players"; addr $9400; }; +label { name "sl_loop"; addr $96D8; }; +label { name "materialize_jumpman"; addr $977B; }; +label { name "mj_clear_loop"; addr $9782; }; +label { name "mj_set_freq_and_color"; addr $97BB; }; +label { name "mj_delay"; addr $97CD; }; +label { name "mj_done"; addr $97DB; }; +label { name "game_main_loop"; addr $9740; }; + +label { name "copy_level_desc_2"; addr $9677; comment "copy level descriptor to $0780"; }; +label { name "randomize_level"; addr $9BED; comment "only after beating levels 1-12 in order"; }; +label { name "enter_level"; addr $96BA; comment "maybe this should be check_level or init_level?"; }; +label { name "copy_level_desc"; addr $96CE; comment "copy level descriptor from levelXX_desc at $A000+(level*$40) to $07c0-$07ff"; }; +label { name "randomizer_mode"; addr $06F3; comment "only after beating levels 1-12 in order"; }; + +label { name "init_loop"; addr $8ac4; comment "clear pages 6 and 7"; }; +label { name "set_vkeybd"; addr $83ED; comment "VKEYBD now points to $9c00 aka keyboard_isr"; }; +label { name "set_vvblki"; addr $8401; comment "VVBLKI now points to $840d aka vblank_imm_isr"; }; +label { name "vblank_imm_isr"; addr $840d; comment "service immediate vblank interrupt"; }; + +label { name "dli_chained_1"; addr $9B72; comment "changes DLI vector to point to dli_chained_2"; }; +label { name "dli_chained_2"; addr $9B87; comment "changes DLI vector to point to dli_chained_3"; }; +label { name "dli_chained_3"; addr $9BB1; comment "changes DLI vector to point to dli_chained_1"; }; +label { name "update_color_regs"; addr $840F; comment "update color regs from shadow regs (X ranges 1 to 9, GRAFM+1 is COLPM0, $2bf+1 is PCOLR0)"; }; + +range { name "code_99f7"; start $99F7; end $9A1B; type code; }; +range { name "data_8406"; start $8406; end $840c; type bytetable; }; +range { name "data_9a1c"; start $9a1c; end $9A5B; type bytetable; }; +range { name "gameboard_dlist_data"; start $9B62; end $9b71; type bytetable; comment "this isn't used as-is for a display list, see setup_gameboard_dlist"; }; +RANGE { NAME "cartstart_left"; START $BFFA; END $BFFB ; TYPE AddrTable; comment "main entry point, note cartstart_left and cartstart_right point to the same address"; }; +RANGE { NAME "cartstart_right"; START $9FFA; END $9FFB ; TYPE AddrTable; comment "main entry point, note cartstart_left and cartstart_right point to the same address"; }; +RANGE { NAME "cartinit_left"; START $BFFE; END $BFFF ; TYPE AddrTable; comment "points to a CLC/RTS do-nothing routine (same as cartinit_right)"; }; +RANGE { NAME "cartinit_right"; START $9FFE; END $9FFF ; TYPE AddrTable; comment "points to a CLC/RTS do-nothing routine (same as cartinit_left)"; }; + +range { name "cartpresent_left"; start $bffc; end $bffc; type bytetable; comment "0 here means 'cartridge present'"; }; +range { name "cartpresent_right"; start $9ffc; end $9ffc; type bytetable; comment "0 here means 'cartridge present'"; }; +range { name "cartoptions_left"; start $bffd; end $bffd; type bytetable; comment "4 here means init & start the cart, no disk boot, non-diagnostic"; }; +range { name "cartoptions_right"; start $9ffd; end $9ffd; type bytetable; comment "4 here means init & start the cart, no disk boot, non-diagnostic"; }; + +label { name "VDSLST"; addr $0200; size 2; }; +label { name "FR1"; addr $00e0; size 6; }; +label { name "player_x_speed"; addr $95C5; size 20; comment "' PLAYER # SPEED? ' in PF2 color"; }; +label { name "num_name_hscrol_table"; addr $95D9; size 4; comment "used for centering ONE TWO THREE FOUR, see option_key_handler"; }; +label { name "number_names_0"; addr $95dd; size 4; comment "space space T space (names ONE TWO THREE FOUR)"; }; +label { name "number_names_1"; addr $95e1; size 4; comment "O T H F"; }; +label { name "number_names_2"; addr $95e5; size 4; comment "N W R O"; }; +label { name "number_names_3"; addr $95e9; size 4; comment "E O E U"; }; +label { name "number_names_4"; addr $95ed; size 4; comment "space space E R"; }; +label { name "sfx_select_key"; addr $95f1; comment "played when select key pressed, 4 notes, descending"; }; +label { name "missiles_mask_table_minus_one"; addr $82df; }; +label { name "set_dma_ctl"; addr $838F; comment "std playfield, enable players + missiles, single-line p/m res, DMA enabled"; }; + +range { name "level_names"; start $BB00; end $bbef; type bytetable; }; +range { name "pm_memory"; start $2800; end $2fff; type bytetable; }; +range { name "missiles_mask_table"; start $82e0; end $82E7; type bytetable; }; +range { name "missiles_done"; start $82DD; end $82df; type code; }; +range { name "position_missiles"; start $8293; end $82DA; type code; }; +range { name "charset"; start $9e00; end $9ff9; type bytetable; comment "GR.1/2 font, 512 bytes"; }; +range { name "game_display_list"; start $0881; end $08e3; type bytetable; comment "display list for game board"; }; +range { name "title_display_list"; start $91B3; end $91ce; type bytetable; comment "display list for title screen"; }; +range { name "numplayer_display_list"; start $955f; end $9577; type bytetable; comment "display list for 'number of players' screen"; }; +label { name "setup_numplayer_dlist"; addr $9444; comment "set dlist shadow to point to numplayer_display_list"; }; +label { name "setup_numplayer_dli_sr"; addr $944e; comment "set dli vector to point to num_player_dli_service"; }; +label { name "anp_loop_done"; addr $9421; comment "X is now 0"; }; +label { name "anp_clear_loop"; addr $940D; comment "clear area where NUMBER OF PLAYERS? will be displayed"; }; +label { name "anp_copy_loop"; addr $9418; comment "copy NUMBER OF PLAYERS to screen RAM"; }; +label { name "save_collisions"; addr $8503; comment "save contents of GTIA collision regs (X ranges 1 to $10, dli_vec_shadow_hi should read collision_save-1)"; }; + +label { name "check_collisions_1"; addr $8F73; size 1; comment "did any missile hit a player, or did players 2 or 3 hit a player..."; }; +label { name "check_collisions_2"; addr $981A; size 1; comment "did player 0 or 1 hit the playfield..."; }; +label { name "check_collisions_3"; addr $9832; size 1; comment "did player 0 or 1 hit the playfield..."; }; +label { name "collision_save"; addr $06B0; size 16; comment "save_collisions copies GTIA collision regs $D000-$d00f here"; }; +label { name "init_next_level"; addr $9BE8; size 1; comment "..."; }; +label { name "show_get_ready_prompt"; addr $9624; size 1; comment "only in multiplayer games"; }; +range { name "gr7_or_masks"; start $8143; end $8152; type bytetable; }; +range { name "gr7_and_masks"; start $8153; end $8156; type bytetable; }; +range { name "data_8892"; start $8892; end $88A7; type bytetable; }; +range { name "data_8dfa"; start $8DFA; end $8DFF; type bytetable; }; +range { name "data_8f43"; start $8F43; end $8f72; type bytetable; }; + +##range { name "mus0_addr1"; start $8FC3; end $8fc4; type addrtable; comment "mus struct table, 5 bytes per entry: 0/1 are an address, 2/3 are another, 5 is maybe the length? tempo?"; }; +##range { name "mus0_addr2"; start $8FC5; end $8fc6; type addrtable; }; +##range { name "mus0_len_or_tempo"; start $8FC7; end $8fc7; type bytetable; }; +## +##range { name "mus1_addr1"; start $8FC8; end $8fc9; type addrtable; }; +##range { name "mus1_addr2"; start $8FCA; end $8fcb; type addrtable; }; +##range { name "mus1_len_or_tempo"; start $8FCC; end $8fcc; type bytetable; }; +## +##range { name "mus2_addr1"; start $8FC8; end $8fc9; type addrtable; }; +##range { name "mus2_addr2"; start $8FCA; end $8fcb; type addrtable; }; +##range { name "mus2_len_or_tempo"; start $8FCC; end $8fcc; type bytetable; }; + +#range { name "more_mus"; start $8FC8; end $8fff; type bytetable; comment "more 5-byte structs"; }; + +range { name "mus00_addr1"; start $8fc3; end $8fc4; type addrtable; comment "aka mus_struct_table, 5 bytes per entry"; }; +range { name "mus00_addr2"; start $8fc5; end $8fc6; type addrtable; }; +range { name "mus00_len_or_tempo"; start $8fc7; end $8fc7; type bytetable; }; + +range { name "mus01_addr1"; start $8fc8; end $8fc9; type addrtable; }; +range { name "mus01_addr2"; start $8fca; end $8fcb; type addrtable; }; +range { name "mus01_len_or_tempo"; start $8fcc; end $8fcc; type bytetable; }; + +range { name "mus02_addr1"; start $8fcd; end $8fce; type addrtable; comment "end of game tune"; }; +range { name "mus02_addr2"; start $8fcf; end $8fd0; type addrtable; }; +range { name "mus02_len_or_tempo"; start $8fd1; end $8fd1; type bytetable; }; + +range { name "mus03_addr1"; start $8fd2; end $8fd3; type addrtable; }; +range { name "mus03_addr2"; start $8fd4; end $8fd5; type addrtable; }; +range { name "mus03_len_or_tempo"; start $8fd6; end $8fd6; type bytetable; }; + +range { name "mus04_addr1"; start $8fd7; end $8fd8; type addrtable; }; +range { name "mus04_addr2"; start $8fd9; end $8fda; type addrtable; }; +range { name "mus04_len_or_tempo"; start $8fdb; end $8fdb; type bytetable; }; + +range { name "mus05_addr1"; start $8fdc; end $8fdd; type addrtable; }; +range { name "mus05_addr2"; start $8fde; end $8fdf; type addrtable; }; +range { name "mus05_len_or_tempo"; start $8fe0; end $8fe0; type bytetable; }; + +range { name "mus06_addr1"; start $8fe1; end $8fe2; type addrtable; }; +range { name "mus06_addr2"; start $8fe3; end $8fe4; type addrtable; }; +range { name "mus06_len_or_tempo"; start $8fe5; end $8fe5; type bytetable; }; + +range { name "mus07_addr1"; start $8fe6; end $8fe7; type addrtable; }; +range { name "mus07_addr2"; start $8fe8; end $8fe9; type addrtable; }; +range { name "mus07_len_or_tempo"; start $8fea; end $8fea; type bytetable; }; + +range { name "mus08_addr1"; start $8feb; end $8fec; type addrtable; comment "tune that plays while level is being drawn"; }; +range { name "mus08_addr2"; start $8fed; end $8fee; type addrtable; }; +range { name "mus08_len_or_tempo"; start $8fef; end $8fef; type bytetable; }; + +range { name "mus09_addr1"; start $8ff0; end $8ff1; type addrtable; }; +range { name "mus09_addr2"; start $8ff2; end $8ff3; type addrtable; }; +range { name "mus09_len_or_tempo"; start $8ff4; end $8ff4; type bytetable; }; + +range { name "mus10_addr1"; start $8ff5; end $8ff6; type addrtable; }; +range { name "mus10_addr2"; start $8ff7; end $8ff8; type addrtable; }; +range { name "mus10_len_or_tempo"; start $8ff9; end $8ff9; type bytetable; }; + +range { name "mus11_addr1"; start $8ffa; end $8ffb; type addrtable; }; +range { name "mus11_addr2"; start $8ffc; end $8ffd; type addrtable; }; +range { name "mus11_len_or_tempo"; start $8ffe; end $8ffe; type bytetable; }; + +range { name "empty_music_entry"; start $8fff; end $8fff; type bytetable; comment "empty music table entries point here"; }; + +label { name "sfx_tempo_tmp"; addr $0661; comment "??"; }; +label { name "sfx_slot_curpos"; addr $064E; size 2; comment "address we've got to so far, playing this sfx"; }; +label { name "sfx_slot_tempo"; addr $063E; size 1; comment "tempo of this sfx"; }; +label { name "sfx_lock"; addr $062F; size 1; comment "lets other code know cue_sfx is still running? not 100% sure"; }; +label { name "inc_sfx_pos"; addr $8231; size 1; comment "point to next byte in current sfx slot indexed by X"; }; +label { name "sfx_finished"; addr $8226; size 1; comment "done playing this sfx, free up the slot, X-indexed"; }; +label { name "sfx_next_note"; addr $817D; size 1; }; +label { name "sfx_player_entry"; addr $8157; size 1; comment "we have 4 slots (because POKEY has 4 voices), X counts down by 2 from 10 to 2 (at 0, the loop exits)"; }; +label { name "next_sfx_slot"; addr $815F; size 1; }; +label { name "sfx_exit"; addr $815E; size 1; }; +label { name "is_slot_active"; addr $8163; size 1; comment "skip it, if slot is inactive"; }; +label { name "sfx_slot_timer"; addr $063F; size 1; }; +label { name "sfx_slot_duration"; addr $0646; size 1; }; +label { name "sfx_play_note"; addr $8206; size 1; comment "y==0, a>=4 on entry"; }; +label { name "sfx_play_rest"; addr $819E; size 1; comment "y==0 on entry"; }; +label { name "sfx_change_tempo"; addr $81AE; size 1; comment "y==0 on entry"; }; +label { name "sfx_jump"; addr $81C8; size 1; comment "I *think* this jumps to a different sfx address..."; }; +label { name "sfx_slot_freq"; addr $0647; size 1; }; + +range { name "sfx00"; start $BDF2; end $BE24; type bytetable; }; +range { name "sfx01"; start $BE25; end $BE78; type bytetable; }; +range { name "sfx_extra_life"; start $BE79; end $BE8C; type bytetable; }; +range { name "sfx02"; start $BE8D; end $BEAE; type bytetable; comment "end of game tune, melody"; }; +range { name "sfx03"; start $BEAF; end $BED4; type bytetable; comment "end of game tune, bass"; }; +range { name "sfx04"; start $BED5; end $BEEC; type bytetable; comment "end level tune #1, bass"; }; +range { name "sfx05"; start $BEED; end $BF13; type bytetable; comment "end level tune #1, melody"; }; +range { name "sfx06"; start $BF14; end $BF2F; type bytetable; comment "end level tune #2, melody"; }; +range { name "sfx07"; start $BF30; end $BF49; type bytetable; comment "end level tune #2, bass"; }; +range { name "sfx08"; start $BF4A; end $BF5F; type bytetable; comment "end level tune #3, bass"; }; +range { name "sfx09"; start $BF60; end $BF83; type bytetable; comment "end level tune #3, melody"; }; +range { name "sfx10"; start $BF84; end $BFA5; type bytetable; comment "end level tune #4, melody"; }; +range { name "sfx11"; start $BFA6; end $BFBD; type bytetable; comment "end level tune #4, bass"; }; +range { name "sfx12"; start $BFBE; end $BFCF; type bytetable; comment "jumping sound"; }; +range { name "sfx13"; start $BFD0; end $BFE9; type bytetable; comment "funeral march melody"; }; +range { name "sfx14"; start $BFEA; end $BFF9; type bytetable; comment "funeral march bass"; }; +range { name "sfx15"; start $BABC; end $BAE9; type bytetable; comment "level intro music, melody"; }; +range { name "sfx16"; start $BAEA; end $BAFF; type bytetable; comment "level intro music, bass"; }; + +range { name "code_8f38"; start $8F38; end $8F42; type code; }; +range { name "try_to_write_rom_again"; start $9126; end $9133; type code; comment "see comment at try_to_write_rom"; }; +range { name "code_adb5"; start $ADB5; end $adc0; type code; }; +range { name "code_adc1"; start $adc1; end $adc3; type code; }; +range { name "data_9134"; start $9134; end $9139; type bytetable; }; +label { name "maybe_data"; addr $913A; comment "this might be more data for the above table instead of code?"; }; +label { name "probly_code"; addr $913D; comment "this probably really is code"; }; +label { name "illegal_nop"; addr $AF1B; comment "NMOS 6502 illegal opcode, NOP zp"; }; +range { name "data_9afc"; start $9AFC; end $9aff; type bytetable; }; +range { name "num_player_dli_service"; start $9578; end $959a; type code; comment "DLI service routine, changes COLPF2, address gets stored in $6ae/$6af by code at $944e"; }; +range { name "dli_service_2"; start $bdc7; end $bdd1; type code; comment "DLI service routine, changes COLBK, address gets stored in $6ae/$6af by code at $bc3c"; }; +label { name "numplayer_screen_data_minus_one"; addr $959a; comment "1-indexed loop copies from here+1"; }; +range { name "numplayer_screen_data"; start $959b; end $95ff; type bytetable; comment "'number of players?', gets copied to $3800, see option_key_handler"; }; +range { name "sfx_add_life_bonus"; start $b896; end $b8a6; type bytetable; comment "played when adding bonus per life at end of level"; }; +range { name "mul_25_table"; start $b8a7; end $b8be; type wordtable; comment "multiply by 25"; }; +range { name "data_table_8a39"; start $8a39; end $8a7f; type bytetable; }; +range { name "data_table_86da"; start $86da; end $8713; type bytetable; }; +range { name "level_name_hscrol_table"; start $BBF0; end $BBff; type bytetable; comment "used for centering level name on gameboard"; }; +range { name "zero_filler_b8bf"; start $b8bf; end $b96a; type bytetable; comment "all zeroes, filler?"; }; +range { name "zero_filler_baab"; start $baab; end $babb; type bytetable; comment "filler?"; }; +range { name "code_bccd"; start $bccd; end $bcd8; type code; comment "dunno, but referenced by code at $BC6A"; }; +range { name "well_done_map"; start $bcd9; end $bd51; type bytetable; comment "level map used for the WELL DONE screen, when you beat level 12"; }; +range { name "well_done_shape"; start $bda0; end $bdc6; type bytetable; comment "used to draw the large WELL DONE banner"; }; +range { name "total_score_msg"; start $bdd2; end $bdf1; type bytetable; comment "not sure what displays this, but it's screen codes"; }; +range { name "zero_filler_8588"; start $B588; end $B696; type bytetable; }; +range { name "wind_table_1"; start $B76B; end $b7bf; type bytetable; comment "used in level11"; }; +label { name "wind_table_2"; addr $b771; }; +range { name "level00_map"; start $A300; end $a497; type bytetable; comment "level map data starts here"; }; +range { name "sfx_a52d"; start $A52D; end $A53C; type bytetable; comment "dunno, referenced by routine at $A50F"; }; +range { name "data_table_a542"; start $A542; end $A68B; type bytetable; comment "dunno, referenced by routine at $A498"; }; +range { name "dumbwaiter_player"; start $a782; end $A826; type bytetable; comment "the dumbwaiters from level02. stored upside-down."; }; +label { name "dw_platform_player"; addr $A685; comment "horizontally moving platforms from level02"; }; +range { name "data_table_a8fd"; start $a8fd; end $A9C6; type bytetable; comment "dunno, referenced by routine at $A8D4"; }; +range { name "map_aa90"; start $aa90; end $AD67; type bytetable; comment "dunno what this is for yet"; }; +label { name "map_aaa6"; addr $aaa6; comment "referenced by routine at $AA82"; }; +range { name "data_table_adc7"; start $adc7; end $af0c; type bytetable; comment "dunno, referenced by routines at $AD9E and $ADB5"; }; +range { name "sfx_afcb"; start $AFCB; end $b0c3; type bytetable; comment "referenced by routine at $AF96"; }; +label { name "map_b000"; addr $b000; comment "referenced by routine at $B0C4"; }; +range { name "data_table_85b6"; start $85b6; end $85bd; type bytetable; comment "used in vblank_imm_isr, not sure for what yet"; }; +range { name "data_table_85de"; start $85de; end $85f5; type bytetable; comment "dunno what this is for yet, but it's copied into page 6 by init_hardware"; }; +range { name "zero_filler_85f6"; start $85f6; end $85ff; type bytetable; comment "probably just filler"; }; +range { name "movement_direction_table"; start $85be; end $85dd; type wordtable; comment "X/Y movement, indexed by joystick_state << 1, each entry is XXYY, $FF is -1"; }; +range { name "get_ready_msg"; start $9714; end $9726; type bytetable; comment "PLAYER GET READY"; }; +range { name "pcolor0_table"; start $8B7B; end $8b7f; type bytetable; }; +range { name "color0_table"; start $9728; end $972b; type bytetable; }; +range { name "color0_table_minus_one"; start $9727; end $9727; type bytetable; }; +range { name "level_gfx"; start $9C21; end $9cff; type bytetable; comment "definitions for level graphics objects aka shapes. (girder segment, ladder, rope, etc)"; }; +label { name "sh_girder"; addr $9C33; comment "3 rows of pixels. 1st: 04 = 4 pixels wide, 00 00 = no X/Y offset, 01 01 01 01 = actual pixel data (4 color0 pixels). see level_maps.txt"; }; +label { name "sh_blank_4x4"; addr $9C49; }; +label { name "sh_ladder"; addr $9C5F; }; +label { name "sh_9c89"; addr $9c89; comment "dunno what this is yet"; }; +label { name "sh_bomb"; addr $9cb3; }; +label { name "sh_up_rope"; addr $9cc9; }; +label { name "sh_down_rope"; addr $9cda; }; +label { name "sh_9ceb"; addr $9ceb; comment "dunno what this is yet"; }; +range { name "sprite_table"; start $9d00; end $9dff; type bytetable; comment "jumpman's animation frames and other sprites, seem to be 10 bytes per sprite"; }; +range { name "sxf_b319"; start $b319; end $B44B; type bytetable; comment "referenced by routine at $B2FD"; }; +range { name "data_table_b1df"; start $b1df; end $B27d; type bytetable; comment "dunno what this is for yet"; }; +range { name "data_table_b2a8"; start $b2a8; end $B2df; type bytetable; comment "dunno what this is for yet"; }; +range { name "data_table_b50b"; start $b50b; end $B57b; type bytetable; comment "dunno what this is for yet"; }; +range { name "scores_screen_dlist"; start $8C52; end $8C67; type bytetable; comment "a GR.2-ish DL, with DLIs, screen mem at $3000, for player scores screen"; }; +label { name "reyalp_msg_minus_one"; addr $8c67; }; +label { name "show_reyalp_msg"; addr $8BC0; comment "shows PLAYER (backwards loop)"; }; +label { name "reyalp_msg_loop"; addr $8BC2; }; +label { name "check_10th"; addr $8BC8; comment "replace 10th char with the ASCII player number"; }; +label { name "continue_loop"; addr $8BD5; }; +label { name "check_alive"; addr $8BE9; comment "player still has lives left?"; }; +label { name "no_cross"; addr $8BEF; }; +label { name "what_are_we_waiting_for"; addr $8C39; comment "I *think* we're waiting for the music to finish playing..."; }; + +label { name "jiffy_timer_1"; addr $061A; comment "gets incremented every frame"; }; +label { name "jiffy_timer_2"; addr $061B; comment "gets incremented every frame"; }; +label { name "bonus_jiffy_timer"; addr $0626; comment "gets incremented every frame when playing a level, bonus-=100 when this reaches 0"; }; +label { name "speed_jiffy_timer"; addr $061E; comment "counts 0..initial_speed"; }; +label { name "playing_level"; addr $0627; comment "0 = not playing, non-0 = playing"; }; +label { name "no_dec_bonus"; addr $848B; }; +label { name "add_time_bonus"; addr $8E0F; comment "score += time_bonus;"; }; +label { name "lt_64k"; addr $8E27; }; +label { name "wait_32_jiffies"; addr $8E3A; comment "533ms ntsc, 640ms pal"; }; +label { name "pick_random_music"; addr $8E41; comment "pick random sound effect between 4 and 7"; }; +label { name "cue_music"; addr $8F92; comment "setup to play whichever music is in A reg, using 5-byte sfx stuct (a music is a pair of sfx played simultaneously)"; }; +label { name "cue_music_jv"; addr $8018; comment "setup to play whichever music is in A reg, using 5-byte sfx stuct"; }; +label { name "cue_sfx_jv"; addr $8006; comment "setup to play sfx"; }; +label { name "cue_sfx"; addr $8255; comment "setup to play sfx at *sfx_ptr, tempo (?) A"; }; +label { name "cue_sfx_lowprior"; addr $8240; comment "if cue_sfx not already in progress, setup to play sfx at (sfx_slot_tempo, sfx_lock) tempo (?) A"; }; +label { name "sfx_ptr"; addr $063C; size 2; }; +label { name "cue_ok"; addr $8244; size 1; }; +label { name "cue_done"; addr $8278; size 1; }; +label { name "inc_done"; addr $823F; size 1; }; + +label { name "wait_3_sec"; addr $8C4A; comment "wait 192 jiffies: 3.2 sec (ntsc), 3.84 sec (pal)"; }; +label { name "not_alive"; addr $8BEB; comment "no, show a cross instead of a space"; }; +label { name "store_space"; addr $8BE2; comment "$AF is the character to show after the score (space for alive, cross for dead)"; }; +range { name "reyalp_msg"; start $8C68; end $8C7a; type bytetable; comment "player spelled backwards: ' 0 # REYALP '"; }; +range { name "scores_msg"; start $8C7b; end $8C81; type bytetable; comment "' SCORES' in color 3"; }; +range { name "blank_dlist_8add"; start $8ADD; end $8adf; type bytetable; comment "yet another jump-to-itself empty display list"; }; +range { name "blank_dlist_8aeb"; start $8AEB; end $8aed; type bytetable; comment "another jump-to-itself empty display list"; }; +range { name "blank_dlist_8c82"; start $8C82; end $8C84; type bytetable; comment "looks like an empty jump-to-itself dlist"; }; +label { name "init_game"; addr $9000; comment "called from cart_entry_point routine"; }; +label { name "reinit_game"; addr $900C; comment "this entry point doesn't disable start/option keys"; }; +label { name "try_to_write_rom"; addr $9022; comment "seems to try to write $FF bytes to ROM that already contains $FF's (it's the solid block character in the font). possibly left over from early development before conversion to cartridge"; }; +label { name "setup_select_key_vec"; addr $901b; comment "set select key vector to ask_num_players at $9400, enable select key"; }; +label { name "setup_select_key_vec_again"; addr $9517; comment "set select key vector to ask_num_players at $9400, enable select key"; }; +label { name "disable_start_opt"; addr $94EC; comment "disable start and option keys"; }; +label { name "init_speed"; addr $952a; comment "initialize speed to -1"; }; +label { name "wait_for_speed"; addr $952F; comment "wait for keyboard IRQ handler to set a speed <= 8"; }; +label { name "speed_to_ascii"; addr $9540; comment "convert to ASCII digit"; }; +label { name "add_11_to_x"; addr $953B; comment "11-byte per-player struct?"; }; +label { name "struct_player_lives_offsets_minus_one"; addr $8C88; }; +label { name "struct_player_lives_offsets"; addr $8C89; comment "lookup table, offset from $713 to lives for indexed player"; }; +label { name "show_scores_screen"; addr $8C22; comment "set dlist shadow to scores_screen_dlist"; }; +label { name "display_speed"; addr $9542; comment "show it to the user"; }; +label { name "speed_value"; addr $06F9; comment "decoded speed (1-8)"; }; +label { name "show_player_speed_prompt"; addr $94F9; comment "copy PLAYER #n SPEED? to screen RAM"; }; +label { name "psprompt_loop"; addr $94fb; }; +range { name "get_ready_dlist"; start $972c; end $973f; type bytetable; comment "112 blank scanlines, then one GR.2 line, loaded from $0742"; }; +range { name "score_offsets"; start $8C85; end $8c8c; type bytetable; comment "offsets into screen memory, column 12, rows 2 3 4 5, used by code at $8BEF, loaded in $d3, hi byte in $d4 is $30"; }; +label { name "score_screen_dli_sr"; addr $8C8D; comment "used by score screen"; }; +label { name "set_score_screen_dli"; addr $8C31; comment "dli = score_screen_dli_sr"; }; +range { name "title_screen_data"; start $91cf; end $93ff; type bytetable; comment "title screen data"; }; + +label { name "title_screen_data_minus_one"; addr $91ce; }; +label { name "copy_title_screen"; addr $902A; }; +label { name "wait_until_9c_is_0e"; addr $906E; comment "some ISR is writing to $9c..."; }; +label { name "funky_init_loop"; addr $90C8; comment "lot going on here, not understood yet"; }; +label { name "player_scores_screen"; addr $8B80; comment "show scores, called at end of game, also called after beating level 12 (after WELL DONE). $40 in NMIEN = disable DLI, enable VBI"; }; +label { name "read_joystick"; addr $84AC; comment "always joystick #1 (all players use the same joystick and pass it around)"; }; +label { name "check_joystick_enabled"; addr $84A4; comment "read the joystick if not disabled"; }; +label { name "fake_read_trigger"; addr $84CD; comment "??"; }; +label { name "read_trigger"; addr $84D3; comment "always joystick #1"; }; +label { name "store_joystick_state"; addr $84B1; comment "store bottom 4 bits of PORTA, or 0 if joystick_disabled"; }; +label { name "clear_collisions"; addr $850D; }; +label { name "update_dlist"; addr $8510; comment "update display list, if there's a new one in the shadow reg"; }; +label { name "update_dli_vector"; addr $8523; comment "update DLI vector, if there's a new one in the shadow reg"; }; +label { name "setup_get_ready_dl"; addr $964A; comment "06ac/06ad gets address of get_ready_dlist (why not SDLSTL/H?)"; }; +label { name "end_of_level_bonus"; addr $B800; }; +label { name "keycode_table_minus_one"; addr $9c18; }; +range { name "keyboard_isr"; start $9C00; end $9c18; type code; comment "only use of keyboard is to enter player speed before starting game"; }; +range { name "keycode_table"; start $9C19; end $9c20; type bytetable; }; +#label { name "mul_25_table"; addr $B8A7; size 2; }; + +label { name "init_hardware"; addr $837c; }; +label { name "init_page6_loop"; addr $837e; comment "movement_direction_table+31 should read data_table_85de-1, da65 isn't perfect yet"; }; + +# these are so far only for player 1 +label { name "number_of_players"; addr $06f4; size 1; comment "0 for single-player game, otherwise range 1-3 (2 to 4 players)"; }; +label { name "score"; addr $0700; size 3; }; +label { name "level"; addr $06f6; size 1; }; +label { name "lives"; addr $070a; size 1; }; +label { name "current_player"; addr $06fe; size 1; comment "*think* this ranges 1-4, not 0-3"; }; +label { name "player_speed"; addr $0624; size 1; }; +label { name "initial_speed"; addr $0625; size 1; }; +label { name "setup_dli_2"; addr $bc3f; size 1; comment "load dli_service_2 address into dli shadow"; }; +label { name "silence_audio"; addr $875B; size 1; comment "set all AUDFx to 0"; }; +label { name "sa_loop"; addr $875F; size 1; }; +label { name "store_audc"; addr $8DC6; size 1; comment "store A to AUDCx (and its ?shadow?)"; }; +label { name "set_prior"; addr $8798; size 1; comment "priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles) [redundant? init_set_prior sets this, nothing appears to change it]"; }; +label { name "SAVMSC"; addr $58; size 2; comment "OS's idea of the start of screen memory [redundant to set here?]"; }; +label { name "set_char_base"; addr $83BB; size 1; comment "use character set at $9e00 aka charset"; }; +label { name "set_savmsc"; addr $83E9; size 1; comment "tell OS that screen memory starts at $3000"; }; +label { name "position_player_5"; addr $8310; size 1; comment "position the 4 missiles side-by-side"; }; +label { name "init_set_prior"; addr $8399; size 1; comment "priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles)"; }; +label { name "joystick_disabled"; addr $0632; size 1; comment "nonzero = jumpman can't move (title screen or materialization, etc)"; }; +label { name "joystick_state"; addr $0633; size 1; comment "last PORTA read (bottom 4 bits), or 0 if joystick_disabled"; }; +label { name "trigger_disabled"; addr $0634; size 1; comment "nonzero = jumpman can't jump (he's already jumping, or title screen or materialization, etc)"; }; +label { name "trigger_state"; addr $0635; size 1; comment "last TRIG0 read (0 = pressed)"; }; +label { name "check_trigger_state"; addr $984D; size 1; comment "did user press the trigger?"; }; +label { name "trig_jmp"; addr $9852; size 1; comment "yes, jump to handler"; }; +label { name "check_up_down"; addr $9855; size 1; comment "did user move joystick up/down?"; }; +label { name "check_up_down_2"; addr $993B; size 1; comment "did user move joystick up/down?"; }; +label { name "trigger_handler"; addr $9985; size 1; comment "handle trigger presses (maybe start a jump)"; }; +label { name "cud_jmp"; addr $9860; size 1; comment "no, jump over handler"; }; +label { name "player_delta_x"; addr $0630; size 1; comment "amount to move jumpman this frame (1 or $FF aka -1)"; }; +label { name "player_delta_y"; addr $0631; size 1; comment "amount to move jumpman this frame (1 or $FF aka -1)"; }; +label { name "dli_vec_shadow_hi"; addr $06AF; size 1; comment "stored in VDSLST if nonzero"; }; +label { name "dli_vec_shadow_lo"; addr $06ae; size 1; comment "stored in VDSLST if dli_vec_shadow_hi nonzero"; }; +label { name "dlist_shadow_hi"; addr $06AD; size 1; comment "stored in DLISTH if nonzero"; }; +label { name "dlist_shadow_lo"; addr $06ac; size 1; comment "stored in DLISTL if dlist_shadow_hi nonzero"; }; +label { name "clear_dlist_shadow"; addr $851E; size 1; comment "clear the shadow now that we've updated the HW"; }; +label { name "clear_dli_shadow"; addr $8531; size 1; comment "clear the shadow now that we've updated the HW"; }; +label { name "enable_dli"; addr $8536; size 1; comment "enable DLI now that we've set up the vector"; }; +label { name "enable_keyboard_irq"; addr $8554; size 1; comment "$C0 = regular keypress, break keypress"; }; +label { name "silence_console_speaker"; addr $855A; size 1; comment "8 = silent (0 would be a click)"; }; +label { name "check_start_key"; addr $8561; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "check_select_key"; addr $8573; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "check_option_key"; addr $8580; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "setup_start_key_vec"; addr $9465; size 1; comment "we'll jump to $94de aka get_player_speeds when start key is pressed"; }; +label { name "get_player_speeds"; addr $94de; size 1; comment "loop up to 4 times, ask PLAYER #n SPEED? and wait for number key press"; }; +label { name "setup_option_key_vec"; addr $9458; size 1; comment "we'll jump to $9489 aka option_key_handler when option key is pressed"; }; +label { name "start_key_vec"; addr $06c4; size 2; comment "vblank_imm_isr jumps thru here if start key pressed"; }; +label { name "select_key_vec"; addr $06c2; size 2; comment "vblank_imm_isr jumps thru here if select key pressed"; }; +label { name "option_key_vec"; addr $06c0; size 2; comment "vblank_imm_isr jumps thru here if option key pressed"; }; +label { name "start_key_enabled"; addr $06C8; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "select_key_enabled"; addr $06C7; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "option_key_enabled"; addr $06C6; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "zp_temp1"; addr $cb; size 2; comment "used for (zp,y) addressing, also for checking console keys in vblank_imm_isr"; }; +label { name "hang_main_thread"; addr $9486; size 1; comment "initialization done, everything's done in interrupts from here on out"; }; +label { name "option_key_handler"; addr $9489; size 1; comment "called via option_key_vec when someone presses option"; }; + +label { name "level_finished"; addr $8E00; size 1; }; +label { name "level_finished_jv"; addr $802D; size 1; }; +label { name "decrement_time_bonus"; addr $8DCE; size 1; comment "bonus -= 100;"; }; +label { name "decrement_time_bonus_jv"; addr $8021; size 1; comment "bonus -= 100;"; }; +label { name "check_bonus_0"; addr $8DD7; size 1; comment "don't decrement if bonus == 0"; }; +label { name "dec_done"; addr $8DF9; size 1; }; +label { name "bonus_lt_256"; addr $8DE7; size 1; }; + +label { name "set_y"; addr $8F9B; size 1; comment "y = a * 5; // offset into mus_struct_table"; }; + + +label { name "show_level_name"; addr $BA5D; size 1; comment "copy level name into screen RAM"; }; +label { name "sync_to_music"; addr $BA71; size 1; comment "level is already drawn with all color regs set to black. for each color reg, wait 1 sec before turning it visible. this syncs up with the music because the music was written to sync with this actually"; }; +label { name "wait_1_sec"; addr $BA9E; size 1; comment "actually 64 jiffies, 1.067S ntsc, 1.28s pal"; }; +label { name "keep_waiting"; addr $BAA3; size 1; }; +label { name "enable_joystick"; addr $8775; size 1; comment "called after level-intro music is finished playing"; }; +label { name "enable_joystick_jv"; addr $801B; size 1; comment "called after level-intro music is finished playing"; }; +label { name "ej_loop"; addr $8777; size 1; }; +label { name "hide_player"; addr $8DB8; size 1; comment "move player selected by X reg minus one off the left edge of the screen"; }; +label { name "play_select_key_sfx"; addr $946F; size 1; comment "play sfx_select_key at $95f1"; }; +label { name "wait_sfx"; addr $947C; size 1; comment "wait for sound to finish playing"; }; +label { name "play_life_bonus_sfx"; addr $B868; size 1; comment "play once per life"; }; +label { name "add_life_bonus"; addr $B83B; size 1; }; +label { name "sfx_option_pressed"; addr $8ab0; size 1; }; +label { name "play_opt_key_sfx"; addr $94BC; size 1; }; +label { name "wait_opt_key_sfx"; addr $94CE; size 1; comment "wait until it's done playing"; }; +range { name "map_b11a"; start $B11A; end $b120; type bytetable; comment "dunno what this is for yet"; }; +label { name "block_char_minus_one"; addr $9e0f; size 1; comment "couple of places in the code try to write here"; }; +label { name "position_players"; addr $82E9; size 1; comment "X counts down 5..1 (starts at 6, immediately decremented, and loop is done with 0). zp_temp1 is ZP pointer to the current player or missile being written to ($2f00..$2b00, or p3/p2/p1/p0/missiles)."; }; +label { name "HPOSP0_minus_two"; addr $CFFE; size 1; }; +label { name "position_pm_vert"; addr $8322; size 1; }; +label { name "clear_pm"; addr $8342; size 1; comment "write zeroes to unused portion of this player/missile"; }; +label { name "position_done"; addr $82E8; size 1; }; +label { name "clear_pm_mem"; addr $872A; size 1; comment "clear P/M mem"; }; +label { name "clear_screen_mem"; addr $8714; size 1; comment "clear the gameboard screen memory (called before drawing a level, natch)"; }; +label { name "clear_screen_mem_jv"; addr $801E; size 1; comment "clear the gameboard screen memory (called before drawing a level, natch)"; }; +label { name "csm_loop"; addr $871F; size 1; }; +label { name "dm_obj_to_screen"; addr $80BD; size 1; comment "actually write the object's pixels to screen memory. quite hairy."; }; +label { name "unused_vecs"; addr $803F; size 1; comment "3 unused jump vectors, all pointed to the same RTS"; }; +label { name "unused_vec_rts"; addr $8048; size 1; comment "unused jump vectors point here"; }; +label { name "sfx_bounce_1"; addr $8A4B; size 1; comment "used when jumpman is falling?"; }; +range { name "sfx_bounce_2"; start $8a97; end $8abf; type bytetable; comment "used when jumpman is falling?"; }; +label { name "sfx_death"; addr $8a60; comment "jumpman hit by bullet or started falling"; }; +label { name "play_sfx_bounce_2"; addr $8A80; }; +label { name "play_sfx_bounce_1"; addr $899A; }; +label { name "falling_bounce"; addr $8983; comment "this looks like it hurts..."; }; +label { name "afterlife"; addr $9600; comment "multiple code paths jump here. replay level, load next level, or go back to ask_num_players"; }; +label { name "code_bd52"; addr $BD52; comment "referenced by code at $BC83"; }; +label { name "crumble_gameboard"; addr $8D00; comment "just lost your last life"; }; +label { name "crumble_gameboard_jv"; addr $8030; comment "just lost your last life"; }; +label { name "init_page_7"; addr $9A5C; }; +label { name "init_page_7_jv"; addr $8024; }; +range { name "data_9a71"; start $9A71; end $9a7b; type bytetable; comment "used by code above"; }; +range { name "l_equals"; start $8CFD; end $8CFF; type bytetable; comment "L= (for lives display)"; }; +label { name "add_extra_life"; addr $8CE4; comment "plays sfx_extra_life"; }; +label { name "show_l_equals"; addr $8CCE; comment "L= (for lives display)"; }; +label { name "show_lives_icons"; addr $86BB; comment "up to 6 jumpmen, and a + if lives > 6. char $C1 = jumpman icon, $CB = plus sign"; }; +label { name "show_current_player"; addr $86A7; comment "1 to 4"; }; +label { name "update_status_window"; addr $8694; comment "bottom 2 GR.1 lines on the game board"; }; +label { name "update_status_window_jv"; addr $8012; comment "bottom 2 GR.1 lines on the game board"; }; +label { name "setup_gameboard_dlist"; addr $9B00; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; +label { name "setup_gameboard_dlist_jv"; addr $8015; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; +label { name "xxx_level_something"; addr $8600; comment "gets called after the level is drawn & the intro music stops, and also during the level (?)"; }; +label { name "xxx_level_something_jv"; addr $8009; comment "gets called after the level is drawn & the intro music stops, and also during the level (?)"; }; +label { name "draw_map"; addr $8049; comment "the entry point for parsing the level map and drawing graphics from it. see level_maps.txt. caller must set $C0/$C1 to the address of the map data. modders beware: bogus map data can & will cause infinite loops."; }; +label { name "draw_map_jv"; addr $8000; comment "the entry point for parsing the level map and drawing graphics from it. see level_maps.txt."; }; +label { name "dm_get_opcode"; addr $804B; comment "$C0/$C1 points to $A300 (level00_desc) on the first call"; }; +label { name "dm_switch_opcode"; addr $804D; comment "map opcodes: $FC = jump, $FF = end, $FD = set drawing direction, $FE = select graphics object"; }; +label { name "dm_draw_gfx"; addr $8090; comment "handle gfx_draw opcode"; }; +label { name "dm_jump"; addr $805C; comment "handle gfx_jump opcode"; }; +label { name "dm_delta"; addr $806B; comment "handle gfx_delta opcode"; }; +label { name "dm_obj"; addr $8083; comment "handle gfx_object opcode"; }; +label { name "dm_fallthru"; addr $805B; comment "handle gfx_end opcode"; }; +label { name "dm_next_opcode"; addr $8075; comment "all the other opcode handlers jump here"; }; +label { name "dm_progctr"; addr $C0; size 2; comment "see draw_map and level_maps.txt"; }; +label { name "dm_delta_x"; addr $C9; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_delta_y"; addr $CA; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_objptr"; addr $C2; size 2; comment "see draw_map and level_maps.txt"; }; +label { name "dm_xpos"; addr $55; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_ypos"; addr $54; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_length"; addr $BF; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_draw_loop"; addr $809C; size 1; comment "loop 'dm_length' times"; }; +label { name "dm_draw_obj"; addr $80B4; size 1; comment "draw current object at current x/y position"; }; +label { name "dm_draw_obj_loop"; addr $80B6; size 1; comment "object definition ends with $FF"; }; +label { name "dm_count"; addr $BE; size 1; comment "graphics object definition is this long"; }; +label { name "dm_x_with_offset"; addr $C6; size 1; comment "graphics object X offset, plus dm_xpos"; }; +label { name "dm_y_with_offset"; addr $C7; size 1; comment "graphics object Y offset, plus dm_xpos"; }; +label { name "dm_screen_addr"; addr $C4; size 2; comment "points to byte to write gfx data to"; }; +label { name "calc_screen_addr"; addr $80D0; size 1; comment "calculate 40 * dm_y_with_offset + dm_x_with_offset + screen mem address, store in dm_screen_addr"; }; +label { name "store_rts"; addr $83B6; comment "store an RTS at $06E6, which will get JSR'ed to by unused level subroutines"; }; +label { name "well_done_screen"; addr $BC00; comment "the WELL DONE screen, when you beat all the levels. after this, the game plays random levels."; }; +label { name "cue_woop_sound"; addr $B4D3; }; +label { name "sfx_woop"; addr $B564; }; +label { name "got_all_bombs"; addr $9766; }; +label { name "call_eol_sub"; addr $976C; }; + +# end of main.info, everything below here is generated by mklevelinfo.pl +label { name "work_level_desc"; addr $0780; size 2; comment "first 2 bytes are level number in screencodes"; }; +label { name "work_level_sub0"; addr $0782; size 2; comment "a subroutine"; }; +label { name "work_level_sub1"; addr $0784; size 2; comment "a subroutine"; }; +label { name "work_level_sub2"; addr $0786; size 2; comment "a subroutine"; }; +label { name "work_level_sub3"; addr $0788; size 2; comment "a subroutine"; }; +label { name "work_level_num_bombs"; addr $078a; size 1; comment "number of bombs to pick up on this level"; }; +label { name "work_level_bullet_chance"; addr $078b; size 1; comment "0 = no bullets"; }; +label { name "work_level_y_start"; addr $078c; size 1; comment "jumpman starting Y position"; }; +label { name "work_level_x_start"; addr $078d; size 1; comment "jumpman starting X position"; }; +label { name "work_level_offs_14"; addr $078e; size 2; comment "points to $0600"; }; +label { name "work_level_points_per_bomb"; addr $0790; size 1; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +label { name "work_level_time_bonus"; addr $0791; size 2; comment "amount of time bonus at start of level"; }; +label { name "work_level_offs_19"; addr $0793; size 1; comment "always $00"; }; +label { name "work_level_unkn_table0"; addr $0794; size 2; comment "pointer to ROM table or $06xx"; }; +label { name "work_level_map0"; addr $0796; size 2; comment "map data"; }; +label { name "work_level_map1"; addr $0798; size 2; comment "map data"; }; +label { name "work_level_map2"; addr $079a; size 2; comment "map data"; }; +label { name "work_level_unkn_table1"; addr $079c; size 2; comment "unknown, pointer to a ROM table or $0000"; }; +label { name "work_level_offs_30"; addr $079e; size 2; comment "always $0000"; }; +label { name "work_level_sub4"; addr $07a0; size 2; comment "$06E6 for most levels, or else a ROM subroutine"; }; +label { name "work_level_sub5"; addr $07a2; size 2; comment "$06E6 for some levels, or else a ROM subroutine"; }; +label { name "work_level_sub6"; addr $07a4; size 2; comment "always $9740 aka game_main_loop"; }; +label { name "work_level_sub_eol"; addr $07a6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +label { name "work_level_offs_40"; addr $07a8; size 6; comment "all zeroes"; }; +label { name "work_level_offs_46"; addr $07ae; size 9; comment "unknown"; }; +label { name "work_level_offs_55"; addr $07b7; size 3; comment "unknown, always $00 $00 $00"; }; +label { name "work_level_offs_58"; addr $07ba; size 2; comment "unknown, not a ROM address"; }; +label { name "work_level_offs_60"; addr $07bc; size 4; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +label { name "cur_level_desc"; addr $07c0; size 2; comment "first 2 bytes are level number in screencodes"; }; +label { name "cur_level_sub0"; addr $07c2; size 2; comment "a subroutine"; }; +label { name "cur_level_sub1"; addr $07c4; size 2; comment "a subroutine"; }; +label { name "cur_level_sub2"; addr $07c6; size 2; comment "a subroutine"; }; +label { name "cur_level_sub3"; addr $07c8; size 2; comment "a subroutine"; }; +label { name "cur_level_num_bombs"; addr $07ca; size 1; comment "number of bombs to pick up on this level"; }; +label { name "cur_level_bullet_chance"; addr $07cb; size 1; comment "0 = no bullets"; }; +label { name "cur_level_y_start"; addr $07cc; size 1; comment "jumpman starting Y position"; }; +label { name "cur_level_x_start"; addr $07cd; size 1; comment "jumpman starting X position"; }; +label { name "cur_level_offs_14"; addr $07ce; size 2; comment "points to $0600"; }; +label { name "cur_level_points_per_bomb"; addr $07d0; size 1; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +label { name "cur_level_time_bonus"; addr $07d1; size 2; comment "amount of time bonus at start of level"; }; +label { name "cur_level_offs_19"; addr $07d3; size 1; comment "always $00"; }; +label { name "cur_level_unkn_table0"; addr $07d4; size 2; comment "pointer to ROM table or $06xx"; }; +label { name "cur_level_map0"; addr $07d6; size 2; comment "map data"; }; +label { name "cur_level_map1"; addr $07d8; size 2; comment "map data"; }; +label { name "cur_level_map2"; addr $07da; size 2; comment "map data"; }; +label { name "cur_level_unkn_table1"; addr $07dc; size 2; comment "unknown, pointer to a ROM table or $0000"; }; +label { name "cur_level_offs_30"; addr $07de; size 2; comment "always $0000"; }; +label { name "cur_level_sub4"; addr $07e0; size 2; comment "$06E6 for most levels, or else a ROM subroutine"; }; +label { name "cur_level_sub5"; addr $07e2; size 2; comment "$06E6 for some levels, or else a ROM subroutine"; }; +label { name "cur_level_sub6"; addr $07e4; size 2; comment "always $9740 aka game_main_loop"; }; +label { name "cur_level_sub_eol"; addr $07e6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +label { name "cur_level_offs_40"; addr $07e8; size 6; comment "all zeroes"; }; +label { name "cur_level_offs_46"; addr $07ee; size 9; comment "unknown"; }; +label { name "cur_level_offs_55"; addr $07f7; size 3; comment "unknown, always $00 $00 $00"; }; +label { name "cur_level_offs_58"; addr $07fa; size 2; comment "unknown, not a ROM address"; }; +label { name "cur_level_offs_60"; addr $07fc; size 4; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level00_desc"; start $a000; end $a001; type bytetable; comment "64-byte level descriptors, 12 of them (1 per level). first 2 bytes are level number in screencodes"; }; +range { name "level00_sub0"; start $a002; end $a003; type addrtable; comment "a subroutine"; }; +range { name "level00_sub1"; start $a004; end $a005; type addrtable; comment "a subroutine"; }; +range { name "level00_sub2"; start $a006; end $a007; type addrtable; comment "a subroutine"; }; +range { name "level00_sub3"; start $a008; end $a009; type addrtable; comment "a subroutine"; }; +range { name "level00_num_bombs"; start $a00a; end $a00a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level00_bullet_chance"; start $a00b; end $a00b; type bytetable; comment "0 = no bullets"; }; +range { name "level00_y_start"; start $a00c; end $a00c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level00_x_start"; start $a00d; end $a00d; type bytetable; comment "jumpman starting X position"; }; +range { name "level00_offs_14"; start $a00e; end $a00f; type bytetable; comment "points to $0600"; }; +range { name "level00_points_per_bomb"; start $a010; end $a010; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level00_time_bonus"; start $a011; end $a012; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level00_offs_19"; start $a013; end $a013; type bytetable; comment "always $00"; }; +range { name "level00_unkn_table0"; start $a014; end $a015; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level00_map0"; start $a016; end $a017; type addrtable; comment "map data"; }; +range { name "level00_map1"; start $a018; end $a019; type addrtable; comment "map data"; }; +range { name "level00_map2"; start $a01a; end $a01b; type addrtable; comment "map data"; }; +range { name "level00_unkn_table1"; start $a01c; end $a01d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level00_offs_30"; start $a01e; end $a01f; type bytetable; comment "always $0000"; }; +range { name "level00_sub4"; start $a020; end $a021; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level00_sub5"; start $a022; end $a023; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level00_sub6"; start $a024; end $a025; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level00_sub_eol"; start $a026; end $a027; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level00_offs_40"; start $a028; end $a02d; type bytetable; comment "all zeroes"; }; +range { name "level00_offs_46"; start $a02e; end $a036; type bytetable; comment "unknown"; }; +range { name "level00_offs_55"; start $a037; end $a039; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level00_offs_58"; start $a03a; end $a03b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level00_offs_60"; start $a03c; end $a03f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level01_desc"; start $a040; end $a041; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level01_sub0"; start $a042; end $a043; type addrtable; comment "a subroutine"; }; +range { name "level01_sub1"; start $a044; end $a045; type addrtable; comment "a subroutine"; }; +range { name "level01_sub2"; start $a046; end $a047; type addrtable; comment "a subroutine"; }; +range { name "level01_sub3"; start $a048; end $a049; type addrtable; comment "a subroutine"; }; +range { name "level01_num_bombs"; start $a04a; end $a04a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level01_bullet_chance"; start $a04b; end $a04b; type bytetable; comment "0 = no bullets"; }; +range { name "level01_y_start"; start $a04c; end $a04c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level01_x_start"; start $a04d; end $a04d; type bytetable; comment "jumpman starting X position"; }; +range { name "level01_offs_14"; start $a04e; end $a04f; type bytetable; comment "points to $0600"; }; +range { name "level01_points_per_bomb"; start $a050; end $a050; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level01_time_bonus"; start $a051; end $a052; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level01_offs_19"; start $a053; end $a053; type bytetable; comment "always $00"; }; +range { name "level01_unkn_table0"; start $a054; end $a055; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level01_map0"; start $a056; end $a057; type addrtable; comment "map data"; }; +range { name "level01_map1"; start $a058; end $a059; type addrtable; comment "map data"; }; +range { name "level01_map2"; start $a05a; end $a05b; type addrtable; comment "map data"; }; +range { name "level01_unkn_table1"; start $a05c; end $a05d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level01_offs_30"; start $a05e; end $a05f; type bytetable; comment "always $0000"; }; +range { name "level01_sub4"; start $a060; end $a061; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level01_sub5"; start $a062; end $a063; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level01_sub6"; start $a064; end $a065; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level01_sub_eol"; start $a066; end $a067; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level01_offs_40"; start $a068; end $a06d; type bytetable; comment "all zeroes"; }; +range { name "level01_offs_46"; start $a06e; end $a076; type bytetable; comment "unknown"; }; +range { name "level01_offs_55"; start $a077; end $a079; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level01_offs_58"; start $a07a; end $a07b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level01_offs_60"; start $a07c; end $a07f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level02_desc"; start $a080; end $a081; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level02_sub0"; start $a082; end $a083; type addrtable; comment "a subroutine"; }; +range { name "level02_sub1"; start $a084; end $a085; type addrtable; comment "a subroutine"; }; +range { name "level02_sub2"; start $a086; end $a087; type addrtable; comment "a subroutine"; }; +range { name "level02_sub3"; start $a088; end $a089; type addrtable; comment "a subroutine"; }; +range { name "level02_num_bombs"; start $a08a; end $a08a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level02_bullet_chance"; start $a08b; end $a08b; type bytetable; comment "0 = no bullets"; }; +range { name "level02_y_start"; start $a08c; end $a08c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level02_x_start"; start $a08d; end $a08d; type bytetable; comment "jumpman starting X position"; }; +range { name "level02_offs_14"; start $a08e; end $a08f; type bytetable; comment "points to $0600"; }; +range { name "level02_points_per_bomb"; start $a090; end $a090; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level02_time_bonus"; start $a091; end $a092; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level02_offs_19"; start $a093; end $a093; type bytetable; comment "always $00"; }; +range { name "level02_unkn_table0"; start $a094; end $a095; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level02_map0"; start $a096; end $a097; type addrtable; comment "map data"; }; +range { name "level02_map1"; start $a098; end $a099; type addrtable; comment "map data"; }; +range { name "level02_map2"; start $a09a; end $a09b; type addrtable; comment "map data"; }; +range { name "level02_unkn_table1"; start $a09c; end $a09d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level02_offs_30"; start $a09e; end $a09f; type bytetable; comment "always $0000"; }; +range { name "level02_sub4"; start $a0a0; end $a0a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level02_sub5"; start $a0a2; end $a0a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level02_sub6"; start $a0a4; end $a0a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level02_sub_eol"; start $a0a6; end $a0a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level02_offs_40"; start $a0a8; end $a0ad; type bytetable; comment "all zeroes"; }; +range { name "level02_offs_46"; start $a0ae; end $a0b6; type bytetable; comment "unknown"; }; +range { name "level02_offs_55"; start $a0b7; end $a0b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level02_offs_58"; start $a0ba; end $a0bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level02_offs_60"; start $a0bc; end $a0bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level03_desc"; start $a0c0; end $a0c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level03_sub0"; start $a0c2; end $a0c3; type addrtable; comment "a subroutine"; }; +range { name "level03_sub1"; start $a0c4; end $a0c5; type addrtable; comment "a subroutine"; }; +range { name "level03_sub2"; start $a0c6; end $a0c7; type addrtable; comment "a subroutine"; }; +range { name "level03_sub3"; start $a0c8; end $a0c9; type addrtable; comment "a subroutine"; }; +range { name "level03_num_bombs"; start $a0ca; end $a0ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level03_bullet_chance"; start $a0cb; end $a0cb; type bytetable; comment "0 = no bullets"; }; +range { name "level03_y_start"; start $a0cc; end $a0cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level03_x_start"; start $a0cd; end $a0cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level03_offs_14"; start $a0ce; end $a0cf; type bytetable; comment "points to $0600"; }; +range { name "level03_points_per_bomb"; start $a0d0; end $a0d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level03_time_bonus"; start $a0d1; end $a0d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level03_offs_19"; start $a0d3; end $a0d3; type bytetable; comment "always $00"; }; +range { name "level03_unkn_table0"; start $a0d4; end $a0d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level03_map0"; start $a0d6; end $a0d7; type addrtable; comment "map data"; }; +range { name "level03_map1"; start $a0d8; end $a0d9; type addrtable; comment "map data"; }; +range { name "level03_map2"; start $a0da; end $a0db; type addrtable; comment "map data"; }; +range { name "level03_unkn_table1"; start $a0dc; end $a0dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level03_offs_30"; start $a0de; end $a0df; type bytetable; comment "always $0000"; }; +range { name "level03_sub4"; start $a0e0; end $a0e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level03_sub5"; start $a0e2; end $a0e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level03_sub6"; start $a0e4; end $a0e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level03_sub_eol"; start $a0e6; end $a0e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level03_offs_40"; start $a0e8; end $a0ed; type bytetable; comment "all zeroes"; }; +range { name "level03_offs_46"; start $a0ee; end $a0f6; type bytetable; comment "unknown"; }; +range { name "level03_offs_55"; start $a0f7; end $a0f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level03_offs_58"; start $a0fa; end $a0fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level03_offs_60"; start $a0fc; end $a0ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level04_desc"; start $a100; end $a101; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level04_sub0"; start $a102; end $a103; type addrtable; comment "a subroutine"; }; +range { name "level04_sub1"; start $a104; end $a105; type addrtable; comment "a subroutine"; }; +range { name "level04_sub2"; start $a106; end $a107; type addrtable; comment "a subroutine"; }; +range { name "level04_sub3"; start $a108; end $a109; type addrtable; comment "a subroutine"; }; +range { name "level04_num_bombs"; start $a10a; end $a10a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level04_bullet_chance"; start $a10b; end $a10b; type bytetable; comment "0 = no bullets"; }; +range { name "level04_y_start"; start $a10c; end $a10c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level04_x_start"; start $a10d; end $a10d; type bytetable; comment "jumpman starting X position"; }; +range { name "level04_offs_14"; start $a10e; end $a10f; type bytetable; comment "points to $0600"; }; +range { name "level04_points_per_bomb"; start $a110; end $a110; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level04_time_bonus"; start $a111; end $a112; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level04_offs_19"; start $a113; end $a113; type bytetable; comment "always $00"; }; +range { name "level04_unkn_table0"; start $a114; end $a115; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level04_map0"; start $a116; end $a117; type addrtable; comment "map data"; }; +range { name "level04_map1"; start $a118; end $a119; type addrtable; comment "map data"; }; +range { name "level04_map2"; start $a11a; end $a11b; type addrtable; comment "map data"; }; +range { name "level04_unkn_table1"; start $a11c; end $a11d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level04_offs_30"; start $a11e; end $a11f; type bytetable; comment "always $0000"; }; +range { name "level04_sub4"; start $a120; end $a121; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level04_sub5"; start $a122; end $a123; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level04_sub6"; start $a124; end $a125; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level04_sub_eol"; start $a126; end $a127; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level04_offs_40"; start $a128; end $a12d; type bytetable; comment "all zeroes"; }; +range { name "level04_offs_46"; start $a12e; end $a136; type bytetable; comment "unknown"; }; +range { name "level04_offs_55"; start $a137; end $a139; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level04_offs_58"; start $a13a; end $a13b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level04_offs_60"; start $a13c; end $a13f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level05_desc"; start $a140; end $a141; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level05_sub0"; start $a142; end $a143; type addrtable; comment "a subroutine"; }; +range { name "level05_sub1"; start $a144; end $a145; type addrtable; comment "a subroutine"; }; +range { name "level05_sub2"; start $a146; end $a147; type addrtable; comment "a subroutine"; }; +range { name "level05_sub3"; start $a148; end $a149; type addrtable; comment "a subroutine"; }; +range { name "level05_num_bombs"; start $a14a; end $a14a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level05_bullet_chance"; start $a14b; end $a14b; type bytetable; comment "0 = no bullets"; }; +range { name "level05_y_start"; start $a14c; end $a14c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level05_x_start"; start $a14d; end $a14d; type bytetable; comment "jumpman starting X position"; }; +range { name "level05_offs_14"; start $a14e; end $a14f; type bytetable; comment "points to $0600"; }; +range { name "level05_points_per_bomb"; start $a150; end $a150; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level05_time_bonus"; start $a151; end $a152; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level05_offs_19"; start $a153; end $a153; type bytetable; comment "always $00"; }; +range { name "level05_unkn_table0"; start $a154; end $a155; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level05_map0"; start $a156; end $a157; type addrtable; comment "map data"; }; +range { name "level05_map1"; start $a158; end $a159; type addrtable; comment "map data"; }; +range { name "level05_map2"; start $a15a; end $a15b; type addrtable; comment "map data"; }; +range { name "level05_unkn_table1"; start $a15c; end $a15d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level05_offs_30"; start $a15e; end $a15f; type bytetable; comment "always $0000"; }; +range { name "level05_sub4"; start $a160; end $a161; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level05_sub5"; start $a162; end $a163; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level05_sub6"; start $a164; end $a165; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level05_sub_eol"; start $a166; end $a167; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level05_offs_40"; start $a168; end $a16d; type bytetable; comment "all zeroes"; }; +range { name "level05_offs_46"; start $a16e; end $a176; type bytetable; comment "unknown"; }; +range { name "level05_offs_55"; start $a177; end $a179; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level05_offs_58"; start $a17a; end $a17b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level05_offs_60"; start $a17c; end $a17f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level06_desc"; start $a180; end $a181; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level06_sub0"; start $a182; end $a183; type addrtable; comment "a subroutine"; }; +range { name "level06_sub1"; start $a184; end $a185; type addrtable; comment "a subroutine"; }; +range { name "level06_sub2"; start $a186; end $a187; type addrtable; comment "a subroutine"; }; +range { name "level06_sub3"; start $a188; end $a189; type addrtable; comment "a subroutine"; }; +range { name "level06_num_bombs"; start $a18a; end $a18a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level06_bullet_chance"; start $a18b; end $a18b; type bytetable; comment "0 = no bullets"; }; +range { name "level06_y_start"; start $a18c; end $a18c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level06_x_start"; start $a18d; end $a18d; type bytetable; comment "jumpman starting X position"; }; +range { name "level06_offs_14"; start $a18e; end $a18f; type bytetable; comment "points to $0600"; }; +range { name "level06_points_per_bomb"; start $a190; end $a190; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level06_time_bonus"; start $a191; end $a192; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level06_offs_19"; start $a193; end $a193; type bytetable; comment "always $00"; }; +range { name "level06_unkn_table0"; start $a194; end $a195; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level06_map0"; start $a196; end $a197; type addrtable; comment "map data"; }; +range { name "level06_map1"; start $a198; end $a199; type addrtable; comment "map data"; }; +range { name "level06_map2"; start $a19a; end $a19b; type addrtable; comment "map data"; }; +range { name "level06_unkn_table1"; start $a19c; end $a19d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level06_offs_30"; start $a19e; end $a19f; type bytetable; comment "always $0000"; }; +range { name "level06_sub4"; start $a1a0; end $a1a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level06_sub5"; start $a1a2; end $a1a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level06_sub6"; start $a1a4; end $a1a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level06_sub_eol"; start $a1a6; end $a1a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level06_offs_40"; start $a1a8; end $a1ad; type bytetable; comment "all zeroes"; }; +range { name "level06_offs_46"; start $a1ae; end $a1b6; type bytetable; comment "unknown"; }; +range { name "level06_offs_55"; start $a1b7; end $a1b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level06_offs_58"; start $a1ba; end $a1bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level06_offs_60"; start $a1bc; end $a1bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level07_desc"; start $a1c0; end $a1c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level07_sub0"; start $a1c2; end $a1c3; type addrtable; comment "a subroutine"; }; +range { name "level07_sub1"; start $a1c4; end $a1c5; type addrtable; comment "a subroutine"; }; +range { name "level07_sub2"; start $a1c6; end $a1c7; type addrtable; comment "a subroutine"; }; +range { name "level07_sub3"; start $a1c8; end $a1c9; type addrtable; comment "a subroutine"; }; +range { name "level07_num_bombs"; start $a1ca; end $a1ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level07_bullet_chance"; start $a1cb; end $a1cb; type bytetable; comment "0 = no bullets"; }; +range { name "level07_y_start"; start $a1cc; end $a1cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level07_x_start"; start $a1cd; end $a1cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level07_offs_14"; start $a1ce; end $a1cf; type bytetable; comment "points to $0600"; }; +range { name "level07_points_per_bomb"; start $a1d0; end $a1d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level07_time_bonus"; start $a1d1; end $a1d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level07_offs_19"; start $a1d3; end $a1d3; type bytetable; comment "always $00"; }; +range { name "level07_unkn_table0"; start $a1d4; end $a1d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level07_map0"; start $a1d6; end $a1d7; type addrtable; comment "map data"; }; +range { name "level07_map1"; start $a1d8; end $a1d9; type addrtable; comment "map data"; }; +range { name "level07_map2"; start $a1da; end $a1db; type addrtable; comment "map data"; }; +range { name "level07_unkn_table1"; start $a1dc; end $a1dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level07_offs_30"; start $a1de; end $a1df; type bytetable; comment "always $0000"; }; +range { name "level07_sub4"; start $a1e0; end $a1e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level07_sub5"; start $a1e2; end $a1e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level07_sub6"; start $a1e4; end $a1e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level07_sub_eol"; start $a1e6; end $a1e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level07_offs_40"; start $a1e8; end $a1ed; type bytetable; comment "all zeroes"; }; +range { name "level07_offs_46"; start $a1ee; end $a1f6; type bytetable; comment "unknown"; }; +range { name "level07_offs_55"; start $a1f7; end $a1f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level07_offs_58"; start $a1fa; end $a1fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level07_offs_60"; start $a1fc; end $a1ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level08_desc"; start $a200; end $a201; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level08_sub0"; start $a202; end $a203; type addrtable; comment "a subroutine"; }; +range { name "level08_sub1"; start $a204; end $a205; type addrtable; comment "a subroutine"; }; +range { name "level08_sub2"; start $a206; end $a207; type addrtable; comment "a subroutine"; }; +range { name "level08_sub3"; start $a208; end $a209; type addrtable; comment "a subroutine"; }; +range { name "level08_num_bombs"; start $a20a; end $a20a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level08_bullet_chance"; start $a20b; end $a20b; type bytetable; comment "0 = no bullets"; }; +range { name "level08_y_start"; start $a20c; end $a20c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level08_x_start"; start $a20d; end $a20d; type bytetable; comment "jumpman starting X position"; }; +range { name "level08_offs_14"; start $a20e; end $a20f; type bytetable; comment "points to $0600"; }; +range { name "level08_points_per_bomb"; start $a210; end $a210; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level08_time_bonus"; start $a211; end $a212; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level08_offs_19"; start $a213; end $a213; type bytetable; comment "always $00"; }; +range { name "level08_unkn_table0"; start $a214; end $a215; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level08_map0"; start $a216; end $a217; type addrtable; comment "map data"; }; +range { name "level08_map1"; start $a218; end $a219; type addrtable; comment "map data"; }; +range { name "level08_map2"; start $a21a; end $a21b; type addrtable; comment "map data"; }; +range { name "level08_unkn_table1"; start $a21c; end $a21d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level08_offs_30"; start $a21e; end $a21f; type bytetable; comment "always $0000"; }; +range { name "level08_sub4"; start $a220; end $a221; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level08_sub5"; start $a222; end $a223; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level08_sub6"; start $a224; end $a225; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level08_sub_eol"; start $a226; end $a227; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level08_offs_40"; start $a228; end $a22d; type bytetable; comment "all zeroes"; }; +range { name "level08_offs_46"; start $a22e; end $a236; type bytetable; comment "unknown"; }; +range { name "level08_offs_55"; start $a237; end $a239; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level08_offs_58"; start $a23a; end $a23b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level08_offs_60"; start $a23c; end $a23f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level09_desc"; start $a240; end $a241; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level09_sub0"; start $a242; end $a243; type addrtable; comment "a subroutine"; }; +range { name "level09_sub1"; start $a244; end $a245; type addrtable; comment "a subroutine"; }; +range { name "level09_sub2"; start $a246; end $a247; type addrtable; comment "a subroutine"; }; +range { name "level09_sub3"; start $a248; end $a249; type addrtable; comment "a subroutine"; }; +range { name "level09_num_bombs"; start $a24a; end $a24a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level09_bullet_chance"; start $a24b; end $a24b; type bytetable; comment "0 = no bullets"; }; +range { name "level09_y_start"; start $a24c; end $a24c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level09_x_start"; start $a24d; end $a24d; type bytetable; comment "jumpman starting X position"; }; +range { name "level09_offs_14"; start $a24e; end $a24f; type bytetable; comment "points to $0600"; }; +range { name "level09_points_per_bomb"; start $a250; end $a250; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level09_time_bonus"; start $a251; end $a252; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level09_offs_19"; start $a253; end $a253; type bytetable; comment "always $00"; }; +range { name "level09_unkn_table0"; start $a254; end $a255; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level09_map0"; start $a256; end $a257; type addrtable; comment "map data"; }; +range { name "level09_map1"; start $a258; end $a259; type addrtable; comment "map data"; }; +range { name "level09_map2"; start $a25a; end $a25b; type addrtable; comment "map data"; }; +range { name "level09_unkn_table1"; start $a25c; end $a25d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level09_offs_30"; start $a25e; end $a25f; type bytetable; comment "always $0000"; }; +range { name "level09_sub4"; start $a260; end $a261; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level09_sub5"; start $a262; end $a263; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level09_sub6"; start $a264; end $a265; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level09_sub_eol"; start $a266; end $a267; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level09_offs_40"; start $a268; end $a26d; type bytetable; comment "all zeroes"; }; +range { name "level09_offs_46"; start $a26e; end $a276; type bytetable; comment "unknown"; }; +range { name "level09_offs_55"; start $a277; end $a279; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level09_offs_58"; start $a27a; end $a27b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level09_offs_60"; start $a27c; end $a27f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level10_desc"; start $a280; end $a281; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level10_sub0"; start $a282; end $a283; type addrtable; comment "a subroutine"; }; +range { name "level10_sub1"; start $a284; end $a285; type addrtable; comment "a subroutine"; }; +range { name "level10_sub2"; start $a286; end $a287; type addrtable; comment "a subroutine"; }; +range { name "level10_sub3"; start $a288; end $a289; type addrtable; comment "a subroutine"; }; +range { name "level10_num_bombs"; start $a28a; end $a28a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level10_bullet_chance"; start $a28b; end $a28b; type bytetable; comment "0 = no bullets"; }; +range { name "level10_y_start"; start $a28c; end $a28c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level10_x_start"; start $a28d; end $a28d; type bytetable; comment "jumpman starting X position"; }; +range { name "level10_offs_14"; start $a28e; end $a28f; type bytetable; comment "points to $0600"; }; +range { name "level10_points_per_bomb"; start $a290; end $a290; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level10_time_bonus"; start $a291; end $a292; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level10_offs_19"; start $a293; end $a293; type bytetable; comment "always $00"; }; +range { name "level10_unkn_table0"; start $a294; end $a295; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level10_map0"; start $a296; end $a297; type addrtable; comment "map data"; }; +range { name "level10_map1"; start $a298; end $a299; type addrtable; comment "map data"; }; +range { name "level10_map2"; start $a29a; end $a29b; type addrtable; comment "map data"; }; +range { name "level10_unkn_table1"; start $a29c; end $a29d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level10_offs_30"; start $a29e; end $a29f; type bytetable; comment "always $0000"; }; +range { name "level10_sub4"; start $a2a0; end $a2a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level10_sub5"; start $a2a2; end $a2a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level10_sub6"; start $a2a4; end $a2a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level10_sub_eol"; start $a2a6; end $a2a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level10_offs_40"; start $a2a8; end $a2ad; type bytetable; comment "all zeroes"; }; +range { name "level10_offs_46"; start $a2ae; end $a2b6; type bytetable; comment "unknown"; }; +range { name "level10_offs_55"; start $a2b7; end $a2b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level10_offs_58"; start $a2ba; end $a2bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level10_offs_60"; start $a2bc; end $a2bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level11_desc"; start $a2c0; end $a2c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level11_sub0"; start $a2c2; end $a2c3; type addrtable; comment "a subroutine"; }; +range { name "level11_sub1"; start $a2c4; end $a2c5; type addrtable; comment "a subroutine"; }; +range { name "level11_sub2"; start $a2c6; end $a2c7; type addrtable; comment "a subroutine"; }; +range { name "level11_sub3"; start $a2c8; end $a2c9; type addrtable; comment "a subroutine"; }; +range { name "level11_num_bombs"; start $a2ca; end $a2ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level11_bullet_chance"; start $a2cb; end $a2cb; type bytetable; comment "0 = no bullets"; }; +range { name "level11_y_start"; start $a2cc; end $a2cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level11_x_start"; start $a2cd; end $a2cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level11_offs_14"; start $a2ce; end $a2cf; type bytetable; comment "points to $0600"; }; +range { name "level11_points_per_bomb"; start $a2d0; end $a2d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level11_time_bonus"; start $a2d1; end $a2d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level11_offs_19"; start $a2d3; end $a2d3; type bytetable; comment "always $00"; }; +range { name "level11_unkn_table0"; start $a2d4; end $a2d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level11_map0"; start $a2d6; end $a2d7; type addrtable; comment "map data"; }; +range { name "level11_map1"; start $a2d8; end $a2d9; type addrtable; comment "map data"; }; +range { name "level11_map2"; start $a2da; end $a2db; type addrtable; comment "map data"; }; +range { name "level11_unkn_table1"; start $a2dc; end $a2dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level11_offs_30"; start $a2de; end $a2df; type bytetable; comment "always $0000"; }; +range { name "level11_sub4"; start $a2e0; end $a2e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level11_sub5"; start $a2e2; end $a2e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level11_sub6"; start $a2e4; end $a2e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level11_sub_eol"; start $a2e6; end $a2e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level11_offs_40"; start $a2e8; end $a2ed; type bytetable; comment "all zeroes"; }; +range { name "level11_offs_46"; start $a2ee; end $a2f6; type bytetable; comment "unknown"; }; +range { name "level11_offs_55"; start $a2f7; end $a2f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level11_offs_58"; start $a2fa; end $a2fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level11_offs_60"; start $a2fc; end $a2ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + diff --git a/jumpmanjr.rom b/jumpmanjr.rom Binary files differnew file mode 100644 index 0000000..e2367e2 --- /dev/null +++ b/jumpmanjr.rom diff --git a/jumpmanjr_manual.pdf b/jumpmanjr_manual.pdf Binary files differnew file mode 100644 index 0000000..1a607a5 --- /dev/null +++ b/jumpmanjr_manual.pdf diff --git a/level_descriptors.txt b/level_descriptors.txt new file mode 100644 index 0000000..4cbed12 --- /dev/null +++ b/level_descriptors.txt @@ -0,0 +1,127 @@ +TODO: structure-ize the descriptors in the .info file, so dasm +will politely generate labels for all the subroutines and map data. + +At $A000 in the ROM, there's a block of 64 bytes per level (12 blocks, +768 bytes total). Each block describes a level of the game, so I'm calling +them level descriptors. Pretty much everything about a level *except* its +name is stored here. The names are stored separately in a table at $BB00. + +Level descriptors get copied to $07C0 as part of level entry. Possibly +the copy gets modified as the level plays. + +Swapping the descriptors for the first two levels results in Electrocution +being the first level, except the game says it's called Nothing To +It. It plays normally, with electric floors, and displays L=1 in the +status window. The next level is Nothing To It (but the game calls it +Electrocution), which also plays normally and displays L=2. + +Anything that refers to a level below as levelXX is using zero-based +numbering (level00 = first level, aka Nothing To It). + +Level descriptor structure: + +Offset 0, size 2: +Level number displayed in the status window, 2 digits, screen codes. +Levels <10 have $10 (the 0 character) as the first byte, but the code +that draws the status window replaces it with a $00 (space). Possibly +the decision to use e.g. 'L= 1' rather than 'L=01' was made late in +the development process? + +Offset 2, size 2: +A subroutine that gets called during the level (or $00 $00 for 'none'). +Not sure exactly when it gets called though. + +Offset 4, size 2: +Another subroutine or $00 $00 for none.. + +Offset 6, size 2: +Another subroutine or $00 $00 for none.. + +Offset 8, size 2: +Another subroutine or $00 $00 for none.. + +Offset 10, size 1: +Number of bombs to pick up on this level. + +Offset 12, size 1: +Jumpman's starting X position. + +Offset 13, size 1: +Jumpman's starting Y position. + +Offset 14, size 2: +No idea, but it's always $00 $06 (looks like a pointer to page 6). + +Offset 16, size 1: +Always $64. Amount of points per bomb pickup. Interesting that this +is potentially different per level, even though nothing was done with it. + +Offset 17, size 2: +Amount of time bonus, e.g. $e8 $03 for Nothing To It (1000), $d0 $07 for +Electrocution (2000). + +Offset 19, size 1: +No idea. Always zero. + +Offset 20, size 2: don't know yet. **TODO** looks like a ROM address after all + +Offset 22, size 2: +Address of the map for this level. When I figure out how the map +format works, I'll document it in a file that will likely be called +level_maps.txt. + +Offset 24, size 2: +ROM address, more map data? (same areas of ROM) + +Offset 26, size 2: +ROM address, more map data? (same areas of ROM) + +Offset 28, size 2: +$00,$00 on most levels, else a ROM data table address. + +Offset 30, size 2: +Always $00 $00. + +Offset 32, size 2: +$06E6 for most levels, otherwise it's a subroutine in ROM. + +Offset 34, size 2: +$06E6 for a few levels, otherwise it's a subroutine in ROM. + +Offset 36, size 2 (?): +$40,$97 on every level. + +Offset 38, size 2: +$06E6 for all levels except level07, where it's $AF58 (which is +a subroutine in ROM). + +Offset 40, size 6: +All $00 on all levels. + +Offset 46, size 2 (?): +Unknown. Not a ROM address. + +Offset 48, size 2 (?): +Unknown. Not a ROM address. + +Offset 50, size 1: +$0C on most levels except: +$18 on level01 +$4C on level03 +$04 on level05 + +Offsets 51-54: unknown. + +Offset 55, size 1 (?): +$00 on every level. + +Offset 56, size 2: +$00,$00 on every level. + +Offset 58, size 2 (?): +Unknown. Not a ROM address. + +Offset 60, size 4: +$00,$00,$00,$00 on every level except level05 (Walls) where it's +$FF,$FF,$FF,$FF. + diff --git a/level_maps.txt b/level_maps.txt new file mode 100644 index 0000000..b114485 --- /dev/null +++ b/level_maps.txt @@ -0,0 +1,188 @@ +Level Maps +---------- + +level00_map: + .byte $FE,$33,$9C,$FD,$04,$00,$44,$05 ; A300 FE 33 9C FD 04 00 44 05 .3....D. + .byte $06,$04,$15,$0A,$74,$15,$0A,$24 ; A308 06 04 15 0A 74 15 0A 24 ....t..$ + .byte $22,$02,$74,$22,$02,$24,$25,$16 ; A310 22 02 74 22 02 24 25 16 ".t".$%. + .byte $04,$45,$04,$44,$45,$06,$8C,$45 ; A318 04 45 04 44 45 06 8C 45 .E.DE..E + .byte $04,$04,$55,$08,$34,$55,$0E,$7C ; A320 04 04 55 08 34 55 0E 7C ..U.4U.| + .byte $55,$08,$FD,$04,$FF,$34,$09,$04 ; A328 55 08 FD 04 FF 34 09 04 U....4.. + .byte $5C,$44,$0A,$FD,$04,$01,$5C,$06 ; A330 5C 44 0A FD 04 01 5C 06 \D....\. + .byte $04,$1C,$3B,$0A,$FE,$5F,$9C,$FD ; A338 04 1C 3B 0A FE 5F 9C FD ..;.._.. + .byte $00,$04,$0C,$41,$05,$8C,$41,$05 ; A340 00 04 0C 41 05 8C 41 05 ...A..A. + .byte $24,$01,$05,$74,$01,$05,$4C,$01 ; A348 24 01 05 74 01 05 4C 01 $..t..L. + .byte $15,$FE,$C9,$9C,$06,$18,$0A,$99 ; A350 15 FE C9 9C 06 18 0A 99 ........ + .byte $18,$0A,$FE,$DA,$9C,$1D,$38,$06 ; A358 18 0A FE DA 9C 1D 38 06 ......8. + .byte $81,$38,$06,$FE,$B3,$9C ; A360 81 38 06 FE B3 9C .8.... + +A300: FE 33 9C selects a shape (in this case, a girder) +A303: FD 04 00 sets the X and Y delta (4 pixels X, 0 lines Y) +A306: 44 is the X starting position +A307: 05 is the Y starting position +A308: 06 is the number of copies to draw (length of line) +A309: 04 is another X position (same shape type, still drawing girders) +A30A: 15 is another Y position (same shape type) +A30B: 0A is the number of copies to draw + +...more x/y/length tuples here, all drawn with dx=4, dy=0, aka +horizontally from left to right. + +A32A: $FD,$04,$FF sets a new X/Y delta. now we're drawing left and +down, for the diagonal girders (aka ramps) that run SW to NE. + +A333: $FD,$04,$01 is X/Y delta, drawing left and up, for the ramps +that run NW to SE (tilted the other way from the previous set). + +A33C: $FE,$5F,$9C selects a different shape (ladders) + +so eventually, I need ca65 macros that resemble instructions that assemble +into map data. Something like: + +set_gfx $9Cee +set_delta $04,$00 +draw_gfx $44,$05,$06 +draw_gfx $04,$15,$0A + +...notionally the drawing engine is a little CPU with 3 16-bit registers: +a program counter (stored at $C0), gfx (the graphic object it draws) +and delta (2 8-bit signed ints). It has 5 opcodes: + +$FC - gfx_jump (operand = 16-bit target address) +$FD - gfx_delta (operand = 2 8-bit signed ints) +$FE - gfx_shape (operand = 16-bit address of shape, see below) +$FF - gfx_end (done drawing) +Anything else - gfx_draw (opcode is X start, next 2 bytes are Y and length) + +All the opcodes other than gfx_end are 3 bytes. Write macros for ca65 and a +disassembler in perl. + +There are 13 primary maps (one per level, plus the WELL DONE screen). Some +(all?) levels also have secondary map data, which I think is used for +changing parts of the map during the level (e.g. the disappearing girders +on level 1). + +Shapes +------ + +Actual graphics data (girder sections, ladders, etc) is stored less +efficiently. I'm not going to call these "sprites" because they don't +move, and I'm not going to call them "tiles" because they aren't (they +can be placed at arbitrary X/Y positions, not limited to a character +map style grid). So I'll refer them as a "shape". + +Each shape is at least one pixel wide and at least 1 pixel tall. Pixels +are 2 bits wide (4-color GR.7 mode), and are stored unpacked (2 bits +per byte). + +Here's what the girder section looks like: + +girder: .byte $04,$00,$00,$01,$01,$01,$01,$04 ; 9C33 04 00 00 01 01 01 01 04 ........ + .byte $00,$01,$01,$00,$01,$00,$04,$00 ; 9C3B 00 01 01 00 01 00 04 00 ........ + .byte $02,$01,$01,$01,$01,$FF,$xx,$xx ; 9C43 02 01 01 01 01 FF xx xx ........ + +That's from the disassembly, the xx's are "don't care" because they're +actually part of the next shape in the table. + +Here's the same thing, laid out in a more human-readable way [*] + +girder: +girder_row0: +girder_row0_width: .byte $04 +girder_row0_x_offset: .byte $00 +girder_row0_y_offset: .byte $00 +girder_row0_pixels: .byte $01,$01,$01,$01 +girder_row1: +girder_row1_width: .byte $04 +girder_row1_x_offset: .byte $00 +girder_row1_y_offset: .byte $01 +girder_row1_pixels: .byte $01,$00,$01,$00 +girder_row2: +girder_row2_width: .byte $04 +girder_row2_x_offset: .byte $00 +girder_row2_y_offset: .byte $02 +girder_row2_pixels: .byte $01,$01,$01,$01 +girder_end: .byte $FF + + [*] Getting da65 to emit this would be possible but unwieldy, it'll have + to wait until I've mapped out all the 'unknown' code/data sections + and can start manually editing the disassembly to turn it into + proper source. + +This makes a shape like this: + +XXXX +X X +XXXX + +...which you'll recognize as a girder segment, if you squint a little. + +Notice the use of $FF as an end marker. If it occurs in place of a width, +the dm_draw_gfx routine knows it's done, and exits immediately. + +Here's the next shape in the table: + +blank: +blank_row0: +blank_row0_width: .byte $04 +blank_row0_x_offset: .byte $00 +blank_row0_y_offset: .byte $00 +blank_row0_pixels: .byte $00,$00,$00,$00 +blank_row1: +blank_row1_width: .byte $04 +blank_row1_x_offset: .byte $00 +blank_row1_y_offset: .byte $01 +blank_row1_pixels: .byte $00,$00,$00,$00 +blank_row2: +blank_row2_width: .byte $04 +blank_row2_x_offset: .byte $00 +blank_row2_y_offset: .byte $02 +blank_row2_pixels: .byte $00,$00,$00,$00 +blank_end: .byte $FF + +This is a 4x4 block of empty pixels. It's probably used to erase parts +of the level (e.g. the disappearing platforms on level 1). + +Next: + +xxx: +xxx_row0: +xxx_row0_width: .byte $02 +xxx_row0_x_offset: .byte $00 +xxx_row0_y_offset: .byte $00 +xxx_row0_pixels: .byte $02,$02 + +xxx_row1_width: .byte $02 +xxx_row1_x_offset: .byte $06 +xxx_row1_y_offset: .byte $00 +xxx_row1_pixels: .byte $02,$02 + +xxx_row2_width: .byte $02 +xxx_row2_x_offset: .byte $00 +xxx_row2_y_offset: .byte $01 +xxx_row2_pixels: .byte $02,$02 + +xxx_row3_width: .byte $02 +xxx_row3_x_offset: .byte $06 +xxx_row3_y_offset: .byte $01 +xxx_row3_pixels: .byte $02,$02 + +xxx_row4_width: .byte $08 +xxx_row4_x_offset: .byte $00 +xxx_row4_y_offset: .byte $02 +xxx_row4_pixels: .byte $02,$02,$02,$02,$02,$02,$02,$02 + +xxx_row5_width: .byte $02 +xxx_row5_x_offset: .byte $00 +xxx_row5_y_offset: .byte $03 +xxx_row5_pixels: .byte $02,$02 + +xxx_row6_width: .byte $02 +xxx_row6_x_offset: .byte $06 +xxx_row6_y_offset: .byte $03 +xxx_row6_pixels: .byte $02,$02 + +xxx_end: .byte $FF + +In this one, all the pixels are $02. Most of the shapes will be like +this, only using one color. diff --git a/leveldesc.info b/leveldesc.info new file mode 100644 index 0000000..47b7ebc --- /dev/null +++ b/leveldesc.info @@ -0,0 +1,406 @@ +label { name "work_level_desc"; addr $0780; size 2; comment "first 2 bytes are level number in screencodes"; }; +label { name "work_level_sub0"; addr $0782; size 2; comment "a subroutine"; }; +label { name "work_level_sub1"; addr $0784; size 2; comment "a subroutine"; }; +label { name "work_level_sub2"; addr $0786; size 2; comment "a subroutine"; }; +label { name "work_level_sub3"; addr $0788; size 2; comment "a subroutine"; }; +label { name "work_level_num_bombs"; addr $078a; size 1; comment "number of bombs to pick up on this level"; }; +label { name "work_level_bullet_chance"; addr $078b; size 1; comment "0 = no bullets"; }; +label { name "work_level_y_start"; addr $078c; size 1; comment "jumpman starting Y position"; }; +label { name "work_level_x_start"; addr $078d; size 1; comment "jumpman starting X position"; }; +label { name "work_level_offs_14"; addr $078e; size 2; comment "points to $0600"; }; +label { name "work_level_points_per_bomb"; addr $0790; size 1; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +label { name "work_level_time_bonus"; addr $0791; size 2; comment "amount of time bonus at start of level"; }; +label { name "work_level_offs_19"; addr $0793; size 1; comment "always $00"; }; +label { name "work_level_unkn_table0"; addr $0794; size 2; comment "pointer to ROM table or $06xx"; }; +label { name "work_level_map0"; addr $0796; size 2; comment "map data"; }; +label { name "work_level_map1"; addr $0798; size 2; comment "map data"; }; +label { name "work_level_map2"; addr $079a; size 2; comment "map data"; }; +label { name "work_level_unkn_table1"; addr $079c; size 2; comment "unknown, pointer to a ROM table or $0000"; }; +label { name "work_level_offs_30"; addr $079e; size 2; comment "always $0000"; }; +label { name "work_level_sub4"; addr $07a0; size 2; comment "$06E6 for most levels, or else a ROM subroutine"; }; +label { name "work_level_sub5"; addr $07a2; size 2; comment "$06E6 for some levels, or else a ROM subroutine"; }; +label { name "work_level_sub6"; addr $07a4; size 2; comment "always $9740 aka game_main_loop"; }; +label { name "work_level_sub_eol"; addr $07a6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +label { name "work_level_offs_40"; addr $07a8; size 6; comment "all zeroes"; }; +label { name "work_level_offs_46"; addr $07ae; size 9; comment "unknown"; }; +label { name "work_level_offs_55"; addr $07b7; size 3; comment "unknown, always $00 $00 $00"; }; +label { name "work_level_offs_58"; addr $07ba; size 2; comment "unknown, not a ROM address"; }; +label { name "work_level_offs_60"; addr $07bc; size 4; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +label { name "cur_level_desc"; addr $07c0; size 2; comment "first 2 bytes are level number in screencodes"; }; +label { name "cur_level_sub0"; addr $07c2; size 2; comment "a subroutine"; }; +label { name "cur_level_sub1"; addr $07c4; size 2; comment "a subroutine"; }; +label { name "cur_level_sub2"; addr $07c6; size 2; comment "a subroutine"; }; +label { name "cur_level_sub3"; addr $07c8; size 2; comment "a subroutine"; }; +label { name "cur_level_num_bombs"; addr $07ca; size 1; comment "number of bombs to pick up on this level"; }; +label { name "cur_level_bullet_chance"; addr $07cb; size 1; comment "0 = no bullets"; }; +label { name "cur_level_y_start"; addr $07cc; size 1; comment "jumpman starting Y position"; }; +label { name "cur_level_x_start"; addr $07cd; size 1; comment "jumpman starting X position"; }; +label { name "cur_level_offs_14"; addr $07ce; size 2; comment "points to $0600"; }; +label { name "cur_level_points_per_bomb"; addr $07d0; size 1; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +label { name "cur_level_time_bonus"; addr $07d1; size 2; comment "amount of time bonus at start of level"; }; +label { name "cur_level_offs_19"; addr $07d3; size 1; comment "always $00"; }; +label { name "cur_level_unkn_table0"; addr $07d4; size 2; comment "pointer to ROM table or $06xx"; }; +label { name "cur_level_map0"; addr $07d6; size 2; comment "map data"; }; +label { name "cur_level_map1"; addr $07d8; size 2; comment "map data"; }; +label { name "cur_level_map2"; addr $07da; size 2; comment "map data"; }; +label { name "cur_level_unkn_table1"; addr $07dc; size 2; comment "unknown, pointer to a ROM table or $0000"; }; +label { name "cur_level_offs_30"; addr $07de; size 2; comment "always $0000"; }; +label { name "cur_level_sub4"; addr $07e0; size 2; comment "$06E6 for most levels, or else a ROM subroutine"; }; +label { name "cur_level_sub5"; addr $07e2; size 2; comment "$06E6 for some levels, or else a ROM subroutine"; }; +label { name "cur_level_sub6"; addr $07e4; size 2; comment "always $9740 aka game_main_loop"; }; +label { name "cur_level_sub_eol"; addr $07e6; size 2; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +label { name "cur_level_offs_40"; addr $07e8; size 6; comment "all zeroes"; }; +label { name "cur_level_offs_46"; addr $07ee; size 9; comment "unknown"; }; +label { name "cur_level_offs_55"; addr $07f7; size 3; comment "unknown, always $00 $00 $00"; }; +label { name "cur_level_offs_58"; addr $07fa; size 2; comment "unknown, not a ROM address"; }; +label { name "cur_level_offs_60"; addr $07fc; size 4; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level00_desc"; start $a000; end $a001; type bytetable; comment "64-byte level descriptors, 12 of them (1 per level). first 2 bytes are level number in screencodes"; }; +range { name "level00_sub0"; start $a002; end $a003; type addrtable; comment "a subroutine"; }; +range { name "level00_sub1"; start $a004; end $a005; type addrtable; comment "a subroutine"; }; +range { name "level00_sub2"; start $a006; end $a007; type addrtable; comment "a subroutine"; }; +range { name "level00_sub3"; start $a008; end $a009; type addrtable; comment "a subroutine"; }; +range { name "level00_num_bombs"; start $a00a; end $a00a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level00_bullet_chance"; start $a00b; end $a00b; type bytetable; comment "0 = no bullets"; }; +range { name "level00_y_start"; start $a00c; end $a00c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level00_x_start"; start $a00d; end $a00d; type bytetable; comment "jumpman starting X position"; }; +range { name "level00_offs_14"; start $a00e; end $a00f; type bytetable; comment "points to $0600"; }; +range { name "level00_points_per_bomb"; start $a010; end $a010; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level00_time_bonus"; start $a011; end $a012; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level00_offs_19"; start $a013; end $a013; type bytetable; comment "always $00"; }; +range { name "level00_unkn_table0"; start $a014; end $a015; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level00_map0"; start $a016; end $a017; type addrtable; comment "map data"; }; +range { name "level00_map1"; start $a018; end $a019; type addrtable; comment "map data"; }; +range { name "level00_map2"; start $a01a; end $a01b; type addrtable; comment "map data"; }; +range { name "level00_unkn_table1"; start $a01c; end $a01d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level00_offs_30"; start $a01e; end $a01f; type bytetable; comment "always $0000"; }; +range { name "level00_sub4"; start $a020; end $a021; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level00_sub5"; start $a022; end $a023; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level00_sub6"; start $a024; end $a025; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level00_sub_eol"; start $a026; end $a027; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level00_offs_40"; start $a028; end $a02d; type bytetable; comment "all zeroes"; }; +range { name "level00_offs_46"; start $a02e; end $a036; type bytetable; comment "unknown"; }; +range { name "level00_offs_55"; start $a037; end $a039; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level00_offs_58"; start $a03a; end $a03b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level00_offs_60"; start $a03c; end $a03f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level01_desc"; start $a040; end $a041; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level01_sub0"; start $a042; end $a043; type addrtable; comment "a subroutine"; }; +range { name "level01_sub1"; start $a044; end $a045; type addrtable; comment "a subroutine"; }; +range { name "level01_sub2"; start $a046; end $a047; type addrtable; comment "a subroutine"; }; +range { name "level01_sub3"; start $a048; end $a049; type addrtable; comment "a subroutine"; }; +range { name "level01_num_bombs"; start $a04a; end $a04a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level01_bullet_chance"; start $a04b; end $a04b; type bytetable; comment "0 = no bullets"; }; +range { name "level01_y_start"; start $a04c; end $a04c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level01_x_start"; start $a04d; end $a04d; type bytetable; comment "jumpman starting X position"; }; +range { name "level01_offs_14"; start $a04e; end $a04f; type bytetable; comment "points to $0600"; }; +range { name "level01_points_per_bomb"; start $a050; end $a050; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level01_time_bonus"; start $a051; end $a052; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level01_offs_19"; start $a053; end $a053; type bytetable; comment "always $00"; }; +range { name "level01_unkn_table0"; start $a054; end $a055; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level01_map0"; start $a056; end $a057; type addrtable; comment "map data"; }; +range { name "level01_map1"; start $a058; end $a059; type addrtable; comment "map data"; }; +range { name "level01_map2"; start $a05a; end $a05b; type addrtable; comment "map data"; }; +range { name "level01_unkn_table1"; start $a05c; end $a05d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level01_offs_30"; start $a05e; end $a05f; type bytetable; comment "always $0000"; }; +range { name "level01_sub4"; start $a060; end $a061; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level01_sub5"; start $a062; end $a063; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level01_sub6"; start $a064; end $a065; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level01_sub_eol"; start $a066; end $a067; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level01_offs_40"; start $a068; end $a06d; type bytetable; comment "all zeroes"; }; +range { name "level01_offs_46"; start $a06e; end $a076; type bytetable; comment "unknown"; }; +range { name "level01_offs_55"; start $a077; end $a079; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level01_offs_58"; start $a07a; end $a07b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level01_offs_60"; start $a07c; end $a07f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level02_desc"; start $a080; end $a081; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level02_sub0"; start $a082; end $a083; type addrtable; comment "a subroutine"; }; +range { name "level02_sub1"; start $a084; end $a085; type addrtable; comment "a subroutine"; }; +range { name "level02_sub2"; start $a086; end $a087; type addrtable; comment "a subroutine"; }; +range { name "level02_sub3"; start $a088; end $a089; type addrtable; comment "a subroutine"; }; +range { name "level02_num_bombs"; start $a08a; end $a08a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level02_bullet_chance"; start $a08b; end $a08b; type bytetable; comment "0 = no bullets"; }; +range { name "level02_y_start"; start $a08c; end $a08c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level02_x_start"; start $a08d; end $a08d; type bytetable; comment "jumpman starting X position"; }; +range { name "level02_offs_14"; start $a08e; end $a08f; type bytetable; comment "points to $0600"; }; +range { name "level02_points_per_bomb"; start $a090; end $a090; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level02_time_bonus"; start $a091; end $a092; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level02_offs_19"; start $a093; end $a093; type bytetable; comment "always $00"; }; +range { name "level02_unkn_table0"; start $a094; end $a095; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level02_map0"; start $a096; end $a097; type addrtable; comment "map data"; }; +range { name "level02_map1"; start $a098; end $a099; type addrtable; comment "map data"; }; +range { name "level02_map2"; start $a09a; end $a09b; type addrtable; comment "map data"; }; +range { name "level02_unkn_table1"; start $a09c; end $a09d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level02_offs_30"; start $a09e; end $a09f; type bytetable; comment "always $0000"; }; +range { name "level02_sub4"; start $a0a0; end $a0a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level02_sub5"; start $a0a2; end $a0a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level02_sub6"; start $a0a4; end $a0a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level02_sub_eol"; start $a0a6; end $a0a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level02_offs_40"; start $a0a8; end $a0ad; type bytetable; comment "all zeroes"; }; +range { name "level02_offs_46"; start $a0ae; end $a0b6; type bytetable; comment "unknown"; }; +range { name "level02_offs_55"; start $a0b7; end $a0b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level02_offs_58"; start $a0ba; end $a0bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level02_offs_60"; start $a0bc; end $a0bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level03_desc"; start $a0c0; end $a0c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level03_sub0"; start $a0c2; end $a0c3; type addrtable; comment "a subroutine"; }; +range { name "level03_sub1"; start $a0c4; end $a0c5; type addrtable; comment "a subroutine"; }; +range { name "level03_sub2"; start $a0c6; end $a0c7; type addrtable; comment "a subroutine"; }; +range { name "level03_sub3"; start $a0c8; end $a0c9; type addrtable; comment "a subroutine"; }; +range { name "level03_num_bombs"; start $a0ca; end $a0ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level03_bullet_chance"; start $a0cb; end $a0cb; type bytetable; comment "0 = no bullets"; }; +range { name "level03_y_start"; start $a0cc; end $a0cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level03_x_start"; start $a0cd; end $a0cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level03_offs_14"; start $a0ce; end $a0cf; type bytetable; comment "points to $0600"; }; +range { name "level03_points_per_bomb"; start $a0d0; end $a0d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level03_time_bonus"; start $a0d1; end $a0d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level03_offs_19"; start $a0d3; end $a0d3; type bytetable; comment "always $00"; }; +range { name "level03_unkn_table0"; start $a0d4; end $a0d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level03_map0"; start $a0d6; end $a0d7; type addrtable; comment "map data"; }; +range { name "level03_map1"; start $a0d8; end $a0d9; type addrtable; comment "map data"; }; +range { name "level03_map2"; start $a0da; end $a0db; type addrtable; comment "map data"; }; +range { name "level03_unkn_table1"; start $a0dc; end $a0dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level03_offs_30"; start $a0de; end $a0df; type bytetable; comment "always $0000"; }; +range { name "level03_sub4"; start $a0e0; end $a0e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level03_sub5"; start $a0e2; end $a0e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level03_sub6"; start $a0e4; end $a0e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level03_sub_eol"; start $a0e6; end $a0e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level03_offs_40"; start $a0e8; end $a0ed; type bytetable; comment "all zeroes"; }; +range { name "level03_offs_46"; start $a0ee; end $a0f6; type bytetable; comment "unknown"; }; +range { name "level03_offs_55"; start $a0f7; end $a0f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level03_offs_58"; start $a0fa; end $a0fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level03_offs_60"; start $a0fc; end $a0ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level04_desc"; start $a100; end $a101; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level04_sub0"; start $a102; end $a103; type addrtable; comment "a subroutine"; }; +range { name "level04_sub1"; start $a104; end $a105; type addrtable; comment "a subroutine"; }; +range { name "level04_sub2"; start $a106; end $a107; type addrtable; comment "a subroutine"; }; +range { name "level04_sub3"; start $a108; end $a109; type addrtable; comment "a subroutine"; }; +range { name "level04_num_bombs"; start $a10a; end $a10a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level04_bullet_chance"; start $a10b; end $a10b; type bytetable; comment "0 = no bullets"; }; +range { name "level04_y_start"; start $a10c; end $a10c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level04_x_start"; start $a10d; end $a10d; type bytetable; comment "jumpman starting X position"; }; +range { name "level04_offs_14"; start $a10e; end $a10f; type bytetable; comment "points to $0600"; }; +range { name "level04_points_per_bomb"; start $a110; end $a110; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level04_time_bonus"; start $a111; end $a112; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level04_offs_19"; start $a113; end $a113; type bytetable; comment "always $00"; }; +range { name "level04_unkn_table0"; start $a114; end $a115; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level04_map0"; start $a116; end $a117; type addrtable; comment "map data"; }; +range { name "level04_map1"; start $a118; end $a119; type addrtable; comment "map data"; }; +range { name "level04_map2"; start $a11a; end $a11b; type addrtable; comment "map data"; }; +range { name "level04_unkn_table1"; start $a11c; end $a11d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level04_offs_30"; start $a11e; end $a11f; type bytetable; comment "always $0000"; }; +range { name "level04_sub4"; start $a120; end $a121; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level04_sub5"; start $a122; end $a123; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level04_sub6"; start $a124; end $a125; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level04_sub_eol"; start $a126; end $a127; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level04_offs_40"; start $a128; end $a12d; type bytetable; comment "all zeroes"; }; +range { name "level04_offs_46"; start $a12e; end $a136; type bytetable; comment "unknown"; }; +range { name "level04_offs_55"; start $a137; end $a139; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level04_offs_58"; start $a13a; end $a13b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level04_offs_60"; start $a13c; end $a13f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level05_desc"; start $a140; end $a141; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level05_sub0"; start $a142; end $a143; type addrtable; comment "a subroutine"; }; +range { name "level05_sub1"; start $a144; end $a145; type addrtable; comment "a subroutine"; }; +range { name "level05_sub2"; start $a146; end $a147; type addrtable; comment "a subroutine"; }; +range { name "level05_sub3"; start $a148; end $a149; type addrtable; comment "a subroutine"; }; +range { name "level05_num_bombs"; start $a14a; end $a14a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level05_bullet_chance"; start $a14b; end $a14b; type bytetable; comment "0 = no bullets"; }; +range { name "level05_y_start"; start $a14c; end $a14c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level05_x_start"; start $a14d; end $a14d; type bytetable; comment "jumpman starting X position"; }; +range { name "level05_offs_14"; start $a14e; end $a14f; type bytetable; comment "points to $0600"; }; +range { name "level05_points_per_bomb"; start $a150; end $a150; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level05_time_bonus"; start $a151; end $a152; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level05_offs_19"; start $a153; end $a153; type bytetable; comment "always $00"; }; +range { name "level05_unkn_table0"; start $a154; end $a155; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level05_map0"; start $a156; end $a157; type addrtable; comment "map data"; }; +range { name "level05_map1"; start $a158; end $a159; type addrtable; comment "map data"; }; +range { name "level05_map2"; start $a15a; end $a15b; type addrtable; comment "map data"; }; +range { name "level05_unkn_table1"; start $a15c; end $a15d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level05_offs_30"; start $a15e; end $a15f; type bytetable; comment "always $0000"; }; +range { name "level05_sub4"; start $a160; end $a161; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level05_sub5"; start $a162; end $a163; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level05_sub6"; start $a164; end $a165; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level05_sub_eol"; start $a166; end $a167; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level05_offs_40"; start $a168; end $a16d; type bytetable; comment "all zeroes"; }; +range { name "level05_offs_46"; start $a16e; end $a176; type bytetable; comment "unknown"; }; +range { name "level05_offs_55"; start $a177; end $a179; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level05_offs_58"; start $a17a; end $a17b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level05_offs_60"; start $a17c; end $a17f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level06_desc"; start $a180; end $a181; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level06_sub0"; start $a182; end $a183; type addrtable; comment "a subroutine"; }; +range { name "level06_sub1"; start $a184; end $a185; type addrtable; comment "a subroutine"; }; +range { name "level06_sub2"; start $a186; end $a187; type addrtable; comment "a subroutine"; }; +range { name "level06_sub3"; start $a188; end $a189; type addrtable; comment "a subroutine"; }; +range { name "level06_num_bombs"; start $a18a; end $a18a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level06_bullet_chance"; start $a18b; end $a18b; type bytetable; comment "0 = no bullets"; }; +range { name "level06_y_start"; start $a18c; end $a18c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level06_x_start"; start $a18d; end $a18d; type bytetable; comment "jumpman starting X position"; }; +range { name "level06_offs_14"; start $a18e; end $a18f; type bytetable; comment "points to $0600"; }; +range { name "level06_points_per_bomb"; start $a190; end $a190; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level06_time_bonus"; start $a191; end $a192; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level06_offs_19"; start $a193; end $a193; type bytetable; comment "always $00"; }; +range { name "level06_unkn_table0"; start $a194; end $a195; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level06_map0"; start $a196; end $a197; type addrtable; comment "map data"; }; +range { name "level06_map1"; start $a198; end $a199; type addrtable; comment "map data"; }; +range { name "level06_map2"; start $a19a; end $a19b; type addrtable; comment "map data"; }; +range { name "level06_unkn_table1"; start $a19c; end $a19d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level06_offs_30"; start $a19e; end $a19f; type bytetable; comment "always $0000"; }; +range { name "level06_sub4"; start $a1a0; end $a1a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level06_sub5"; start $a1a2; end $a1a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level06_sub6"; start $a1a4; end $a1a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level06_sub_eol"; start $a1a6; end $a1a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level06_offs_40"; start $a1a8; end $a1ad; type bytetable; comment "all zeroes"; }; +range { name "level06_offs_46"; start $a1ae; end $a1b6; type bytetable; comment "unknown"; }; +range { name "level06_offs_55"; start $a1b7; end $a1b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level06_offs_58"; start $a1ba; end $a1bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level06_offs_60"; start $a1bc; end $a1bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level07_desc"; start $a1c0; end $a1c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level07_sub0"; start $a1c2; end $a1c3; type addrtable; comment "a subroutine"; }; +range { name "level07_sub1"; start $a1c4; end $a1c5; type addrtable; comment "a subroutine"; }; +range { name "level07_sub2"; start $a1c6; end $a1c7; type addrtable; comment "a subroutine"; }; +range { name "level07_sub3"; start $a1c8; end $a1c9; type addrtable; comment "a subroutine"; }; +range { name "level07_num_bombs"; start $a1ca; end $a1ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level07_bullet_chance"; start $a1cb; end $a1cb; type bytetable; comment "0 = no bullets"; }; +range { name "level07_y_start"; start $a1cc; end $a1cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level07_x_start"; start $a1cd; end $a1cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level07_offs_14"; start $a1ce; end $a1cf; type bytetable; comment "points to $0600"; }; +range { name "level07_points_per_bomb"; start $a1d0; end $a1d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level07_time_bonus"; start $a1d1; end $a1d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level07_offs_19"; start $a1d3; end $a1d3; type bytetable; comment "always $00"; }; +range { name "level07_unkn_table0"; start $a1d4; end $a1d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level07_map0"; start $a1d6; end $a1d7; type addrtable; comment "map data"; }; +range { name "level07_map1"; start $a1d8; end $a1d9; type addrtable; comment "map data"; }; +range { name "level07_map2"; start $a1da; end $a1db; type addrtable; comment "map data"; }; +range { name "level07_unkn_table1"; start $a1dc; end $a1dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level07_offs_30"; start $a1de; end $a1df; type bytetable; comment "always $0000"; }; +range { name "level07_sub4"; start $a1e0; end $a1e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level07_sub5"; start $a1e2; end $a1e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level07_sub6"; start $a1e4; end $a1e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level07_sub_eol"; start $a1e6; end $a1e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level07_offs_40"; start $a1e8; end $a1ed; type bytetable; comment "all zeroes"; }; +range { name "level07_offs_46"; start $a1ee; end $a1f6; type bytetable; comment "unknown"; }; +range { name "level07_offs_55"; start $a1f7; end $a1f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level07_offs_58"; start $a1fa; end $a1fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level07_offs_60"; start $a1fc; end $a1ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level08_desc"; start $a200; end $a201; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level08_sub0"; start $a202; end $a203; type addrtable; comment "a subroutine"; }; +range { name "level08_sub1"; start $a204; end $a205; type addrtable; comment "a subroutine"; }; +range { name "level08_sub2"; start $a206; end $a207; type addrtable; comment "a subroutine"; }; +range { name "level08_sub3"; start $a208; end $a209; type addrtable; comment "a subroutine"; }; +range { name "level08_num_bombs"; start $a20a; end $a20a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level08_bullet_chance"; start $a20b; end $a20b; type bytetable; comment "0 = no bullets"; }; +range { name "level08_y_start"; start $a20c; end $a20c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level08_x_start"; start $a20d; end $a20d; type bytetable; comment "jumpman starting X position"; }; +range { name "level08_offs_14"; start $a20e; end $a20f; type bytetable; comment "points to $0600"; }; +range { name "level08_points_per_bomb"; start $a210; end $a210; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level08_time_bonus"; start $a211; end $a212; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level08_offs_19"; start $a213; end $a213; type bytetable; comment "always $00"; }; +range { name "level08_unkn_table0"; start $a214; end $a215; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level08_map0"; start $a216; end $a217; type addrtable; comment "map data"; }; +range { name "level08_map1"; start $a218; end $a219; type addrtable; comment "map data"; }; +range { name "level08_map2"; start $a21a; end $a21b; type addrtable; comment "map data"; }; +range { name "level08_unkn_table1"; start $a21c; end $a21d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level08_offs_30"; start $a21e; end $a21f; type bytetable; comment "always $0000"; }; +range { name "level08_sub4"; start $a220; end $a221; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level08_sub5"; start $a222; end $a223; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level08_sub6"; start $a224; end $a225; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level08_sub_eol"; start $a226; end $a227; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level08_offs_40"; start $a228; end $a22d; type bytetable; comment "all zeroes"; }; +range { name "level08_offs_46"; start $a22e; end $a236; type bytetable; comment "unknown"; }; +range { name "level08_offs_55"; start $a237; end $a239; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level08_offs_58"; start $a23a; end $a23b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level08_offs_60"; start $a23c; end $a23f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level09_desc"; start $a240; end $a241; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level09_sub0"; start $a242; end $a243; type addrtable; comment "a subroutine"; }; +range { name "level09_sub1"; start $a244; end $a245; type addrtable; comment "a subroutine"; }; +range { name "level09_sub2"; start $a246; end $a247; type addrtable; comment "a subroutine"; }; +range { name "level09_sub3"; start $a248; end $a249; type addrtable; comment "a subroutine"; }; +range { name "level09_num_bombs"; start $a24a; end $a24a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level09_bullet_chance"; start $a24b; end $a24b; type bytetable; comment "0 = no bullets"; }; +range { name "level09_y_start"; start $a24c; end $a24c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level09_x_start"; start $a24d; end $a24d; type bytetable; comment "jumpman starting X position"; }; +range { name "level09_offs_14"; start $a24e; end $a24f; type bytetable; comment "points to $0600"; }; +range { name "level09_points_per_bomb"; start $a250; end $a250; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level09_time_bonus"; start $a251; end $a252; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level09_offs_19"; start $a253; end $a253; type bytetable; comment "always $00"; }; +range { name "level09_unkn_table0"; start $a254; end $a255; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level09_map0"; start $a256; end $a257; type addrtable; comment "map data"; }; +range { name "level09_map1"; start $a258; end $a259; type addrtable; comment "map data"; }; +range { name "level09_map2"; start $a25a; end $a25b; type addrtable; comment "map data"; }; +range { name "level09_unkn_table1"; start $a25c; end $a25d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level09_offs_30"; start $a25e; end $a25f; type bytetable; comment "always $0000"; }; +range { name "level09_sub4"; start $a260; end $a261; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level09_sub5"; start $a262; end $a263; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level09_sub6"; start $a264; end $a265; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level09_sub_eol"; start $a266; end $a267; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level09_offs_40"; start $a268; end $a26d; type bytetable; comment "all zeroes"; }; +range { name "level09_offs_46"; start $a26e; end $a276; type bytetable; comment "unknown"; }; +range { name "level09_offs_55"; start $a277; end $a279; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level09_offs_58"; start $a27a; end $a27b; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level09_offs_60"; start $a27c; end $a27f; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level10_desc"; start $a280; end $a281; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level10_sub0"; start $a282; end $a283; type addrtable; comment "a subroutine"; }; +range { name "level10_sub1"; start $a284; end $a285; type addrtable; comment "a subroutine"; }; +range { name "level10_sub2"; start $a286; end $a287; type addrtable; comment "a subroutine"; }; +range { name "level10_sub3"; start $a288; end $a289; type addrtable; comment "a subroutine"; }; +range { name "level10_num_bombs"; start $a28a; end $a28a; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level10_bullet_chance"; start $a28b; end $a28b; type bytetable; comment "0 = no bullets"; }; +range { name "level10_y_start"; start $a28c; end $a28c; type bytetable; comment "jumpman starting Y position"; }; +range { name "level10_x_start"; start $a28d; end $a28d; type bytetable; comment "jumpman starting X position"; }; +range { name "level10_offs_14"; start $a28e; end $a28f; type bytetable; comment "points to $0600"; }; +range { name "level10_points_per_bomb"; start $a290; end $a290; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level10_time_bonus"; start $a291; end $a292; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level10_offs_19"; start $a293; end $a293; type bytetable; comment "always $00"; }; +range { name "level10_unkn_table0"; start $a294; end $a295; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level10_map0"; start $a296; end $a297; type addrtable; comment "map data"; }; +range { name "level10_map1"; start $a298; end $a299; type addrtable; comment "map data"; }; +range { name "level10_map2"; start $a29a; end $a29b; type addrtable; comment "map data"; }; +range { name "level10_unkn_table1"; start $a29c; end $a29d; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level10_offs_30"; start $a29e; end $a29f; type bytetable; comment "always $0000"; }; +range { name "level10_sub4"; start $a2a0; end $a2a1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level10_sub5"; start $a2a2; end $a2a3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level10_sub6"; start $a2a4; end $a2a5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level10_sub_eol"; start $a2a6; end $a2a7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level10_offs_40"; start $a2a8; end $a2ad; type bytetable; comment "all zeroes"; }; +range { name "level10_offs_46"; start $a2ae; end $a2b6; type bytetable; comment "unknown"; }; +range { name "level10_offs_55"; start $a2b7; end $a2b9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level10_offs_58"; start $a2ba; end $a2bb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level10_offs_60"; start $a2bc; end $a2bf; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + +range { name "level11_desc"; start $a2c0; end $a2c1; type bytetable; comment "first 2 bytes are level number in screencodes"; }; +range { name "level11_sub0"; start $a2c2; end $a2c3; type addrtable; comment "a subroutine"; }; +range { name "level11_sub1"; start $a2c4; end $a2c5; type addrtable; comment "a subroutine"; }; +range { name "level11_sub2"; start $a2c6; end $a2c7; type addrtable; comment "a subroutine"; }; +range { name "level11_sub3"; start $a2c8; end $a2c9; type addrtable; comment "a subroutine"; }; +range { name "level11_num_bombs"; start $a2ca; end $a2ca; type bytetable; comment "number of bombs to pick up on this level"; }; +range { name "level11_bullet_chance"; start $a2cb; end $a2cb; type bytetable; comment "0 = no bullets"; }; +range { name "level11_y_start"; start $a2cc; end $a2cc; type bytetable; comment "jumpman starting Y position"; }; +range { name "level11_x_start"; start $a2cd; end $a2cd; type bytetable; comment "jumpman starting X position"; }; +range { name "level11_offs_14"; start $a2ce; end $a2cf; type bytetable; comment "points to $0600"; }; +range { name "level11_points_per_bomb"; start $a2d0; end $a2d0; type bytetable; comment "points awarded per bomb pickup (always $64 aka 100)"; }; +range { name "level11_time_bonus"; start $a2d1; end $a2d2; type wordtable; comment "amount of time bonus at start of level"; }; +range { name "level11_offs_19"; start $a2d3; end $a2d3; type bytetable; comment "always $00"; }; +range { name "level11_unkn_table0"; start $a2d4; end $a2d5; type addrtable; comment "pointer to ROM table or $06xx"; }; +range { name "level11_map0"; start $a2d6; end $a2d7; type addrtable; comment "map data"; }; +range { name "level11_map1"; start $a2d8; end $a2d9; type addrtable; comment "map data"; }; +range { name "level11_map2"; start $a2da; end $a2db; type addrtable; comment "map data"; }; +range { name "level11_unkn_table1"; start $a2dc; end $a2dd; type addrtable; comment "unknown, pointer to a ROM table or $0000"; }; +range { name "level11_offs_30"; start $a2de; end $a2df; type bytetable; comment "always $0000"; }; +range { name "level11_sub4"; start $a2e0; end $a2e1; type addrtable; comment "$06E6 for most levels, or else a ROM subroutine"; }; +range { name "level11_sub5"; start $a2e2; end $a2e3; type addrtable; comment "$06E6 for some levels, or else a ROM subroutine"; }; +range { name "level11_sub6"; start $a2e4; end $a2e5; type addrtable; comment "always $9740 aka game_main_loop"; }; +range { name "level11_sub_eol"; start $a2e6; end $a2e7; type addrtable; comment "called at end of level (all bombs picked up). $06E6 for all but level07"; }; +range { name "level11_offs_40"; start $a2e8; end $a2ed; type bytetable; comment "all zeroes"; }; +range { name "level11_offs_46"; start $a2ee; end $a2f6; type bytetable; comment "unknown"; }; +range { name "level11_offs_55"; start $a2f7; end $a2f9; type bytetable; comment "unknown, always $00 $00 $00"; }; +range { name "level11_offs_58"; start $a2fa; end $a2fb; type bytetable; comment "unknown, not a ROM address"; }; +range { name "level11_offs_60"; start $a2fc; end $a2ff; type bytetable; comment "unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00"; }; + diff --git a/main.info b/main.info new file mode 100644 index 0000000..543d4ff --- /dev/null +++ b/main.info @@ -0,0 +1,501 @@ + +# da65 info file for jumpman junior ROM. + +GLOBAL { + OUTPUTNAME "jumpmanjr.dasm"; + INPUTNAME "jumpmanjr.rom"; + STARTADDR $8000; + CPU "6502"; + COMMENTS 4; +}; + +#SEGMENT { START $8000; END $BFFF; NAME "jumpmanjr"; }; + +ASMINC { FILE "jumpmanjr.inc"; }; + +# RANGE { START $whatever; END $whatever; TYPE Code|ByteTable|AddrTable|RtsTable; } + +label { name "cart_start_stub"; addr $8AFE; }; +label { name "cart_entry_point"; addr $8ac0; }; +label { name "check_keycode"; addr $9C07; }; +label { name "store_speed_value"; addr $9C13; }; +label { name "keyboard_isr_exit"; addr $9C0F; }; +label { name "check_consol"; addr $88C8; }; +label { name "ask_num_players"; addr $9400; }; +label { name "sl_loop"; addr $96D8; }; +label { name "materialize_jumpman"; addr $977B; }; +label { name "mj_clear_loop"; addr $9782; }; +label { name "mj_set_freq_and_color"; addr $97BB; }; +label { name "mj_delay"; addr $97CD; }; +label { name "mj_done"; addr $97DB; }; +label { name "game_main_loop"; addr $9740; }; + +label { name "copy_level_desc_2"; addr $9677; comment "copy level descriptor to $0780"; }; +label { name "randomize_level"; addr $9BED; comment "only after beating levels 1-12 in order"; }; +label { name "enter_level"; addr $96BA; comment "maybe this should be check_level or init_level?"; }; +label { name "copy_level_desc"; addr $96CE; comment "copy level descriptor from levelXX_desc at $A000+(level*$40) to $07c0-$07ff"; }; +label { name "randomizer_mode"; addr $06F3; comment "only after beating levels 1-12 in order"; }; + +label { name "init_loop"; addr $8ac4; comment "clear pages 6 and 7"; }; +label { name "set_vkeybd"; addr $83ED; comment "VKEYBD now points to $9c00 aka keyboard_isr"; }; +label { name "set_vvblki"; addr $8401; comment "VVBLKI now points to $840d aka vblank_imm_isr"; }; +label { name "vblank_imm_isr"; addr $840d; comment "service immediate vblank interrupt"; }; + +label { name "dli_chained_1"; addr $9B72; comment "changes DLI vector to point to dli_chained_2"; }; +label { name "dli_chained_2"; addr $9B87; comment "changes DLI vector to point to dli_chained_3"; }; +label { name "dli_chained_3"; addr $9BB1; comment "changes DLI vector to point to dli_chained_1"; }; +label { name "update_color_regs"; addr $840F; comment "update color regs from shadow regs (X ranges 1 to 9, GRAFM+1 is COLPM0, $2bf+1 is PCOLR0)"; }; + +range { name "code_99f7"; start $99F7; end $9A1B; type code; }; +range { name "data_8406"; start $8406; end $840c; type bytetable; }; +range { name "data_9a1c"; start $9a1c; end $9A5B; type bytetable; }; +range { name "gameboard_dlist_data"; start $9B62; end $9b71; type bytetable; comment "this isn't used as-is for a display list, see setup_gameboard_dlist"; }; +RANGE { NAME "cartstart_left"; START $BFFA; END $BFFB ; TYPE AddrTable; comment "main entry point, note cartstart_left and cartstart_right point to the same address"; }; +RANGE { NAME "cartstart_right"; START $9FFA; END $9FFB ; TYPE AddrTable; comment "main entry point, note cartstart_left and cartstart_right point to the same address"; }; +RANGE { NAME "cartinit_left"; START $BFFE; END $BFFF ; TYPE AddrTable; comment "points to a CLC/RTS do-nothing routine (same as cartinit_right)"; }; +RANGE { NAME "cartinit_right"; START $9FFE; END $9FFF ; TYPE AddrTable; comment "points to a CLC/RTS do-nothing routine (same as cartinit_left)"; }; + +range { name "cartpresent_left"; start $bffc; end $bffc; type bytetable; comment "0 here means 'cartridge present'"; }; +range { name "cartpresent_right"; start $9ffc; end $9ffc; type bytetable; comment "0 here means 'cartridge present'"; }; +range { name "cartoptions_left"; start $bffd; end $bffd; type bytetable; comment "4 here means init & start the cart, no disk boot, non-diagnostic"; }; +range { name "cartoptions_right"; start $9ffd; end $9ffd; type bytetable; comment "4 here means init & start the cart, no disk boot, non-diagnostic"; }; + +label { name "VDSLST"; addr $0200; size 2; }; +label { name "FR1"; addr $00e0; size 6; }; +label { name "player_x_speed"; addr $95C5; size 20; comment "' PLAYER # SPEED? ' in PF2 color"; }; +label { name "num_name_hscrol_table"; addr $95D9; size 4; comment "used for centering ONE TWO THREE FOUR, see option_key_handler"; }; +label { name "number_names_0"; addr $95dd; size 4; comment "space space T space (names ONE TWO THREE FOUR)"; }; +label { name "number_names_1"; addr $95e1; size 4; comment "O T H F"; }; +label { name "number_names_2"; addr $95e5; size 4; comment "N W R O"; }; +label { name "number_names_3"; addr $95e9; size 4; comment "E O E U"; }; +label { name "number_names_4"; addr $95ed; size 4; comment "space space E R"; }; +label { name "sfx_select_key"; addr $95f1; comment "played when select key pressed, 4 notes, descending"; }; +label { name "missiles_mask_table_minus_one"; addr $82df; }; +label { name "set_dma_ctl"; addr $838F; comment "std playfield, enable players + missiles, single-line p/m res, DMA enabled"; }; + +range { name "level_names"; start $BB00; end $bbef; type bytetable; }; +range { name "pm_memory"; start $2800; end $2fff; type bytetable; }; +range { name "missiles_mask_table"; start $82e0; end $82E7; type bytetable; }; +range { name "missiles_done"; start $82DD; end $82df; type code; }; +range { name "position_missiles"; start $8293; end $82DA; type code; }; +range { name "charset"; start $9e00; end $9ff9; type bytetable; comment "GR.1/2 font, 512 bytes"; }; +range { name "game_display_list"; start $0881; end $08e3; type bytetable; comment "display list for game board"; }; +range { name "title_display_list"; start $91B3; end $91ce; type bytetable; comment "display list for title screen"; }; +range { name "numplayer_display_list"; start $955f; end $9577; type bytetable; comment "display list for 'number of players' screen"; }; +label { name "setup_numplayer_dlist"; addr $9444; comment "set dlist shadow to point to numplayer_display_list"; }; +label { name "setup_numplayer_dli_sr"; addr $944e; comment "set dli vector to point to num_player_dli_service"; }; +label { name "anp_loop_done"; addr $9421; comment "X is now 0"; }; +label { name "anp_clear_loop"; addr $940D; comment "clear area where NUMBER OF PLAYERS? will be displayed"; }; +label { name "anp_copy_loop"; addr $9418; comment "copy NUMBER OF PLAYERS to screen RAM"; }; +label { name "save_collisions"; addr $8503; comment "save contents of GTIA collision regs (X ranges 1 to $10, dli_vec_shadow_hi should read collision_save-1)"; }; + +label { name "check_collisions_1"; addr $8F73; size 1; comment "did any missile hit a player, or did players 2 or 3 hit a player..."; }; +label { name "check_collisions_2"; addr $981A; size 1; comment "did player 0 or 1 hit the playfield..."; }; +label { name "check_collisions_3"; addr $9832; size 1; comment "did player 0 or 1 hit the playfield..."; }; +label { name "collision_save"; addr $06B0; size 16; comment "save_collisions copies GTIA collision regs $D000-$d00f here"; }; +label { name "init_next_level"; addr $9BE8; size 1; comment "..."; }; +label { name "show_get_ready_prompt"; addr $9624; size 1; comment "only in multiplayer games"; }; +range { name "gr7_or_masks"; start $8143; end $8152; type bytetable; }; +range { name "gr7_and_masks"; start $8153; end $8156; type bytetable; }; +range { name "data_8892"; start $8892; end $88A7; type bytetable; }; +range { name "data_8dfa"; start $8DFA; end $8DFF; type bytetable; }; +range { name "data_8f43"; start $8F43; end $8f72; type bytetable; }; + +##range { name "mus0_addr1"; start $8FC3; end $8fc4; type addrtable; comment "mus struct table, 5 bytes per entry: 0/1 are an address, 2/3 are another, 5 is maybe the length? tempo?"; }; +##range { name "mus0_addr2"; start $8FC5; end $8fc6; type addrtable; }; +##range { name "mus0_len_or_tempo"; start $8FC7; end $8fc7; type bytetable; }; +## +##range { name "mus1_addr1"; start $8FC8; end $8fc9; type addrtable; }; +##range { name "mus1_addr2"; start $8FCA; end $8fcb; type addrtable; }; +##range { name "mus1_len_or_tempo"; start $8FCC; end $8fcc; type bytetable; }; +## +##range { name "mus2_addr1"; start $8FC8; end $8fc9; type addrtable; }; +##range { name "mus2_addr2"; start $8FCA; end $8fcb; type addrtable; }; +##range { name "mus2_len_or_tempo"; start $8FCC; end $8fcc; type bytetable; }; + +#range { name "more_mus"; start $8FC8; end $8fff; type bytetable; comment "more 5-byte structs"; }; + +range { name "mus00_addr1"; start $8fc3; end $8fc4; type addrtable; comment "aka mus_struct_table, 5 bytes per entry"; }; +range { name "mus00_addr2"; start $8fc5; end $8fc6; type addrtable; }; +range { name "mus00_len_or_tempo"; start $8fc7; end $8fc7; type bytetable; }; + +range { name "mus01_addr1"; start $8fc8; end $8fc9; type addrtable; }; +range { name "mus01_addr2"; start $8fca; end $8fcb; type addrtable; }; +range { name "mus01_len_or_tempo"; start $8fcc; end $8fcc; type bytetable; }; + +range { name "mus02_addr1"; start $8fcd; end $8fce; type addrtable; comment "end of game tune"; }; +range { name "mus02_addr2"; start $8fcf; end $8fd0; type addrtable; }; +range { name "mus02_len_or_tempo"; start $8fd1; end $8fd1; type bytetable; }; + +range { name "mus03_addr1"; start $8fd2; end $8fd3; type addrtable; }; +range { name "mus03_addr2"; start $8fd4; end $8fd5; type addrtable; }; +range { name "mus03_len_or_tempo"; start $8fd6; end $8fd6; type bytetable; }; + +range { name "mus04_addr1"; start $8fd7; end $8fd8; type addrtable; }; +range { name "mus04_addr2"; start $8fd9; end $8fda; type addrtable; }; +range { name "mus04_len_or_tempo"; start $8fdb; end $8fdb; type bytetable; }; + +range { name "mus05_addr1"; start $8fdc; end $8fdd; type addrtable; }; +range { name "mus05_addr2"; start $8fde; end $8fdf; type addrtable; }; +range { name "mus05_len_or_tempo"; start $8fe0; end $8fe0; type bytetable; }; + +range { name "mus06_addr1"; start $8fe1; end $8fe2; type addrtable; }; +range { name "mus06_addr2"; start $8fe3; end $8fe4; type addrtable; }; +range { name "mus06_len_or_tempo"; start $8fe5; end $8fe5; type bytetable; }; + +range { name "mus07_addr1"; start $8fe6; end $8fe7; type addrtable; }; +range { name "mus07_addr2"; start $8fe8; end $8fe9; type addrtable; }; +range { name "mus07_len_or_tempo"; start $8fea; end $8fea; type bytetable; }; + +range { name "mus08_addr1"; start $8feb; end $8fec; type addrtable; comment "tune that plays while level is being drawn"; }; +range { name "mus08_addr2"; start $8fed; end $8fee; type addrtable; }; +range { name "mus08_len_or_tempo"; start $8fef; end $8fef; type bytetable; }; + +range { name "mus09_addr1"; start $8ff0; end $8ff1; type addrtable; }; +range { name "mus09_addr2"; start $8ff2; end $8ff3; type addrtable; }; +range { name "mus09_len_or_tempo"; start $8ff4; end $8ff4; type bytetable; }; + +range { name "mus10_addr1"; start $8ff5; end $8ff6; type addrtable; }; +range { name "mus10_addr2"; start $8ff7; end $8ff8; type addrtable; }; +range { name "mus10_len_or_tempo"; start $8ff9; end $8ff9; type bytetable; }; + +range { name "mus11_addr1"; start $8ffa; end $8ffb; type addrtable; }; +range { name "mus11_addr2"; start $8ffc; end $8ffd; type addrtable; }; +range { name "mus11_len_or_tempo"; start $8ffe; end $8ffe; type bytetable; }; + +range { name "empty_music_entry"; start $8fff; end $8fff; type bytetable; comment "empty music table entries point here"; }; + +label { name "sfx_tempo_tmp"; addr $0661; comment "??"; }; +label { name "sfx_slot_curpos"; addr $064E; size 2; comment "address we've got to so far, playing this sfx"; }; +label { name "sfx_slot_tempo"; addr $063E; size 1; comment "tempo of this sfx"; }; +label { name "sfx_lock"; addr $062F; size 1; comment "lets other code know cue_sfx is still running? not 100% sure"; }; +label { name "inc_sfx_pos"; addr $8231; size 1; comment "point to next byte in current sfx slot indexed by X"; }; +label { name "sfx_finished"; addr $8226; size 1; comment "done playing this sfx, free up the slot, X-indexed"; }; +label { name "sfx_next_note"; addr $817D; size 1; }; +label { name "sfx_player_entry"; addr $8157; size 1; comment "we have 4 slots (because POKEY has 4 voices), X counts down by 2 from 10 to 2 (at 0, the loop exits)"; }; +label { name "next_sfx_slot"; addr $815F; size 1; }; +label { name "sfx_exit"; addr $815E; size 1; }; +label { name "is_slot_active"; addr $8163; size 1; comment "skip it, if slot is inactive"; }; +label { name "sfx_slot_timer"; addr $063F; size 1; }; +label { name "sfx_slot_duration"; addr $0646; size 1; }; +label { name "sfx_play_note"; addr $8206; size 1; comment "y==0, a>=4 on entry"; }; +label { name "sfx_play_rest"; addr $819E; size 1; comment "y==0 on entry"; }; +label { name "sfx_change_tempo"; addr $81AE; size 1; comment "y==0 on entry"; }; +label { name "sfx_jump"; addr $81C8; size 1; comment "I *think* this jumps to a different sfx address..."; }; +label { name "sfx_slot_freq"; addr $0647; size 1; }; + +range { name "sfx00"; start $BDF2; end $BE24; type bytetable; }; +range { name "sfx01"; start $BE25; end $BE78; type bytetable; }; +range { name "sfx_extra_life"; start $BE79; end $BE8C; type bytetable; }; +range { name "sfx02"; start $BE8D; end $BEAE; type bytetable; comment "end of game tune, melody"; }; +range { name "sfx03"; start $BEAF; end $BED4; type bytetable; comment "end of game tune, bass"; }; +range { name "sfx04"; start $BED5; end $BEEC; type bytetable; comment "end level tune #1, bass"; }; +range { name "sfx05"; start $BEED; end $BF13; type bytetable; comment "end level tune #1, melody"; }; +range { name "sfx06"; start $BF14; end $BF2F; type bytetable; comment "end level tune #2, melody"; }; +range { name "sfx07"; start $BF30; end $BF49; type bytetable; comment "end level tune #2, bass"; }; +range { name "sfx08"; start $BF4A; end $BF5F; type bytetable; comment "end level tune #3, bass"; }; +range { name "sfx09"; start $BF60; end $BF83; type bytetable; comment "end level tune #3, melody"; }; +range { name "sfx10"; start $BF84; end $BFA5; type bytetable; comment "end level tune #4, melody"; }; +range { name "sfx11"; start $BFA6; end $BFBD; type bytetable; comment "end level tune #4, bass"; }; +range { name "sfx12"; start $BFBE; end $BFCF; type bytetable; comment "jumping sound"; }; +range { name "sfx13"; start $BFD0; end $BFE9; type bytetable; comment "funeral march melody"; }; +range { name "sfx14"; start $BFEA; end $BFF9; type bytetable; comment "funeral march bass"; }; +range { name "sfx15"; start $BABC; end $BAE9; type bytetable; comment "level intro music, melody"; }; +range { name "sfx16"; start $BAEA; end $BAFF; type bytetable; comment "level intro music, bass"; }; + +range { name "code_8f38"; start $8F38; end $8F42; type code; }; +range { name "try_to_write_rom_again"; start $9126; end $9133; type code; comment "see comment at try_to_write_rom"; }; +range { name "code_adb5"; start $ADB5; end $adc0; type code; }; +range { name "code_adc1"; start $adc1; end $adc3; type code; }; +range { name "data_9134"; start $9134; end $9139; type bytetable; }; +label { name "maybe_data"; addr $913A; comment "this might be more data for the above table instead of code?"; }; +label { name "probly_code"; addr $913D; comment "this probably really is code"; }; +label { name "illegal_nop"; addr $AF1B; comment "NMOS 6502 illegal opcode, NOP zp"; }; +range { name "data_9afc"; start $9AFC; end $9aff; type bytetable; }; +range { name "num_player_dli_service"; start $9578; end $959a; type code; comment "DLI service routine, changes COLPF2, address gets stored in $6ae/$6af by code at $944e"; }; +range { name "dli_service_2"; start $bdc7; end $bdd1; type code; comment "DLI service routine, changes COLBK, address gets stored in $6ae/$6af by code at $bc3c"; }; +label { name "numplayer_screen_data_minus_one"; addr $959a; comment "1-indexed loop copies from here+1"; }; +range { name "numplayer_screen_data"; start $959b; end $95ff; type bytetable; comment "'number of players?', gets copied to $3800, see option_key_handler"; }; +range { name "sfx_add_life_bonus"; start $b896; end $b8a6; type bytetable; comment "played when adding bonus per life at end of level"; }; +range { name "mul_25_table"; start $b8a7; end $b8be; type wordtable; comment "multiply by 25"; }; +range { name "data_table_8a39"; start $8a39; end $8a7f; type bytetable; }; +range { name "data_table_86da"; start $86da; end $8713; type bytetable; }; +range { name "level_name_hscrol_table"; start $BBF0; end $BBff; type bytetable; comment "used for centering level name on gameboard"; }; +range { name "zero_filler_b8bf"; start $b8bf; end $b96a; type bytetable; comment "all zeroes, filler?"; }; +range { name "zero_filler_baab"; start $baab; end $babb; type bytetable; comment "filler?"; }; +range { name "code_bccd"; start $bccd; end $bcd8; type code; comment "dunno, but referenced by code at $BC6A"; }; +range { name "well_done_map"; start $bcd9; end $bd51; type bytetable; comment "level map used for the WELL DONE screen, when you beat level 12"; }; +range { name "well_done_shape"; start $bda0; end $bdc6; type bytetable; comment "used to draw the large WELL DONE banner"; }; +range { name "total_score_msg"; start $bdd2; end $bdf1; type bytetable; comment "not sure what displays this, but it's screen codes"; }; +range { name "zero_filler_8588"; start $B588; end $B696; type bytetable; }; +range { name "wind_table_1"; start $B76B; end $b7bf; type bytetable; comment "used in level11"; }; +label { name "wind_table_2"; addr $b771; }; +range { name "level00_map"; start $A300; end $a497; type bytetable; comment "level map data starts here"; }; +range { name "sfx_a52d"; start $A52D; end $A53C; type bytetable; comment "dunno, referenced by routine at $A50F"; }; +range { name "data_table_a542"; start $A542; end $A68B; type bytetable; comment "dunno, referenced by routine at $A498"; }; +range { name "dumbwaiter_player"; start $a782; end $A826; type bytetable; comment "the dumbwaiters from level02. stored upside-down."; }; +label { name "dw_platform_player"; addr $A685; comment "horizontally moving platforms from level02"; }; +range { name "data_table_a8fd"; start $a8fd; end $A9C6; type bytetable; comment "dunno, referenced by routine at $A8D4"; }; +range { name "map_aa90"; start $aa90; end $AD67; type bytetable; comment "dunno what this is for yet"; }; +label { name "map_aaa6"; addr $aaa6; comment "referenced by routine at $AA82"; }; +range { name "data_table_adc7"; start $adc7; end $af0c; type bytetable; comment "dunno, referenced by routines at $AD9E and $ADB5"; }; +range { name "sfx_afcb"; start $AFCB; end $b0c3; type bytetable; comment "referenced by routine at $AF96"; }; +label { name "map_b000"; addr $b000; comment "referenced by routine at $B0C4"; }; +range { name "data_table_85b6"; start $85b6; end $85bd; type bytetable; comment "used in vblank_imm_isr, not sure for what yet"; }; +range { name "data_table_85de"; start $85de; end $85f5; type bytetable; comment "dunno what this is for yet, but it's copied into page 6 by init_hardware"; }; +range { name "zero_filler_85f6"; start $85f6; end $85ff; type bytetable; comment "probably just filler"; }; +range { name "movement_direction_table"; start $85be; end $85dd; type wordtable; comment "X/Y movement, indexed by joystick_state << 1, each entry is XXYY, $FF is -1"; }; +range { name "get_ready_msg"; start $9714; end $9726; type bytetable; comment "PLAYER GET READY"; }; +range { name "pcolor0_table"; start $8B7B; end $8b7f; type bytetable; }; +range { name "color0_table"; start $9728; end $972b; type bytetable; }; +range { name "color0_table_minus_one"; start $9727; end $9727; type bytetable; }; +range { name "level_gfx"; start $9C21; end $9cff; type bytetable; comment "definitions for level graphics objects aka shapes. (girder segment, ladder, rope, etc)"; }; +label { name "sh_girder"; addr $9C33; comment "3 rows of pixels. 1st: 04 = 4 pixels wide, 00 00 = no X/Y offset, 01 01 01 01 = actual pixel data (4 color0 pixels). see level_maps.txt"; }; +label { name "sh_blank_4x4"; addr $9C49; }; +label { name "sh_ladder"; addr $9C5F; }; +label { name "sh_9c89"; addr $9c89; comment "dunno what this is yet"; }; +label { name "sh_bomb"; addr $9cb3; }; +label { name "sh_up_rope"; addr $9cc9; }; +label { name "sh_down_rope"; addr $9cda; }; +label { name "sh_9ceb"; addr $9ceb; comment "dunno what this is yet"; }; +range { name "sprite_table"; start $9d00; end $9dff; type bytetable; comment "jumpman's animation frames and other sprites, seem to be 10 bytes per sprite"; }; +range { name "sxf_b319"; start $b319; end $B44B; type bytetable; comment "referenced by routine at $B2FD"; }; +range { name "data_table_b1df"; start $b1df; end $B27d; type bytetable; comment "dunno what this is for yet"; }; +range { name "data_table_b2a8"; start $b2a8; end $B2df; type bytetable; comment "dunno what this is for yet"; }; +range { name "data_table_b50b"; start $b50b; end $B57b; type bytetable; comment "dunno what this is for yet"; }; +range { name "scores_screen_dlist"; start $8C52; end $8C67; type bytetable; comment "a GR.2-ish DL, with DLIs, screen mem at $3000, for player scores screen"; }; +label { name "reyalp_msg_minus_one"; addr $8c67; }; +label { name "show_reyalp_msg"; addr $8BC0; comment "shows PLAYER (backwards loop)"; }; +label { name "reyalp_msg_loop"; addr $8BC2; }; +label { name "check_10th"; addr $8BC8; comment "replace 10th char with the ASCII player number"; }; +label { name "continue_loop"; addr $8BD5; }; +label { name "check_alive"; addr $8BE9; comment "player still has lives left?"; }; +label { name "no_cross"; addr $8BEF; }; +label { name "what_are_we_waiting_for"; addr $8C39; comment "I *think* we're waiting for the music to finish playing..."; }; + +label { name "jiffy_timer_1"; addr $061A; comment "gets incremented every frame"; }; +label { name "jiffy_timer_2"; addr $061B; comment "gets incremented every frame"; }; +label { name "bonus_jiffy_timer"; addr $0626; comment "gets incremented every frame when playing a level, bonus-=100 when this reaches 0"; }; +label { name "speed_jiffy_timer"; addr $061E; comment "counts 0..initial_speed"; }; +label { name "playing_level"; addr $0627; comment "0 = not playing, non-0 = playing"; }; +label { name "no_dec_bonus"; addr $848B; }; +label { name "add_time_bonus"; addr $8E0F; comment "score += time_bonus;"; }; +label { name "lt_64k"; addr $8E27; }; +label { name "wait_32_jiffies"; addr $8E3A; comment "533ms ntsc, 640ms pal"; }; +label { name "pick_random_music"; addr $8E41; comment "pick random sound effect between 4 and 7"; }; +label { name "cue_music"; addr $8F92; comment "setup to play whichever music is in A reg, using 5-byte sfx stuct (a music is a pair of sfx played simultaneously)"; }; +label { name "cue_music_jv"; addr $8018; comment "setup to play whichever music is in A reg, using 5-byte sfx stuct"; }; +label { name "cue_sfx_jv"; addr $8006; comment "setup to play sfx"; }; +label { name "cue_sfx"; addr $8255; comment "setup to play sfx at *sfx_ptr, tempo (?) A"; }; +label { name "cue_sfx_lowprior"; addr $8240; comment "if cue_sfx not already in progress, setup to play sfx at (sfx_slot_tempo, sfx_lock) tempo (?) A"; }; +label { name "sfx_ptr"; addr $063C; size 2; }; +label { name "cue_ok"; addr $8244; size 1; }; +label { name "cue_done"; addr $8278; size 1; }; +label { name "inc_done"; addr $823F; size 1; }; + +label { name "wait_3_sec"; addr $8C4A; comment "wait 192 jiffies: 3.2 sec (ntsc), 3.84 sec (pal)"; }; +label { name "not_alive"; addr $8BEB; comment "no, show a cross instead of a space"; }; +label { name "store_space"; addr $8BE2; comment "$AF is the character to show after the score (space for alive, cross for dead)"; }; +range { name "reyalp_msg"; start $8C68; end $8C7a; type bytetable; comment "player spelled backwards: ' 0 # REYALP '"; }; +range { name "scores_msg"; start $8C7b; end $8C81; type bytetable; comment "' SCORES' in color 3"; }; +range { name "blank_dlist_8add"; start $8ADD; end $8adf; type bytetable; comment "yet another jump-to-itself empty display list"; }; +range { name "blank_dlist_8aeb"; start $8AEB; end $8aed; type bytetable; comment "another jump-to-itself empty display list"; }; +range { name "blank_dlist_8c82"; start $8C82; end $8C84; type bytetable; comment "looks like an empty jump-to-itself dlist"; }; +label { name "init_game"; addr $9000; comment "called from cart_entry_point routine"; }; +label { name "reinit_game"; addr $900C; comment "this entry point doesn't disable start/option keys"; }; +label { name "try_to_write_rom"; addr $9022; comment "seems to try to write $FF bytes to ROM that already contains $FF's (it's the solid block character in the font). possibly left over from early development before conversion to cartridge"; }; +label { name "setup_select_key_vec"; addr $901b; comment "set select key vector to ask_num_players at $9400, enable select key"; }; +label { name "setup_select_key_vec_again"; addr $9517; comment "set select key vector to ask_num_players at $9400, enable select key"; }; +label { name "disable_start_opt"; addr $94EC; comment "disable start and option keys"; }; +label { name "init_speed"; addr $952a; comment "initialize speed to -1"; }; +label { name "wait_for_speed"; addr $952F; comment "wait for keyboard IRQ handler to set a speed <= 8"; }; +label { name "speed_to_ascii"; addr $9540; comment "convert to ASCII digit"; }; +label { name "add_11_to_x"; addr $953B; comment "11-byte per-player struct?"; }; +label { name "struct_player_lives_offsets_minus_one"; addr $8C88; }; +label { name "struct_player_lives_offsets"; addr $8C89; comment "lookup table, offset from $713 to lives for indexed player"; }; +label { name "show_scores_screen"; addr $8C22; comment "set dlist shadow to scores_screen_dlist"; }; +label { name "display_speed"; addr $9542; comment "show it to the user"; }; +label { name "speed_value"; addr $06F9; comment "decoded speed (1-8)"; }; +label { name "show_player_speed_prompt"; addr $94F9; comment "copy PLAYER #n SPEED? to screen RAM"; }; +label { name "psprompt_loop"; addr $94fb; }; +range { name "get_ready_dlist"; start $972c; end $973f; type bytetable; comment "112 blank scanlines, then one GR.2 line, loaded from $0742"; }; +range { name "score_offsets"; start $8C85; end $8c8c; type bytetable; comment "offsets into screen memory, column 12, rows 2 3 4 5, used by code at $8BEF, loaded in $d3, hi byte in $d4 is $30"; }; +label { name "score_screen_dli_sr"; addr $8C8D; comment "used by score screen"; }; +label { name "set_score_screen_dli"; addr $8C31; comment "dli = score_screen_dli_sr"; }; +range { name "title_screen_data"; start $91cf; end $93ff; type bytetable; comment "title screen data"; }; + +label { name "title_screen_data_minus_one"; addr $91ce; }; +label { name "copy_title_screen"; addr $902A; }; +label { name "wait_until_9c_is_0e"; addr $906E; comment "some ISR is writing to $9c..."; }; +label { name "funky_init_loop"; addr $90C8; comment "lot going on here, not understood yet"; }; +label { name "player_scores_screen"; addr $8B80; comment "show scores, called at end of game, also called after beating level 12 (after WELL DONE). $40 in NMIEN = disable DLI, enable VBI"; }; +label { name "read_joystick"; addr $84AC; comment "always joystick #1 (all players use the same joystick and pass it around)"; }; +label { name "check_joystick_enabled"; addr $84A4; comment "read the joystick if not disabled"; }; +label { name "fake_read_trigger"; addr $84CD; comment "??"; }; +label { name "read_trigger"; addr $84D3; comment "always joystick #1"; }; +label { name "store_joystick_state"; addr $84B1; comment "store bottom 4 bits of PORTA, or 0 if joystick_disabled"; }; +label { name "clear_collisions"; addr $850D; }; +label { name "update_dlist"; addr $8510; comment "update display list, if there's a new one in the shadow reg"; }; +label { name "update_dli_vector"; addr $8523; comment "update DLI vector, if there's a new one in the shadow reg"; }; +label { name "setup_get_ready_dl"; addr $964A; comment "06ac/06ad gets address of get_ready_dlist (why not SDLSTL/H?)"; }; +label { name "end_of_level_bonus"; addr $B800; }; +label { name "keycode_table_minus_one"; addr $9c18; }; +range { name "keyboard_isr"; start $9C00; end $9c18; type code; comment "only use of keyboard is to enter player speed before starting game"; }; +range { name "keycode_table"; start $9C19; end $9c20; type bytetable; }; +#label { name "mul_25_table"; addr $B8A7; size 2; }; + +label { name "init_hardware"; addr $837c; }; +label { name "init_page6_loop"; addr $837e; comment "movement_direction_table+31 should read data_table_85de-1, da65 isn't perfect yet"; }; + +# these are so far only for player 1 +label { name "number_of_players"; addr $06f4; size 1; comment "0 for single-player game, otherwise range 1-3 (2 to 4 players)"; }; +label { name "score"; addr $0700; size 3; }; +label { name "level"; addr $06f6; size 1; }; +label { name "lives"; addr $070a; size 1; }; +label { name "current_player"; addr $06fe; size 1; comment "*think* this ranges 1-4, not 0-3"; }; +label { name "player_speed"; addr $0624; size 1; }; +label { name "initial_speed"; addr $0625; size 1; }; +label { name "setup_dli_2"; addr $bc3f; size 1; comment "load dli_service_2 address into dli shadow"; }; +label { name "silence_audio"; addr $875B; size 1; comment "set all AUDFx to 0"; }; +label { name "sa_loop"; addr $875F; size 1; }; +label { name "store_audc"; addr $8DC6; size 1; comment "store A to AUDCx (and its ?shadow?)"; }; +label { name "set_prior"; addr $8798; size 1; comment "priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles) [redundant? init_set_prior sets this, nothing appears to change it]"; }; +label { name "SAVMSC"; addr $58; size 2; comment "OS's idea of the start of screen memory [redundant to set here?]"; }; +label { name "set_char_base"; addr $83BB; size 1; comment "use character set at $9e00 aka charset"; }; +label { name "set_savmsc"; addr $83E9; size 1; comment "tell OS that screen memory starts at $3000"; }; +label { name "position_player_5"; addr $8310; size 1; comment "position the 4 missiles side-by-side"; }; +label { name "init_set_prior"; addr $8399; size 1; comment "priority $11: pl0-3, pf0-3, bak (and enable 5th player from the missiles)"; }; +label { name "joystick_disabled"; addr $0632; size 1; comment "nonzero = jumpman can't move (title screen or materialization, etc)"; }; +label { name "joystick_state"; addr $0633; size 1; comment "last PORTA read (bottom 4 bits), or 0 if joystick_disabled"; }; +label { name "trigger_disabled"; addr $0634; size 1; comment "nonzero = jumpman can't jump (he's already jumping, or title screen or materialization, etc)"; }; +label { name "trigger_state"; addr $0635; size 1; comment "last TRIG0 read (0 = pressed)"; }; +label { name "check_trigger_state"; addr $984D; size 1; comment "did user press the trigger?"; }; +label { name "trig_jmp"; addr $9852; size 1; comment "yes, jump to handler"; }; +label { name "check_up_down"; addr $9855; size 1; comment "did user move joystick up/down?"; }; +label { name "check_up_down_2"; addr $993B; size 1; comment "did user move joystick up/down?"; }; +label { name "trigger_handler"; addr $9985; size 1; comment "handle trigger presses (maybe start a jump)"; }; +label { name "cud_jmp"; addr $9860; size 1; comment "no, jump over handler"; }; +label { name "player_delta_x"; addr $0630; size 1; comment "amount to move jumpman this frame (1 or $FF aka -1)"; }; +label { name "player_delta_y"; addr $0631; size 1; comment "amount to move jumpman this frame (1 or $FF aka -1)"; }; +label { name "dli_vec_shadow_hi"; addr $06AF; size 1; comment "stored in VDSLST if nonzero"; }; +label { name "dli_vec_shadow_lo"; addr $06ae; size 1; comment "stored in VDSLST if dli_vec_shadow_hi nonzero"; }; +label { name "dlist_shadow_hi"; addr $06AD; size 1; comment "stored in DLISTH if nonzero"; }; +label { name "dlist_shadow_lo"; addr $06ac; size 1; comment "stored in DLISTL if dlist_shadow_hi nonzero"; }; +label { name "clear_dlist_shadow"; addr $851E; size 1; comment "clear the shadow now that we've updated the HW"; }; +label { name "clear_dli_shadow"; addr $8531; size 1; comment "clear the shadow now that we've updated the HW"; }; +label { name "enable_dli"; addr $8536; size 1; comment "enable DLI now that we've set up the vector"; }; +label { name "enable_keyboard_irq"; addr $8554; size 1; comment "$C0 = regular keypress, break keypress"; }; +label { name "silence_console_speaker"; addr $855A; size 1; comment "8 = silent (0 would be a click)"; }; +label { name "check_start_key"; addr $8561; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "check_select_key"; addr $8573; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "check_option_key"; addr $8580; size 1; comment "carry set = not pressed, clear = pressed"; }; +label { name "setup_start_key_vec"; addr $9465; size 1; comment "we'll jump to $94de aka get_player_speeds when start key is pressed"; }; +label { name "get_player_speeds"; addr $94de; size 1; comment "loop up to 4 times, ask PLAYER #n SPEED? and wait for number key press"; }; +label { name "setup_option_key_vec"; addr $9458; size 1; comment "we'll jump to $9489 aka option_key_handler when option key is pressed"; }; +label { name "start_key_vec"; addr $06c4; size 2; comment "vblank_imm_isr jumps thru here if start key pressed"; }; +label { name "select_key_vec"; addr $06c2; size 2; comment "vblank_imm_isr jumps thru here if select key pressed"; }; +label { name "option_key_vec"; addr $06c0; size 2; comment "vblank_imm_isr jumps thru here if option key pressed"; }; +label { name "start_key_enabled"; addr $06C8; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "select_key_enabled"; addr $06C7; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "option_key_enabled"; addr $06C6; size 1; comment "non-zero = jump through start_key_vec if start key pressed (checked by vblank_imm_isr)"; }; +label { name "zp_temp1"; addr $cb; size 2; comment "used for (zp,y) addressing, also for checking console keys in vblank_imm_isr"; }; +label { name "hang_main_thread"; addr $9486; size 1; comment "initialization done, everything's done in interrupts from here on out"; }; +label { name "option_key_handler"; addr $9489; size 1; comment "called via option_key_vec when someone presses option"; }; + +label { name "level_finished"; addr $8E00; size 1; }; +label { name "level_finished_jv"; addr $802D; size 1; }; +label { name "decrement_time_bonus"; addr $8DCE; size 1; comment "bonus -= 100;"; }; +label { name "decrement_time_bonus_jv"; addr $8021; size 1; comment "bonus -= 100;"; }; +label { name "check_bonus_0"; addr $8DD7; size 1; comment "don't decrement if bonus == 0"; }; +label { name "dec_done"; addr $8DF9; size 1; }; +label { name "bonus_lt_256"; addr $8DE7; size 1; }; + +label { name "set_y"; addr $8F9B; size 1; comment "y = a * 5; // offset into mus_struct_table"; }; + + +label { name "show_level_name"; addr $BA5D; size 1; comment "copy level name into screen RAM"; }; +label { name "sync_to_music"; addr $BA71; size 1; comment "level is already drawn with all color regs set to black. for each color reg, wait 1 sec before turning it visible. this syncs up with the music because the music was written to sync with this actually"; }; +label { name "wait_1_sec"; addr $BA9E; size 1; comment "actually 64 jiffies, 1.067S ntsc, 1.28s pal"; }; +label { name "keep_waiting"; addr $BAA3; size 1; }; +label { name "enable_joystick"; addr $8775; size 1; comment "called after level-intro music is finished playing"; }; +label { name "enable_joystick_jv"; addr $801B; size 1; comment "called after level-intro music is finished playing"; }; +label { name "ej_loop"; addr $8777; size 1; }; +label { name "hide_player"; addr $8DB8; size 1; comment "move player selected by X reg minus one off the left edge of the screen"; }; +label { name "play_select_key_sfx"; addr $946F; size 1; comment "play sfx_select_key at $95f1"; }; +label { name "wait_sfx"; addr $947C; size 1; comment "wait for sound to finish playing"; }; +label { name "play_life_bonus_sfx"; addr $B868; size 1; comment "play once per life"; }; +label { name "add_life_bonus"; addr $B83B; size 1; }; +label { name "sfx_option_pressed"; addr $8ab0; size 1; }; +label { name "play_opt_key_sfx"; addr $94BC; size 1; }; +label { name "wait_opt_key_sfx"; addr $94CE; size 1; comment "wait until it's done playing"; }; +range { name "map_b11a"; start $B11A; end $b120; type bytetable; comment "dunno what this is for yet"; }; +label { name "block_char_minus_one"; addr $9e0f; size 1; comment "couple of places in the code try to write here"; }; +label { name "position_players"; addr $82E9; size 1; comment "X counts down 5..1 (starts at 6, immediately decremented, and loop is done with 0). zp_temp1 is ZP pointer to the current player or missile being written to ($2f00..$2b00, or p3/p2/p1/p0/missiles)."; }; +label { name "HPOSP0_minus_two"; addr $CFFE; size 1; }; +label { name "position_pm_vert"; addr $8322; size 1; }; +label { name "clear_pm"; addr $8342; size 1; comment "write zeroes to unused portion of this player/missile"; }; +label { name "position_done"; addr $82E8; size 1; }; +label { name "clear_pm_mem"; addr $872A; size 1; comment "clear P/M mem"; }; +label { name "clear_screen_mem"; addr $8714; size 1; comment "clear the gameboard screen memory (called before drawing a level, natch)"; }; +label { name "clear_screen_mem_jv"; addr $801E; size 1; comment "clear the gameboard screen memory (called before drawing a level, natch)"; }; +label { name "csm_loop"; addr $871F; size 1; }; +label { name "dm_obj_to_screen"; addr $80BD; size 1; comment "actually write the object's pixels to screen memory. quite hairy."; }; +label { name "unused_vecs"; addr $803F; size 1; comment "3 unused jump vectors, all pointed to the same RTS"; }; +label { name "unused_vec_rts"; addr $8048; size 1; comment "unused jump vectors point here"; }; +label { name "sfx_bounce_1"; addr $8A4B; size 1; comment "used when jumpman is falling?"; }; +range { name "sfx_bounce_2"; start $8a97; end $8abf; type bytetable; comment "used when jumpman is falling?"; }; +label { name "sfx_death"; addr $8a60; comment "jumpman hit by bullet or started falling"; }; +label { name "play_sfx_bounce_2"; addr $8A80; }; +label { name "play_sfx_bounce_1"; addr $899A; }; +label { name "falling_bounce"; addr $8983; comment "this looks like it hurts..."; }; +label { name "afterlife"; addr $9600; comment "multiple code paths jump here. replay level, load next level, or go back to ask_num_players"; }; +label { name "code_bd52"; addr $BD52; comment "referenced by code at $BC83"; }; +label { name "crumble_gameboard"; addr $8D00; comment "just lost your last life"; }; +label { name "crumble_gameboard_jv"; addr $8030; comment "just lost your last life"; }; +label { name "init_page_7"; addr $9A5C; }; +label { name "init_page_7_jv"; addr $8024; }; +range { name "data_9a71"; start $9A71; end $9a7b; type bytetable; comment "used by code above"; }; +range { name "l_equals"; start $8CFD; end $8CFF; type bytetable; comment "L= (for lives display)"; }; +label { name "add_extra_life"; addr $8CE4; comment "plays sfx_extra_life"; }; +label { name "show_l_equals"; addr $8CCE; comment "L= (for lives display)"; }; +label { name "show_lives_icons"; addr $86BB; comment "up to 6 jumpmen, and a + if lives > 6. char $C1 = jumpman icon, $CB = plus sign"; }; +label { name "show_current_player"; addr $86A7; comment "1 to 4"; }; +label { name "update_status_window"; addr $8694; comment "bottom 2 GR.1 lines on the game board"; }; +label { name "update_status_window_jv"; addr $8012; comment "bottom 2 GR.1 lines on the game board"; }; +label { name "setup_gameboard_dlist"; addr $9B00; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; +label { name "setup_gameboard_dlist_jv"; addr $8015; comment "for some reason there are 2 copies of the display list, at $0800 and $0881"; }; +label { name "xxx_level_something"; addr $8600; comment "gets called after the level is drawn & the intro music stops, and also during the level (?)"; }; +label { name "xxx_level_something_jv"; addr $8009; comment "gets called after the level is drawn & the intro music stops, and also during the level (?)"; }; +label { name "draw_map"; addr $8049; comment "the entry point for parsing the level map and drawing graphics from it. see level_maps.txt. caller must set $C0/$C1 to the address of the map data. modders beware: bogus map data can & will cause infinite loops."; }; +label { name "draw_map_jv"; addr $8000; comment "the entry point for parsing the level map and drawing graphics from it. see level_maps.txt."; }; +label { name "dm_get_opcode"; addr $804B; comment "$C0/$C1 points to $A300 (level00_desc) on the first call"; }; +label { name "dm_switch_opcode"; addr $804D; comment "map opcodes: $FC = jump, $FF = end, $FD = set drawing direction, $FE = select graphics object"; }; +label { name "dm_draw_gfx"; addr $8090; comment "handle gfx_draw opcode"; }; +label { name "dm_jump"; addr $805C; comment "handle gfx_jump opcode"; }; +label { name "dm_delta"; addr $806B; comment "handle gfx_delta opcode"; }; +label { name "dm_obj"; addr $8083; comment "handle gfx_object opcode"; }; +label { name "dm_fallthru"; addr $805B; comment "handle gfx_end opcode"; }; +label { name "dm_next_opcode"; addr $8075; comment "all the other opcode handlers jump here"; }; +label { name "dm_progctr"; addr $C0; size 2; comment "see draw_map and level_maps.txt"; }; +label { name "dm_delta_x"; addr $C9; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_delta_y"; addr $CA; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_objptr"; addr $C2; size 2; comment "see draw_map and level_maps.txt"; }; +label { name "dm_xpos"; addr $55; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_ypos"; addr $54; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_length"; addr $BF; size 1; comment "see draw_map and level_maps.txt"; }; +label { name "dm_draw_loop"; addr $809C; size 1; comment "loop 'dm_length' times"; }; +label { name "dm_draw_obj"; addr $80B4; size 1; comment "draw current object at current x/y position"; }; +label { name "dm_draw_obj_loop"; addr $80B6; size 1; comment "object definition ends with $FF"; }; +label { name "dm_count"; addr $BE; size 1; comment "graphics object definition is this long"; }; +label { name "dm_x_with_offset"; addr $C6; size 1; comment "graphics object X offset, plus dm_xpos"; }; +label { name "dm_y_with_offset"; addr $C7; size 1; comment "graphics object Y offset, plus dm_xpos"; }; +label { name "dm_screen_addr"; addr $C4; size 2; comment "points to byte to write gfx data to"; }; +label { name "calc_screen_addr"; addr $80D0; size 1; comment "calculate 40 * dm_y_with_offset + dm_x_with_offset + screen mem address, store in dm_screen_addr"; }; +label { name "store_rts"; addr $83B6; comment "store an RTS at $06E6, which will get JSR'ed to by unused level subroutines"; }; +label { name "well_done_screen"; addr $BC00; comment "the WELL DONE screen, when you beat all the levels. after this, the game plays random levels."; }; +label { name "cue_woop_sound"; addr $B4D3; }; +label { name "sfx_woop"; addr $B564; }; +label { name "got_all_bombs"; addr $9766; }; +label { name "call_eol_sub"; addr $976C; }; + +# end of main.info, everything below here is generated by mklevelinfo.pl diff --git a/mapping.txt b/mapping.txt new file mode 100644 index 0000000..584b8a1 --- /dev/null +++ b/mapping.txt @@ -0,0 +1,8814 @@ + MEMORY MAP + + Locations zero to 255 ($0 to $FF) are called "page zero" and have + special importance for assembly language programmers since these + locations are accessed faster and easier by the machine. + + Locations zero to 127 ($0 to $7F) are reserved as the OS page zero, + while 128 to 255 ($80 to $FF) are the BASIC and the user zero page + RAM. Locations zero to 1792 ($0 to $700) are all used as the OS and (if + the cartridge is present) 8K BASIC RAM (except page six). Locations + zero to 8191 ($0 to $1FFF) are the minimum required for operation + (8K). + + Locations two through seven are not cleared on any start operation. + + DECIMAL HEX LABEL + + 0,1 0,1 LINZBS + + LINBUG RAM, replaced by the monitor RAM See the OS + Listing, page 31. It seems to be used to store the VBLANK timer + value. One user application I've seen for location zero is in a + metronome program in De Re Atari. Also used in cross- + assembling the Atari OS. + + + 2,3 2,3 CASINI + + Cassette initialization vector: JSR through here if the cassette + boot was successful. This address is extracted from the first six + bytes of a cassette boot file. The first byte is ignored. The second + contains the number of records, the third and fourth contain the + low and high bytes of the load address, and the fifth and sixth + contain the low and high bytes of the initialization address. + Control upon loading jumps to the load address plus six for a + multi-stage load and through CASINI for initialization. JSR + through DOSVEC (10 and 11; $A,$B) to transfer control to the + application. + + + 4,5 4,5 RAMLO + + RAM pointer for the memory test used on powerup. Also used to + store the disk boot address--normally 1798 ($706)--for the + boot continuation routine. + + + 6 6 TRAMSZ + + Temporary Register for RAM size; used during powerup + sequence to test RAM availability. This value is then moved to + RAMTOP, location 106 ($6A). Reads one when the BASIC or the + A (left) cartridge is plugged in. + + + 7 7 TSTDAT + + RAM test data register. Reads one when the B or the right + cartridge is inserted. + + RAMLO, TRAMSZ and TSTDAT are all used in testing the RAM + size on powerup. On DOS boot, RAMLO and TRAMSZ also act as + temporary storage for the boot continuation address. TRAMSZ + and TSTDAT are used later to flag whether or not the A (left) + and/or B (right) cartridges, respectively, are plugged in (non- + zero equals cartridge plugged in) and whether the disk is to be + hooted. + + Locations eight through 15 ($8-$F) are cleared on coldstart only. + + + 8 8 WARMST + + Warmstart flag. If the location reads zero, then it is in the middle + of powerup; 255 is the normal RESET status. Warmstart is similar + to pressing RESET, so should not wipe out memory, variables, or + programs. WARMST is initialized to zero and will not change + values unless POKEd or until the first time the RESET button is + pressed. It will then read 255 ($FF). + + Warmstart normally vectors to location 58484 ($E474). WARMST + is checked by the NMI status register at 54287 ($D40F) when + RESET is pressed to see whether or not to re-initialize the + software or to re-boot the disk. + + + 9 9 BOOT? + + Boot flag success indicator. A value of 255 in this location will + cause the system to lockup if RESET is pressed. If BOOT? reads + one, then the disk boot was successful; if it reads two, then the + cassette boot was successful. If it reads zero, then neither + peripheral was booted. + + If it is set to two, then the cassette vector at locations two and + three will be used on RESET. Set to one, it will use the DOS + vector at 10 and 11 ($A and $B). Coldstart attempts both a + cassette and a disk boot and flags this location with the success or + failure of the boots. BOOT? is checked during both disk and + cassette boot. + + + 10,11 A,B DOSVEC + + Start vector for disk (or non-cartridge) software. This is the + address BASIC jumps to when you call up DOS. Can be set by + user to point to your own routine, but RESET will return DOSVEC + to the original address. To prevent this, POKE 5446 with the LSB + and 5450 with the MSB of your vector address and re-save DOS + using the WRITE DOS FILES option in the menu. Locations 10 + and 11 are usually loaded with 159 and 23 ($9F and $17), + respectively. This allows the DUPSYS section of DOS to be + loaded when called. It is initially set to blackboard mode vector + (58481; $E471--called by typing "BYE" or "B." from BASIC); it + will also vector to the cassette run address if no DOS vector is + loaded in. If you create an AUTORUN.SYS file that doesn't end + with an RTS instruction, you should set BOOT? to one and 580 + ($244) to zero. + + + 12,13 C,D DOSINI + + Initialization address for the disk boot. Also used to store the + cassette-boot RUN address, which is then moved to CASINI (2, + 3). When you powerup without either the disk or an autoboot + cassette tape, DOSINI will read zero in both locations. + + + 14,15 E,F APPMHI + + Applications memory high limit and pointer to the end of your + BASIC program, used by both the OS and BASIC. It contains the + lowest address you can use to set up a screen and Display List + (which is also the highest address usable for programs and data + below which the display RAM may not be placed). The screen + handler will not OPEN the "S:" device if it would extend the + screen RAM or the Display List below this address; memory + above this address may be used for the screen display and other + data (PM graphics, etc.). + + If an attempted screen mode change would extend the screen + memory below APPMHI, then the screen is set up for GRAPHICS + mode zero; MEMTOP (locations 741, 742; $2E5, $2E6) is updated + and an error is returned to the user. Otherwise, the memory is not + too small for the screen editor; the mode change will take effect + and MEMTOP will be updated. This is one of five locations used + by the OS to keep track of the user and display memory. + Initialized to zero by the OS at powerup. Remember, you cannot + set up a screen display below the location specified here. + + If you use the area below the Display List for your character sets, + PM graphics or whatever, be sure to set APPMHI above the last + address used so that the screen or the DL data will not descend + and destroy your own data. See RAMTOP location 106 ($6A), + MEMTOP at 741, 742 ($2E5, $2E6), PMBASE at 54279 ($D407) + and CHBASE at 54281 ($D409) for more information. + + Locations 16 through 127 ($10-$7F) are cleared on either cold- or + warmstart. + + + 16 10 POKMSK + + POKEY interrupts: the IRQ service uses and alters this location. + Shadow for 53774 ($D20E). POKE with 112 ($70; also POKE this + same value into 53774) to disable the BREAK key. If the following + bits are set (to one), then these interrupts are enabled (bit + decimal values are in parentheses): + + BIT DECIMAL FUNCTION + 7 128 The BREAK key is enabled. + 6 64 The "other key" interrupt is enabled. + 5 32 The serial input data ready interrupt is + enabled. + 4 16 The serial output data required interrupt is + enabled. + 3 8 The serial out transmission finished + interrupt is enabled. + 2 4 The POKEY timer four interrupt is enabled + (only in the "B" or later versions of the OS + ROMs). + 1 2 The POKEY timer two interrupt is enabled. + 0 1 The POKEY timer one interrupt is enabled. + + Timer interrupt enable means the associated AUDF registers are + used as timers and will generate an interrupt request when they + have counted down to zero. See locations 528 to 535 ($210 to + $217) and the POKEY chip from locations 53760 ($D200) on, for a + full explanation. 192 ($C0) is the default on powerup. + + You can also disable the BREAK key by POKEing here with 64 + ($40; or any number less than 128; $80) and also in location + 53774. The problem with simple POKEs is that the BREAK key is + re-enabled when RESET is pressed and by the first PRINT + statement that displays to the screen, or any OPEN statement that + addresses the screen (S: or E:), or the first PRINT statement after + such an OPEN and any GRAPHICS command. In order to + continually disable the BREAK key if such commands are being + used, it's best to use a subroutine that checks the enable bits + frequently during input and output operations, and POKEs a + value less than 128 into the proper locations, such as: + + 1000 BREAK = PEEK(16) - 128: IF BREA + K < 0 THEN RETURN + 1010 POKE 16, BREAK: POKE 53774, BRE + AK: RETURN + + The new OS "B" version ROMs have a vector for the BREAK key + interrupt, which allows users to write their own routines to + process the interrupt in the desired manner. It is located at 566, + 567 ($236, $237). + + + 17 11 BRKKEY + + Zero means the BREAK key is pressed; any other number means + it's not. A BREAK during I/O returns 128 ($80). Monitored by + both keyboard, display, cassette and screen handlers. See + location 16 ($A) for hints on disabling the BREAK key. The latest + editions of OS provide for a proper vector for BREAK interrupts. + The BREAK key abort status code is stored in STATUS (48; $30). + It is also checked during all I/O and scroll/draw routines. During + the keyboard handler routine, the status code is stored in DSTAT + (76; $4C). BRKKEY is turned off at powerup. BREAK key abort + status is flagged by setting BIT 7 of 53774 ($D20E). See the note + on the BREAK key vector, above. + + + 18,19,20 12,13,14 RTCLOK + + Internal realtime clock. Location 20 increments every stage one + VBLANK interrupt (1/60 second = one jiffy) until it reaches 255 + ($FF); then location 19 is incremented by one and 20 is reset to + zero (every 4.27 seconds). When location 19 reaches 255, it and + 20 are reset to zero and location 18 is incremented by one (every + 18.2 minutes or 65536 TV frames). To use these locations as a + timer of seconds, try: + + TIME = INT((PEEK(18) * 65536 + PEEK(19) * 256 + + PEEK(20) )/60) + + To see the count in jiffies, eliminate the "/60" at the end. To see + the count in minutes, change "/60" to "/360." The maximum + value of the RT clock is 16,777,215. When it reaches this value, it + will be reset to zero on the next VBLANK increment. This value is + the result of cubing 256 (i.e., 256 * 256 * 256), the maximum + number of increments in each clock register. The RT clock is + always updated every VBLANK regardless of the time-critical + nature of the code being processed. + + A jiffy is actually a long time to the computer. It can perform + upwards of 8000 machine cycles in that time. Think of what can + be done in the VBLANK interval (one jiffy). In human terms, a + jiffy can be upwards of 20 minutes, as witnessed in the phrase "I'll + be ready in a jiffy." Compare this to the oft-quoted phrase, "I'll + be there in a minute," used by intent programmers to describe a + time frame upwards of one hour. + Users can POKE these clock registers with suitable values for + their own use. The realtime clock is always updated during the + VBLANK interval. Some of the other timer registers (locations + 536 to 544; $218 to $220) are not always updated when the OS is + executing time critical code. + Here's one way to use the realtime clock for a delay timer: + + 10 GOSUB 100 + . + . + . + 100 POKE 20,0: POKE 19,0 + 110 IF NOT PEEK(19) THEN 110 + 120 RETURN + + Line 110 waits to see if location 19 returns to zero and, when it + does, passes control to the RETURN statement. + + See COMPUTE!, August 1982, for a useful program to create a + small realtime clock that will continue to display during your + BASIC programming. See also De Re Atari for another realtime + clock application. + + + 21,22 15,16 BUFADR + + Indirect buffer address register (page zero). Temporary pointer + to the current disk buffer. + + + 23 17 ICCOMT + + Command for CIO vector. Stores the CIO command; used to find + the offset in the command table for the correct vector to the + handler routine. + + + 24,25 18,19 DSKFMS + + Disk file manager pointer. Called JMPTBL by DOS; used as + vector to FMS. + + + 26,27 1A,1B DSKUTL + + The disk utilities pointer. Called BUFADR by DOS, it points to + the area saved for a buffer for the utilities package (data buffer; + DBUF) or for the program area (MEMLO; 743, 744; $2E7, $2E8). + + + 28 1C PTIMOT + + Printer timeout, called every printer status request. Initialized to + 30, which represents 32 seconds (the value is 64 seconds per 60 + increments in this register); typical timeout for the Atari 825 + printer is five seconds. The value is set by your printer handler + software. It is updated after each printer status request operation. + It gets the specific timeout status from location 748 ($2EC), which + is loaded there by SIO. + + The new "B" type OS ROMs have apparently solved the problem + of timeout that haunted the "A" ROMs; you saw it when the + printer or the disk drive periodically went to sleep (timed out) for + a few seconds, causing severe anxiety attacks in the owners who + thought their Ataris had just mysteriously died. This is + compounded when one removes a disk from the drive, believing + the I/O process to be finished--only to have the drive start up + again after the timeout and trying to write to or read from a + nonexistent disk. Usually both the system and the user crash + simultaneously at this point. See the appendix for more + information on the new ROMs. + + + 29 1D PBPNT + + Print buffer pointer; points to the current position (byte) in the + print buffer. Ranges from zero to the value in location 30. + + + 30 1E PBUFSZ + + Print buffer size of printer record for current mode. Normal + buffer size and line size equals 40 bytes; double-width print + equals 20 bytes (most printers use their own control codes for + expanded print); sideways printing equals 29 bytes (Atari 820 + printer only). Printer status request equals four. PBUFSZ is + initialized to 40. The printer handler checks to see if the same + value is in PBPNT and, if so, sends the contents of the buffer to + the printer. + + + 31 1F PTEMP + + Temporary register used by the printer handler for the value of + the character being output to the printer. + + ---------------------------------------------------------------------- + + Locations 32 to 47 ($20 to $2F) are the ZIOCB: Page zero Input-Output + Control Block. They use the same structure as the IOCB's at locations + 832 to 959 ($340 to $3BF). The ZIOCB is used to communicate I/O con- + trol data between CIO and the device handlers. When a CIO opera- + tion is initiated, the information stored in the IOCB channel is moved + here for use by the CIO routines. When the operation is finished, the + updated information is returned to the user area. + + + 32 20 ICHIDZ + + Handler index number. Set by the OS as an index to the device + name table for the currently open file. If no file is open on this + IOCB (IOCB free), then this register is set to 255 ($FF). + + + 33 21 ICDNOZ + + Device number or drive number Called MAXDEV by DOS to in- + dicate the maximum number of devices. Initialized to one. + + + 34 22 ICCOMZ + + Command code byte set by the user to define how the rest of the + IOCB is formatted, and what I/O action is to be performed. + + + 35 23 ICSTAZ + + Status of the last IOCB action returned by the device, set by the + OS. May or may not be the same status returned by the STATUS + command. + + + 36,37 24,25 ICBALZ/HZ + + Buffer address for data transfer or the address of the file name for + commands such as OPEN, STATUS, etc. + + + 38,39 26,27 ICPTLZ/HZ + + Put byte routine address set by the OS. It is the address minus + one byte of the device's "put one byte" routine. It points to CIO's + "IOCB not OPEN" on a CLOSE statement. + + + 40,41 28,29 ICBLLZ/HZ + + Buffer length byte count used for PUT and GET operations; + decreased by one for each byte transferred. + + + 42 2A ICAX1Z + + Auxiliary information first byte used in OPEN to specify the type + of file access needed. + + + 43 2B ICAX2Z + + CIO working variables, also used by some serial port functions. + Auxiliary information second byte. + + + 44,45 2C,2D ICAX3Z/4Z + + Used by BASIC NOTE and POINT commands for the transfer of + disk sector numbers. These next four bytes to location 47 are also + labelled as: ICSPRZ and are defined as spare bytes for local CIO + use. + + + 46 2E ICAX5Z + + The byte being accessed within the sector noted in locations 44 + and 45. It is also used for the IOCB Number multiplied by 16. + Each IOCB block is 16 bytes long. Other sources indicate that the + 6502 X register also contains this information. + + + 47 2F ICAX6Z + + Spare byte. Also labelled CIOCHR, it is the temporary storage + for the character byte in the current PUT operation. + + ------------------------------------------------------------------- + + + 48 30 STATUS + + Internal status storage. The SIO routines in ROM use this byte to + store the status of the current SIO operation. See page 166 of the + OS User's Manual for status values. STATUS uses location 793 + ($319) as temporary storage. STATUS is also used as a storage + register for the timeout, BREAK abort and error values during + SIO routines. + + + 49 31 CHKSUM + + Data frame checksum used by SIO: single byte sum with carry to + the least significant bit. Checksum is the value of the number of + bytes transmitted (255; $FF). When the number of transmitted + bytes equals the checksum, a checksum sent flag is set at location + 59 ($3B). Uses locations 53773 ($D20D) and 56 ($38) for com- + parison of values (bytes transmitted). + + + 50,51 32,33 BUFRLO/HI + + Pointer to the data buffer, the contents of which are transmitted + during an I/O operation, used by SIO and the Device Control + Block (DCB); points to the byte to send or receive. Bytes are + transferred to the eight-bit parallel serial output holding register + or from the input holding register at 53773 ($D20D). This register + is a one-byte location used to hold the eight bits which will be + transmitted one bit at a time (serially) to or from the device. The + computer takes the eight bits for processing when the register is + full or replaces another byte in it when empty after a + transmission. + + + 52,53 34,35 BFENLO/HI + + Next byte past the end of the SIO and DCB data buffer described + above. + + + 54 36 CRETRY + + Number of command frame retries. Default is 13 ($0D). This is the + number of times a device will attempt to carry out a command + such as read a sector or format a disk. + + + 55 37 DRETRY + + Number of device retries. The default is one. + + + 56 38 BUFRFL + + Data buffer full flag (255; $FF equals full). + + + 57 39 RECVDN + + Receive done flag (255; $FF equals done). + + + 58 3A XMTDON + + Transmission done flag (255; $FF equals done). + + + 59 3B CHKSNT + + Checksum sent flag (255; $FF equals sent). + + + 60 3C NOCKSM + + Flag for "no checksum follows data." Not zero means no + checksum follows; zero equals checksum follows transmission + data. + + + 61 3D BPTR + + Cassette buffer pointer: record data index into the portion of data + being read or written. Ranges from zero to the current value at + location 650 ($28A). When these values are equal, the buffer at + 1021 ($3FD) is empty if reading or full if writing. Initialized to 128 + ($80). + + + 62 3E FTYPE + + Inter-record gap type between cassette records, copied from + location 43 ($2B; ICAX2Z) in the ZIOCB, stored there from + DAUX2 (779; $30B) by the user. Normal gaps are a non-zero + positive number; continuous gaps are zero (negative number). + + + 63 3F FEOF + + Cassette end of file flag. If the value is zero, an end of file (EOF) + has not been reached. Any other number means it has been + detected. An EOF record has been reached when the command + byte of a data record equals 254 ($FE). See location 1021 ($3FD). + + + 64 40 FREQ + + Beep count retain register. Counts the number of beeps required + by the cassette handler during the OPEN command for play or + record operations; one beep for play, two for record. + + + 65 41 SOUNDR + + Noisy I/O flag used by SIO to signal the beeping heard during + disk and cassette I/O. POKE here with zero for blessed silence + during these operations. Other numbers return the beep. In- + itialized to three. The hardware solution to this problem is to turn + your speaker volume down. This can also be used to silence the + digital track when playing synchronized voice/data tapes. See + location 54018. + + + 66 42 CRITIC + + Critical I/O region flag; defines the current operation as a time- + critical section when the value here is non-zero. Checked at the + NMI process after the stage one VBLANK has been processed. + POKEing any number other than zero here will disable the repeat + action of the keys and change the sound of the CTRL-2 buzzer. + + Zero is normal; setting CRITIC to a non-zero value suspends a + number of OS processes including system software timer coun- + ting (timers two, three, four and five; see locations 536 to 558; + $218 to $22E). It is suggested that you do not set CRITIC for any + length of time. When one timer is being set, CRITIC stops the + other timers to do so, causing a tiny amount of time to be "lost." + When CRITIC is zero, both stage one and stage two VBLANK + procedures will be executed. When non-zero, only the stage one + VBLANK will be processed. + + + 67-73 43-49 FMZSPG + + Disk file manager system (FMS) page zero registers (seven + bytes). + + + 67,68 43,44 ZBUFP + + Page zero buffer pointer to the user filename for disk I/O. + + + 69,70 45,46 ZDRVA + + Page zero drive pointer. Copied to here from DBUFAL and + DBUFAH; 4905 and 4913 ($1329, $1331). Also used in FMS "free + sector," setup and "get sector" routines. + + + 71,72 47,48 ZSBA + + Zero page sector buffer pointer. + + + 73 49 ERRNO + + Disk I/O error number. Initialized to 159 ($9F) by FMS. + + + 74 4A CKEY + + Cassette boot request flag on coldstart. Checks to see if the + START key is pressed and, if so, CKEY is set. Autoboot cassettes + are loaded by pressing the START console key while turning the + power on. In response to the beep, press the PLAY button on the + recorder. + + + 75 4B CASSBT + + Cassette boot flag. The Atari attempts both a disk and a cassette + boot simultaneously. Zero here means no cassette boot was suc- + cessful. See location 9 + + + 76 4C DSTAT + + Display status and keyboard register used by the display handler. + Also used to indicate memory is too small for the screen mode, + cursor out of range error, and the BREAK abort status. + + + 77 4D ATRACT + + Attract mode timer and flag. Attract mode rotates colors on your + screen at low luminance levels when the computer is on but no + keyboard input is read for a long time (seven to nine minutes). + This helps to save your TV screen from "burn-out" damage suf- + fered from being left on and not used. It is set to zero by IRQ + whenever a key is pressed, otherwise incremented every four + seconds by VBLANK (see locations 18 - 20; $12 - $14). When the + value in ATRACT reaches 127 ($7F), it is then set to 254 ($FE) un- + til attract mode is terminated. This sets the flag to reduce the + luminance and rotate the colors when the Atari is sitting idle. + POKE with 128 ($80) to see this effect immediately: it normally + takes seven to nine minutes to enable the attract mode. The OS + cannot "attract" color generated by DLI's, although your DLI + routine can, at a loss of time. + + Joysticks alone will not reset location 77 to zero. You will have to + add a POKE 77,0 to your program periodically or frequently call + in a subroutine to prevent the Atari from entering attract mode if + you are not using any keyboard input. + + + 78 4E DRKMSK + + Dark attract mask; set to 254 ($FE) for normal brightness when + the attract mode is inactive (see location 77). Set to 246 ($F6) + when the attract mode is active to guarantee screen color + luminance will not exceed 50% . Initialized to 254 ($FE). + + + 79 4F COLRSH + + Color shift mask; attract color shifter; the color registers are + EORd with locations 78 and 79 at the stage two VBLANK (see + locations 18 - 20; $12 - $14). When set to zero and location 78 + equals 246, color luminance is reduced 50%. COLRSH contains + the current value of location 19, therefore is given a new color + value every 4.27 seconds. + + Bytes 80 to 122 ($50 to $7A) are used by the screen editor and display + handler. + + + 80 50 TEMP + + Temporary register used by the display handler in moving data to + and from screen. Also called TMPCHR. + + + 81 51 HOLD1 + + Same as location 80. It is used also to hold the number of Display + List entries. + + + 82 52 LMARGN + + Column of the left margin of text (GR.0 or text window only). + Zero is the value for the left edge of the screen; LMARGN is + initialized to two. You can POKE the margin locations to set them + to your specific program needs, such as POKE 82,10 to make the + left margin start ten locations from the edge of the screen. + + + 83 53 RMARGN + + Right margin of the text screen initialized to 39 ($27). Both + locations 82 and 83 are user-alterable, but ignored in all + GRAPHICS modes except zero and the text window. + Margins work with the text window and blackboard mode and are + reset to their default values by pressing RESET. Margins have no + effect on scrolling or the printer. However, DELETE LINE and + INSERT LINE keys delete or insert 40 character lines (or delete + one program line), which always start at the left margin and wrap + around the screen edge back to the left margin again. The right + margin is ignored in the process. Also, logical lines are always + three physical lines no matter how long or short you make those + lines. + The beep you hear when you are coming to the end of the logical + line works by screen position independent of the margins. Try + setting your left margin at 25 (POKE 82,25) and typing a few lines + of characters. Although you have just a few characters beyond + 60, the buzzer will still sound on the third line of text. + + + 84 54 ROWCRS + + Current graphics or text screen cursor row, value ranging from + zero to 191 ($BF) depending on the current GRAPHICS mode + (maximum number of rows, minus one). This location, together + with location 85 below, defines the cursor location for the next + element to be read/written to the screen. Rows run horizontally, + left to right across the TV screen. Row zero is the topmost line; + row 192 is the maximum value for the bottom-most line. + + + 85,86 55,56 COLCRS + + Current graphics or text mode cursor column; values range from + zero to 319 (high byte, for screen mode eight) depending on + current GRAPHICS mode (maximum numher of columns minus + one). Location 86 will always be zero in modes zero through + seven. Home position is 0,0 (upper left-hand corner). Columns + run vertically from the top to the bottom down the TV screen, the + leftmost column being number zero, the rightmost column the + maximum value in that mode. The cursor has a complete top to + bottom, left to right wraparound on the screen. + + ROWCRS and COLCRS define the cursor location for the next + element to be read from or written to in the main screen segment + of the display. For the text window cursor, values in locations 656 + to 667 ($290 to $29B) are exchanged with the current values in + locations 84 to 95 ($54 to $5F), and location 123 ($7B) is set to 255 + ($FF) to indicate the swap has taken place. ROWCRS and + COLCRS are also used in the DRAW and FILL functions to + contain the values of the endpoint of the line being drawn. The + color of the line is kept in location 763 ($2FB). These values are + loaded into locations 96 to 98 ($60 to $62) so that ROWCRS and + COLCRS may be altered during the operation. + + BASIC's LOCATE statement not only examines the screen, but + also moves the cursor one position to the right at the next PRINT + or PUT statement. It does this by updating locations 84 and 85, + above. You can override the cursor advance by saving the + contents of the screen before the LOCATE command, then + restoring them after the LOCATE. Try: + + 100 REM: THE SCREEN MUST HAVE BEEN 0 + PENED FOR READ OR READ/WRITE PREV + IOUSLY + 110 LOOK = PEEK(84): SEE = PEEK(85) + 120 LOCATE X,Y,THIS + 130 POKE 84, LOOK: POKE 65, SEE + + Note that CHR$(253) is a non-printing character---the bell-- + and doesn't affect the cursor position. + + See COMPUTE!, August 198l, for an example of using COLCRS + for dynamic data restore and updating with the screen editor and + the IOCBs. + + + 87 57 DINDEX + + Display mode/current screen mode. Labelled CRMODE by (*M). + DINDEX contains the number obtained from the low order four + bits of most recent open AUX1 byte. It can be used to fool the OS + into thinking you are in a different GRAPHICS mode by + POKEing DINDEX with a number from zero to 11. POKE with + seven after you have entered GRAPHICS mode eight, and it will + give you a split screen with mode seven on top and mode eight + below. However, in order to use both halves of the screen, you + will have to modify location 89 (below) to point to the area of the + screen you wish to DRAW in. (See Your Atan 400/800, pp. 280 - + 283.) + Watch for the cursor out-of-range errors (number 141) when + changing GRAPHICS modes in this manner and either PRINTing + or DRAWing to the new mode screen. POKE 87 with the BASIC + mode number, not the ANTIC mode number. + Did you know you can use PLOT and DRAWTO in GR.0? Try + this: + + 10 GR.0 + 20 PLOT 0,0: DRAWTO 10,10: DRAWTO 0 + ,10 + 30 DRAWTO 39,0: DRAWTO 20,23: DRAWT + O 0,20 + 40 GOTO 40 + + You can also set the text window for PRINT and PLOT modes by + POKEing 87 with the graphics mode for the window. Then you + must POKE the address of the top left corner of the text window + into 88 and 89 ($58, $59). The screen mode of the text window is + stored at location 659 ($293). + + You may have already discovered that you cannot call up the + GTIA modes from a direct command. Like the + 16 GRAPHICS + modes, they can only be called up during a program, and the + screen display will be reset to GR.0 on the first INPUT or PRINT + (not PRINT#6) statement executed in these modes. + + Since this location only takes BASIC modes, you can't POKE it + with the other ANTIC modes such as "E", the famous "seven-and- + a-half" mode which offers higher resolution than seven and a four + color display (used in Datasoft's Micropainter program). If you're + not drawing to the screen, simply using it for display purposes, + you can always go into the Display List and change the + instructions there. But if you try to draw to the screen, you risk an + out-of-bounds error (error number 141). + + See Creative Computing, March 1982, for an excellent look at + mode 7.5. The short subroutine below can be used to change the + Display List to GR.7.5: + + 1000 GRAPHICS 8+16: DLIST = PEEK(560) + ) + PEEK(561) * 256:POKE DLIST + + 3,78 + 1010 FOR CHANGE = DLIST + 6 TO DLIST + + 204: IF PEEK(CHANGE) = 15 THE + N POKE CHANGE,14 + 1020 IF PEEK (CHANGE) = 79 THEN POKE + CHANGE,78: NEXT CHANGE + 1030 POKE 87,7:RETURN + + DOWNLOAD MODE75.BAS + + (Actually, 15 ($F) is the DL number for the maximum memory + mode; it also indicates modes eight through eleven. The DL's for + these modes are identical.) Fourteen is the ANTIC E mode; + GR.7.5 This program merely changes GR.8 to mode E in the + Display List. The value 79 is 64 + 15; mode eight screen with BIT + 6 set for a Load Memory Scan (LMS) instruction (see the DL + information in locations 560, 561; $230, $231). It does not check + for other DL bits. + + You can also POKE 87 with the GTIA values (nine to eleven). To + get a pseudo-text window in GTIA modes, POKE the mode + number here and then POKE 623 with 64 for mode nine, 128 for + mode ten, and 192 for mode eleven, then POKE 703 with four, in + program mode. (In command mode, you will be returned to + GR.0.) You won't be able to read the text in the window, but you + will be able to write to it. However, to get a true text window, + you'll need to use a Display List Interrupt (see COMPUTE!, + September 1982). If you don't have the GTIA chip, it is still + possible to simulate those GRAPHICS modes by using DINDEX + with changes to the Display List Interrupt. See COMPUTE!, July + 1981, for an example of simulating GR.10. + + + 88,89 58,59 SAVMSC + + The lowest address of the screen memory, corresponding to the + upper left corner of the screen (where the value at this address + will be displayed). The upper left corner of the text window is + stored at locations 660, 661 ($294, $295). + You can verify this for yourself by: + + WINDOW = PEEK(88) + PEEK(89) * 256: POKE WINDOW,33 + + This will put the letter "A" in the upper left corner in GR.0, 1 and + 2. In other GRAPHICS modes, it will print a colored block or + bar. To see this effect, try: + + 5 REM FIRST CLEAR SCREEN + 10 GRAPHICS Z: IF Z > 59 THEN END + 15 SCREEN = PEEK (88) + PEEK (89) * + 256 + 20 FOR N = 0 TO 255: POKE SCREEN + N + ,N + 25 NEXT N: FOR N = 1 TO 300: NEXT N: + Z = Z + 1 + 30 GOTO 10 + + DOWNLOAD SAVEMSC1.BAS + + You will notice that you get the Atari internal character code, not + the ATASCII code. See also locations 560, 561 ($230, $231) and + 57344 ($E000). + + How do you find the entire screen RAM? First, look at the chart + below and find your GRAPHICS mode. Then you multiply the + number of rows-per-screen type by the number of bytes-per-line. + This will tell you how many bytes each screen uses. Add this + value, minus one, to the address specified by SAVMSC. + However, if you subtract MEMTOP (locations 741, 742; $2E5, + $2E6) from RAMTOP (106; $6A * 256 for the number of bytes), + you will see that there is more memory reserved than just the + screen area. The extra is taken up by the display list or the text + window, or is simply not used (see the second chart below). + + Mode 0 1 2 3 4 5 6 7 8 9-12 + + Rows + Full 24 24 12 24 48 48 96 96 192 192 + Split -- 20 10 20 40 40 80 80 160 -- + + Bytes per + Line 40 20 20 10 10 20 20 40 40 40 + + Columns + per Line 40 20 20 40 80 80 160 160 320 80 + + Memory (1) 993 513 261 273 537 1017 2025 3945 7900 7900 + + Memory (2) + Full 992 672 420 432 696 1176 2184 4200 8138 8138 + Split -- 674 424 434 694 1174 2174 4190 8112 -- + + (1) According to the Atari BASIC Reference Manual, p.45; OS + User's Manual, p.172, and Your Atari 400/800, p.360. + + (2) According to Your Atari 400/800, p.274, and Atari Microsoft + Basic Manual, p.69. This is also the value you get when you + subtract MEMTOP from RAMTOP (see above). + + For example, to POKE the entire screen RAM in GR.4, you + would find the start address of the screen (PEEK(88) + PEEK(89) + * 256), then use a FOR-NEXT loop to POKE all the locations + specified above: + + 10 GRAPHICS 4: SCRN = PEEK(88) + PE + EK(89) * 256 + 20 FOR LOOP = SCRN to SCRN + 479: R + EM 48 ROWS * 10 BYTES - 1 + 30 POKE LOOP,35: NEXT LOOP + + DOWNLOAD SAVEMSC2.BAS + + Why the minus one in the calculation? The first byte of the screen + is the first byte in the loop. If we add the total size, we will go one + byte past the end of the soreen, so we subtract one from the total. + Here's how to arrive at the value for the total amount ot memory + located for screen use, display list and Text window: + + Total memory allocation for the screen + + Screen display Display List + ----------------------------------------------------------- + Text unused bytes screen unused used + GR window always cond. use bytes bytes Total + ----------------------------------------------------------- + 0 ... none none 960 none 32 992 + 1 160 none 80 400 none 34 674 + 2 160 none 40 200 none 24 424 + 3 160 none 40 200 none 34 434 + 4 160 none 80 400 none 54 694 + 5 160 none 160 800 none 54 1174 + 6 160 none 320 1600 none 94 2174 + 7 160 none 640 3200 96 94 4190 + 8 160 16 1280 6400 80 176 8112 + + The number of bytes from RAMTOP (location 106; $6A) is counted + from the left text window column towards the total column. + MEMTOP (741, 742; $2E5, $2E6) points to one byte below + RAMTOP * 256 minus the number of bytes in the total column. If + 16 is added to the GRAPHICS mode (no text window), then the + conditional unused bytes are added to the total. Then the bytes + normally added for the text window become unused, and the + Display List expands slightly. (See COMPUTE!, September 1981.) + + When you normally PRINT CHR$(125) (clear screen), Atari sends + zeroes to the memory starting at locations 88 and 89. It continues to + do this until it reaches one byte less than the contents of RAMTQP + (location 106; $6A). Here is a potential source of conflict with your + program, however: CHR$(125)--CLEAR SCREEN--and any + GRAPHICS command actually continue to clear the first 64 ($40) + bytes above RAMTOP! + + It would have no effect on BASIC since BASIC is a ROM + cartridge. The OS Source Listing seems to indicate that it ends at + RAMTOP, but Atari assumed that there would be nothing after + RAMTOP, so no checks were provided. Don't reserve any data + within 64 bytes of RAMTOP or else it will be eaten by the CLEAR + SCREEN routine, or avoid using a CLEAR SCREEN or a + GRAPHICS command. Scrolling the text window also clears 800 + bytes of memory above RAMTOP. + + You can use this to clear other areas of memory by POKEing the + LSB and MSB of the area to be cleared into these locations. Your + routine should always end on a $FF boundary (RAMTOP indicates + the number of pages). Remember to POKE back the proper screen + locations or use a GRAPHICS command immediately after doing + so to set the screen right. Try this: + + 10 BOTTOM = 30000: TOP = 36863: REM + LOWEST AND HIGHEST ADDRESS TO CLEA + R = $7530 & $8FFF + 20 RAMTOP = PEEK(106): POKE 106, INT + (TOP + 1 / 256) + 30 TEST = INT(BOTTOM / 256): POKE89, + TEST + 40 POKE 88. BOTTOM - 256 * TEST + 50 PRINT CHR$(125): POKE 106, RAMTOP + 60 GRAPHICS 0 + + DOWNLOAD SAVEMSC3.BAS + + This will clear the specified memory area and update the address + of screen memory. If you don't specify TOP, the CLEAR SCREEN + will continue merrily cleaning out memory and, most likely, will + cause your program to crash. Use it with caution. + Here's a means to SAVE your current GR.7 screen display to disk + using BASIC: + + 1000 SCREEN = PEEK(88) + PEEK(89) * + 256 + 1010 OPEN #2,8,0,"D:picturename" + 1020 MODE = PEEK(87): PUT #2, MODE: + REM SAVE GR. MODE + 1030 FOR SCN = 0 TO 4: COL PEEK(70 + 8 + SCN): PUT #2,COL: NEXT SCN: + REM SAVE COLOR REGISTERS + 1040 FOR TV = SCREEN TO SCREEN + 319 + 9:BYTE = PEEK(TV): PUT #2, BYTE: + NEXT TV: CLOSE #2 + + DOWNLOAD SAVEMSC4.BAS + + To use this with other screen modes, you will have to change the + value of 3199 in line 1040 to suit your screen RAM (see the chart + above). For example, GR.7 + 16 would require 3839 bytes (3840 + minus one). You can use the same routine with cassette by using + device C:. To retrieve your picture, you use GET#2 and POKE + commands. You will, however, find both routines very slow. Using + THE CIO routine at 58454 ($E456) and the IOCBs, try this machine + language save routine: + + 10 DIM ML$(10): B$(10): GR.8+16 + 20 B$ = "your picture name":Q = PEEK + (559) + 30 FOR N = 1 TO 6: READ BYTE: ML$(N, + N) = CHR$(BYTE): NEXT N + 35 DATA 104,162,16,76,86,228 + 36 REM PLA,LDX,$10,JMP $E456 + 40 OPEN #1,4,0,B$ + 50 POKE 849,1: POKE 850,7: POKE 852, + PEEK(88): POKE 853,PEEK(89): POKE + 856,70: POKE 857,30: POKE 858,4 + 55 REM THESE POKES SET UP THE IOCB + 60 POKE 559,0: REM TURN OFF THE SCRE + EN TO SPEED THINGS UP + 70 X = USR(ADR(ML$)): CLOSE #1 + 80 POKE 559,Q: REM TURN IT BACK ON A + GAIN + + DOWNLOAD SAVEMSC5.BAS + + Note that there is no provision to SAVE the color registers in this + program, so I suggest you have them SAVEd after you have + SAVEd the picture. It will make it easier to retrieve them if they are + at the end of the file. You will have to make suitable adjustments + when SAVEing a picture in other than GR.8 + 16 -- such as + changing the total amount of screen memory to be SAVEd, POKEd + into 856 and 857. Also, you will need a line such as 1000 GOTO + 1000 to keep a GTIA or + 16 mode screen intact. See the Atari + column in InfoAge Magazine, July 1982, for more on this idea. See + location 54277 ($D405) for some ideas on scrolling the screen + RAM. + + ------------------------------------------------------------------------ + A SHORT DIGRESSION + There are two techniques used in this hook for calling a machine + language program from BASIC with the USR command. One method + is to POKE the values into a specific address -- say, page six -- and + use the starting address for the USR call, such as X = USR(1536). For + an example of this technique, see location 632 ($278). + + The other technique, used above, is to make a string (ML$) out of the + routine by assigning to the elements of the string the decimal + equivalents of the machine language code by using a FOR-NEXT and + READ-DATA loop. To call this routine, you would use X = + USR(ADR(ML$)). This tells the Atari to call the machine language + routine located at the address where ML$ is stored. This address will + change with program size and memory use. The string method won't + be overwritten by another routine or data since it floats around safely + in memory. The address of the string itself is stored by the string/array + table at location 140 ($8C). + ------------------------------------------------------------------------ + + + 90 5A OLDROW + + Previous graphics cursor row. Updated from location 84 ($54) + before every operation. Used to determine the starting row for + the DRAWTO and XIO 18 (FILL command). + + + 91,92 5B,5C OLDCOL + + Previous graphics cursor column. Updated from locations 85 and + 86 ($55, $56) before every operation. These locations are used by + the DRAWTO and XIO 18 (FILL) commands to determine the + starting column of the DRAW or FILL + + + 93 5D OLDCHR + + Retains the value of the character under the cursor used to + restore that character when the cursor moves + + + 94,95 5E,5F OLDADR + + Retains the memory location of the current cursor location. Used + with location 93 (above) to restore the character under the cursor + when the cursor moves + + + 96 60 NEWROW + + Point (row) to which DRAWTO and XIO 18 (FILL) will go. + + + 97,98 61,62 NEWCOL + + Point (column) to which DRAWTO and XIO 18 (FILL) will go. + NEWROW and NEWCOL are initialized to the values in + ROWCRS and COLCRS (84 to 86; $54 to $56) above, which + represent the destination end point of the DRAW and FILL + functions. This is done so that ROWCRS and COLCRS can be + altered during these routines. + + + 99 63 LOGCOL + + Position of the cursor at the column in a logical line. A logical + line can contain up to three physical lines, so LOGCOL can + range between zero and 119. Used by the display handler. + + + 100,101 64,65 ADRESS + + Temporary storage used by the display handler for the Display + List address, line buffer (583 to 622; $247 to $26E), new MEMTOP + value after DL entry, row column address, DMASK value, data to + the right of cursor, scroll, delete, the clear screen routine and for + the screen address memory (locations 88, 89; $58, $59). + + + 102,103 66,67 MLTTMP + + Also called OPNTMP and TOADR; first byte used in OPEN as + temporary storage. Also used by the display handler as + temporary storage. + + + 104,105 68,69 SAVADR + + Also called FRMADR. Temporary storage, used with ADRESS + above for the data under the cursor and in moving line data on + the screen. + + + 106 6A RAMTOP + + RAM size, defined by powerup as passed from TRAMSZ (location + 6), given in the total number of available pages (one page equals + 256 bytes, so PEEK(106) * 256 will tell you where the Atari thinks + the last usable address --byte-- of RAM is). MEMIOP (741, + 742; $2E5. $2E6) may not extend below this value. In a 48K Atari, + RAMTOP is initialized to 160 ($A0), which points to location + 40960 ($A000). The user's highest address will be one byte less + than this value. + + This is initially the same value as in location 740. PEEK(740) / 4 or + PEEK(106) / 4 gives the number of 1K blocks. You can fool the + computer into thinking you have less memory than you actually + have, thus reserving a relatively safe area for data (for your new + character set or player/missile characters, for example) or + machine language subroutines by: + + POKE(106), PEEK(106) - # of pages you want to reserve. + + The value here is the number of memory pages (256-byte blocks) + present. This is useful to know when changing GR.7 and GR.8 + screen RAM. If you are reserving memory for PM graphics, + POKE 54279, PEEK(106) - # of pages you are reserving before + you actually POKE 106 with that value. To test to see if you have + exceeded your memory by reserving too much memory space, + you can use: + + 10 SIZE = (PEEK(106) - # of pages) + * 256 + 20 IF SIZE < = PEEK(144) + PEEK(145 + ) * 256 THEN PRINT "TOO MUCH MEMOR + Y USED" + + If you move RAMTOP to reserve memory, always issue a + GRAPHICS command (even issuing one to the same GRAPHICS + mode you are in will work) immediately so that the display list + and data are moved beneath the new RAMTOP. + + You should note that a GRAPHICS command and a CLEAR + command (or PRINT CHR$(125)) actually clear the first 64 bytes + above RAMTOP (see location 88; $58 for further discussion). + Scrolling the text window of a GRAPHICS mode clears up to 800 + ($320) bytes above RAMTOP (the text window scroll actually + scrolls an entire GR.0 screen-worth of data, so the unseen 20 + lines * 40 bytes equals 800 bytes). PM graphics may be safe + (unless you scroll the text window) since the first 384 or 768 bytes + (double or single line resolution, respectively) are unused. + However, you should take both of these effects into account when + writing your programs. + To discover the exact end of memory, use this routine (it's a tad + slow): + + 10 RAMTOP = 106: TOP = PEEK(RAMTOP) + 20 BYTE = TOP * 256: TEST = 255 - PE + EK(BYTE): POKE BYTE,TEST + 30 IF PEEK(BYTE) = TEST THEN TOP = T + OP +1: POKE BYTE, 255 - TEST + 40 GOTO 20 + 50 PRINT "MEMORY ENDS AT "; BYTE + + One caution: BASIC cannot always handle setting up a display + list and display memory for GRAPHICS 7 and GRAPHICS 8 + when you modify this location by less than 4K (16 pages; 4096 + bytes). Some bizarre results may occur if you use PEEK(106) - 8 + in these modes, for example. Use a minimum of 4K (PEEK(106) - + 16) to avoid trouble. This may explain why some people have + difficulties with player/missile graphics in the hi-res (high + resolution; GR.7 and GR.8) modes. See location 54279 ($D407). + + Another alternative to reserving memory in high RAM is to save + an area below MEMLO, location 743 ($2E7: below your BASIC + program). See also MEMTOP, locations 741, 742 ($2E5, $2E6). + + + 107 6B BUFCNT + + Buffer count: the screen editor current logical line size counter. + + + 108,109 6C,6D BUFSTR + + Editor low byte (AM). Display editor GETCH routine pointer + (location 62867 for entry; $F593). Temporary storage; returns the + character pointed to by BUFCNT above. + + + 110 6E BITMSK + + Bit mask used in bit mapping routines by the OS display handler + at locations 64235 to 64305 ($FAEB to $FB31). Also used as a + display handler temporary storage register. + + + 111 6F SHFAMT + + Pixel justification: the amount to shift the right justified pixel data + on output or the amount to shift the input data to right justify it. + Prior to the justification process, this value is always the same as + that in 672 ($2A0). + + + 112,113 70,71 ROWAC + + ROWAC and COLAC (below) are both working accumulators for + the control of row and column point plotting and the increment + and decrement functions. + + + 114,115 72,73 COLAC + + Controls column point plotting. + + + 116,117 74,75 ENDPT + + End point of the line to be drawn. Contains the larger value of + either DELTAR or DELTAC (locations 118 and 119, below) to be + used in conjunction with ROWAC/COLAC (locations 112 and + 114, above) to control the plotting of line points. + + + 118 76 DELTAR + + Delta row; contains the absolute value of NEWBOW (location 96; + $60) minus ROWCRS (location 84; $54). + + + 119,120 77,78 DELTAC + + Delta column; contains the absolute value of NEWCOL (location + 97; $61) minus the value in COLCRS (location 85; $55). These + delta register values, along with locations 121 and 122 below, are + used to define the slope of the line to be drawn. + + + 121 79 ROWINC + + The row increment or decrement value (plus or minus one). + + + 122 7A COLINC + + The column increment or decrement value (plus or minus one). + ROWINC and COLINC control the direction of the line drawing + routine. The values represent the signs derived from the value in + NEWROW (location 96; $60) minus the value in ROWCRS + (location 84; $54) and the value in NEWCOL (locations 97, 98; + $61, $62) minus the value in COLCRS (locations 85, 86; $55, + $56). + + + 123 7B SWPFLG + + Split-screen cursor control. Equal to 255 ($FF) if the text window + RAM and regular RAM are swapped; otherwise, it is equal to + zero. In split-screen modes, the graphics cursor data and the text + window data are frequently swapped in order to get the values + associated with the area being accessed into the OS data base + locations 84 to 95 ($54 to $5F). SWPFLG helps to keep track of + which data set is in these locations. + + + 124 7C HOLDCH + + A character value is moved here before the control and shift logic + are processed for it. + + + 125 7D INSDAT + + Temporary storage byte used by the display handler for the + character under the cursor and end of line detection. + + + 126,127 7E,7F COUNTR + + Starts out containing the larger value of either DELTAR (location + 118; $76) or DELTAC (location 119; $77). This is the number of + iterations required to draw a line. As each point on a line is + drawn, this value is decremented. When the byte equals zero, the + line is complete (drawn). + + --------------------------------------------------------------------- + + User and/or BASIC page zero RAM begins here. Locations 128 to 145 + ($80 to $91) are for BASIC program pointers; 146 to 202 ($92 to $CA) + are for miscellaneous BASIC RAM; 203 to 209 ($CB to $D1) are + unused by BASIC, and 210 to 255 ($D2 to $FF) are the floating point + routine work area. The Assembler Editor cartridge uses locations 128 + to 176 ($80 to $B0) for its page zero RAM. Since the OS doesn't use this + area, you are free to use it in any non-BASIC or non-cartridge + environment. If you are using another language such as FORTH, + check that program's memory map to see if any conflict will occur. + See COMPUTE!'s First Book of Atari, pages 26 to 53, for a discussion + of Atari BASIC structure, especially that using locations 130 to 137 + ($82 to $89). Included in the tutorials are a memory analysis, a line + dump, and a renumber utility. See also De Re Atari, BYTE, February + 1982, and the locations for the BASIC ROM 40960 to 49151 ($A000 to + $BFFF). + + + 128,129 80,81 LOMEM + + Pointer to BASIC's low memory (at the high end of OS RAM + space). The first 256 bytes of the memory pointed to are the token + output buffer, which is used by BASIC to convert BASIC + statements into numeric representation (tokens; see locations + 136, 137; $88, $89). This value is loaded from MEMLO (locations + 743, 744; $2E7, $2E8) on initialization or the execution of a NEW + command (not on RESET!). Remember to update this value when + changing MEMLO to reserve space for drivers or buffers. + When a BASIC SAVE is made, two blocks of information are + written: the first block is the seven pointers from LOMEM to + STARP (128 to 141; $80 to $8D). The value of LOMEM is + subtracted from each of these two-byte pointers in the process, so + the first two bytes written will both be zero. The second block + contains the following: the variable name table, the variable + value table, the tokenized program, and the immediate mode + line. + When a BASIC LOAD is made, BASIC adds the value at MEMLO + (743, 744; $2E7, $2E8) to each of the two-byte pointers SAVEd as + above. The pointers are placed back in page zero, and the values + of RUNSTK (142, 143; $8E, $8F) and MEMTOP (144, 145; $90, + $91) are set to the value in STARP. Then 256 bytes are reserved + above the value in MEMLO for the token output buffer, and the + program is read in immediately following this buffer. + When you don't have DOS or any other application program + using low memory loaded, LOMEM points to 1792 ($700). When + DOS 2.0 is present, it points to 7420 ($1CFC). When you change + your drive and data buffer defaults (see 1801, 1802; $709, $70A), + you will raise or lower this figure by 128 bytes for each buffer + added or deleted, respectively. When you boot up the RS-232 + handler, add another 1728 ($6C0) bytes used. + LOMEM is also called ARGOPS by BASIC when used in + expression evaluation. When BASIC encounters any kind of + expression, it puts the immediate results into a stack. ARGOPS + points to the same 256 byte area; for this operation it is reserved + for both the argument and operator stack. It is also called + OUTBUFF for another operation, pointing to the same 256 byte + buffer as ARGOPS points to. Used by BASIC when checking a + line for syntax and converting it to tokens. This buffer + temporarily stores the tokens before moving them to the + program. + + + 130,131 82,83 VNTP + + Beginning address of the variable name table. Variable names + are stored in the order input into your program, in ATASCII + format. You can have up to 128 variable names. These are stored + as tokens representing the variable number in the tokenized + BASIC program, numbered from 128 to 255 ($80 to $FF). + + The table continues to store variable names, even those no longer + used in your program and those used in direct mode entry. It is + not cleared by SAVEing your program. LOADing a new program + replaces the current VNT with the one it retrieves from the file. + You must LIST the program to tape or disk to save your program + without these unwanted variables from the table. LIST does not + SAVE the variable name or variable value tables with your + program. It stores the program in ATASCII, not tokenized form, + and requires an ENTER command to retrieve it. You would use a + NEW statement to clear the VNT in memory once you have + LISTed your program. + + Each variable name is stored in the order it was entered, not the + ATASCII order. With numeric (scalar) variables, the MSB is set + on the last character in a name. With string variables, the last + character is a "$" with the MSB (BIT 7) set. With array variables, + the last character is a "(" with the MSB set. Setting the MSB turns + the character into its inverse representation so it can be easily + recognized. + You can use variable names for GOSUB and GOTO routines, + such as: + + 10 CALCULATE = 1000 + . + . + 100 GOSUB CALCULATE + + This can save a lot of bytes for a frequently called routine. But + remember, each variable used for a GOSUB or GOTO address + uses one of the 128 possible variable names. A disadvantage of + using variable names for GOTO and GOSUB references is when + you try to use a line renumbering program. Line renumbering + programs will not change references to lines with variable + names, only to lines with numbered references. + + Here's a small routine you can add to the start of your BASIC + program (or the end if you change the line numbers) to print out + the variable names used in your program. You call it up with a + GOTO statement in direct mode: + + 1 POKE 1664, PEEK(130): POKE 1665, + PEEK (131) + 2 IF PEEK(1664) = PEEK(132) THEN IF + PEEK(1665) = PEEK(133) THEN STOP + 3 PRINT CHR$(PEEK(PEEK(1664) + PEEK + (1665) * 256))); + 4 IF PEEK(PEEK(1664) + PEEK(1665) * + 256)) > 127 THEN PRINT""; + 5 IF PEEK(1664) = 255 THEN POKE 166 + 4, 0: POKE 1665, PEEK(1665) + 1: GO + TO 2 + 6 POKE 1664, PEEK(1664) + 1: GOTO 2 + + DOWNLOAD VNTP.BAS + + See COMPUTE!, October 1981. + + + 132,133 84,85 VNTD + + Pointer to the ending address of the variable name table plus one + byte. When fewer than 128 variables are present, it points to a + dummy zero byte. When 128 variables are present, this points to + the last byte of the last variable name, plus one. + + It is often useful to be able to list your program variables; using + locations 130 to 133, you can do that by: + + 10 VARI = PEEK(130) + PEEK(131) * 2 + 56 :REM This gives you the start o + f the table. + 20 FOR VARI = VARI TO PEEK(132) + P + EEK(133) * 256 - 1: PRINT CHR$(PEE + K(VARI) - 128 * PEEK(VARI > 127)); + CHR$(27 + 128 * PEEK(VARI) > 127) + );:NEXT VARI + 25 REM this finds the end of the va + ri able name table (remember table + is end + 1). then PRINTs ASCII cha + racters < 128 + 30 NUM = 0: FOR VARI = PEEK(130) + + PEEK(313) * 256 TO PEEK(132) + PEE + K(131) * 256 - 1:NUM = NUM + (PEEK + (VARI) < 127):NEXT VARI: PRINT NU + M; "Variables in use" + + DOWNLOAD VNTD1.BAS + + Or try this, for a possibly less opaque example of the same + routine: + + 1000 NUM = 0: FOR LOOP = PEEK (130) + + PEEK(131) * 256 TO PEEK(132) + + PEEK(133) * 256 - 1 + 1010 IF PEEK(LOOP) < 128 THEN PRINT + CHR$(PEEK(LOOP));: GOTO 1030 + 1020 PRINT CHR$(PEEK(LOOP) - 128): N + UM - NUM + 1 + 1030 NEXT LOOP: PRINT; PRINT NUM; " + VARIABLES IN USE": END + + DOWNLOAD VNTD2.BAS + + + 134,135 86,87 VVTP + + Address for the variable value table. Eight bytes are allocated for + each variable in the name table as follows: + + Byte 1 2 3 4 5 6 7 8 + Variable + -------------------------------------------------------------- + Scalar 00 var # six byte BCD constant + Array;DIMed 65 var # offset first second + unDIMed 64 from DIM + 1 DIM + 1 + STARP + String;DIMed 129 var # offset length DIM + unDIMed 128 from + STARP + + In scalar (undimensioned numeric) variables, bytes three to eight + are the FP number; byte three is the exponent; byte four contains + the least significant two decimal digits, and byte eight contains + the most significant two decimal digits. + In array variables, bytes five and six contain the size plus one of + the first dimension of the array (DIM + 1; LSB/MSB), and bytes + seven and eight contain the size plus one of the second dimension + (the second DIM + 1; LSB/MSB). + In string variables, bytes five and six contain the current length + of the variable (LSB MSB), and bytes seven and eight contain the + actual dimension (up to 32767). There is an undocumented + BASIC statement, "COM," mentioned only in the BASIC + Reference Manual's index, which executes exactly the same as + the "DIM" statement (see Your Atari 400/800, p.346). Originally, + it was to be used to implement "common" variables. + + In all cases, the first byte is always one of the number listed on the + chart above (you will seldom, if ever, see the undimensioned + values in a program). This number defines what type of variable + information will follow. The next byte, var # (variable number), is + in the range from zero to 127. Offset is the number of bytes from + the beginning of STARP at locations 140 and 141 ($8C, $8D). + Since each variable is assigned eight bytes, you could find the + values for each variable by: + + 1000 VVTP = PEEK(134) + PEEK(135) * + 256: INPUT VAR: REM VARIABLE NUM + BER + 1010 FOR LOOP = 0 TO 7: PRINT PEEK(V + VTP + LOOP + 8 * VAR): NEXT LOOP + + where VAR is the variable number from zero to 127. + If you wish to assign the same value to every element in a DIMed + string variable use this simple technique: + + 10 DIM TEST$(100) + 20 TEST$ = "*": REM or use TEST$(1) + 30 TEST$(100) = TEST$ + 40 TEST$(2) = TEST$: PRINT TEST$ + + By assigning the first, last and second variables in the array in + that order, your Atari will then assign the same value to the rest of + the array. Make sure you make the second and last elements + equal to the string, not the character value (i.e don't use + TEXT$(2) = "*"). + See De Re Atari for an example of SAVEing the six-byte BCD + numbers to a disk file -- very useful when dealing with fixed + record lengths. + + + 136,137 88,89 STMTAB + + The address of the statement table (which is the beginning of the + user's BASIC program), containing all the tokenized lines of + code plus the immediate mode lines entered by the user. Line + numbers are stored as two-byte integers, and immediate mode + lines are given the default value of line 32768 ($8000). The first + two bytes of a tokenized line are the line number, and the next is + a dummy byte reserved for the byte count (or offset) from the start + of this line to the start of the next line. + + Following that is another count byte for the start of this line to the + start of the next statement. These count values are set only when + tokenization for the line and statement are complete. + Tokenization takes place in a 256 byte ($100) buffer that resides at + the end of the reserved OS RAM (pointed to by locations 128, + 129; $80, $81). + To see the starting address of your BASIC line numbers use this + routine: + + 10 STMTAB = PEEK(136) + PEEK(137)*2 + 56 + 20 NUM = PEEK(STMTAB) + PEEK (STMTAB + +1)*256 + 30 IF NUM = 32768 THEN END + 40 PRINT"LINE NUMBER: ";NUM;" ADDRE + SS: ";STMTAB + 50 STMTAB = STMTAB + PEEK(STMTAB+2) + 60 GOTO 20 + + The August 1982 issue of ANTIC provided a useful program to + delete a range of BASIC line numbers. The routine can be + appended to your program and even be used to delete itself. + + + 138,139 8A,8B STMCUR + + Current BASIC statement pointer, used to access the tokens + being currently processed within a line of the statement table. + When BASIC is awaiting input, this pointer is set to the + beginning of the immediate mode (line 32768). + + Using the address of the variable name table, the length, and the + current statement (locations 130 to 133, 138, 139), here is a way to + protect your programs from being LISTed or LOADed: they can + only be RUN! Remember, that restricts you too, so make sure you + have SAVEd an unchanqed version before you do this: + + 32000 FOR VARI = PEEK(130) + PEEK(1 + 31) * 256 TO PEEK(132) + PEEK(1 + 33) * 256:POKE VARI,155:NEXT VA + RI + 32100 POKE PEEK(138) + PEEK(139) * + 256 + 2,0: SAVE "D:filename": N + EW + + This will cause all variable names to be replaced with a RETURN + character. Other characters may be used: simply change 155 for + the appropriate ATASCII code for the character desired. Make + sure that these are the last two lines of your program and that + NEW is the last statement. CLOAD will not work, but a filename + with C: will. + + + 140,141 8C,8D STARP + + The address for the string and array table and a pointer to the end + of your BASIC program. Arrays are stored as six-byte binary + coded decimal numbers (BCD) while string characters use one + bye each. The address of the strings in the table are the same as + those returned by the BASIC ADR function. Always use this + function under program control, since the addresses in the table + change according to your program size. Try: + + 10 DIM A$(10),B$(10) + 20 A$ = "*": A$(10) = A$: A$(2) = A + $ + 30 B$ = "&": B$(10) = B$: B$(2) = B + $ + 40 PRINT ADR(A$), ADR(B$) + 50 PRINT PEEK(140) + PEEK(141) * 25 + 6: REM ADDRESS OF A$ + 60 PRINT PEEK(140) + PEEK(141) * 25 + 6 + 10: REM ADRESS OF A$ + 10 BYTE + S = ADDRESS OF B$ + + This table is expanded as each dimension is processed by + BASIC, reducing available memory. A ten-element numeric + array will require 60 bytes for storage. An array variable such as + DIM A(100) will cost the program 600 bytes (100 * six per + dimensioned number equals 600). On the other hand, a string + array such as DIM A$(100) will only cost 100 bytes! It would save + a lot of memory to write your arrays as strings and retrieve the + array values using the VAL statement. For example: + + 10 DIM A$(10): A$ = "1234567890" + 20 PRINT VAL(A$) + 30 PRINT VAL(A$(4,4)) + 40 PRINT VAL(A$(3,3))+VAL(A$(8,9)) + + See COMPUTE!, June 1982, for a discussion of STARP and + VVTP. See De Re Atari for a means to SAVE the string/array area + with your program. + + + 142,143 8E,8F RUNSTK + + Address of the runtime stack which holds the GOSUB entries + (four bytes each) and the FOR-NEXT entries (16 bytes each). The + POP command in BASIC affects this stack, pulling entries off it + one at a time for each POP executed. The stack expands and + contracts as necessary while the program is running. + + Each GOSUB entry consists of four bytes in this order: a zero to + indicate a GOSUB, a two-byte integer line number on which the + call occurred, and an offset into that line so the RETURN can + come back and execute the next statement. + + Each FOR-NEXT entry contains 16 bytes in this order: first, the + limit the counter variable can reach; second, the step or counter + increment. These two are allocated six bytes each in BCD format + (12 bytes total). The 13th byte is the counter variable number with + the MSB set; the 14th and 15th are the line number and the 16th is + the line offset to the FOR statement. + RUNSTK is also called ENDSTAR; it is used by BASIC to point to + the end of the string/array space pointed to by STARR above. + + + 144,145 90,91 MEMTOP + + Pointer to the top of BASIC memory, the end of the space the + program takes up. There may still be space between this address + and the display list, the size of which may be retrieved by the + FRE(0) command (which actually subtracts the MEMTOP value + that is at locations 741 and 742; $2E5, $2E6). Not to be confused + with locations 741 and 742, which have the same name but are an + OS variable. MEMTOP is also called TOPSTK; it points to the top + of the stack space pointed to by RUNSTK above. + + When reserving memory using location 106 ($6A) and MEMTOP, + here's a short error-trapping routine you can add: + + 10 SIZE = (PEEK(106) - # of pages yo + u are reserving) * 256 + 20 IF SIZE < = PEEK(144) + PEEK(145 + ) * 256 THEN PRINT " PROGRAM TOO L + ARGE": END + + Locations 146 to 202 ($92 to $CA) are reserved for use by the 8K + BASIC ROM. + Locations 176 to 207 ($B0 to $CF) are reserved by the Assembler + Editor cartridge for the user's page zero use. The Assembler debug + routine also reserves 30 bytes in page zero, scattered from location 164 + ($A4) to 255 ($FF), but they cannot be used outside the debug process. + (See De Re Atari, Rev. 1, Appendix A for a list of these available + bytes.) + + + 186,187 BA,BB STOPLN + + The line where a program was stopped either due to an error or + the use of the BREAK key, or a STOP or a TRAP statement + occurred. You can use PEEK (186) + PEEK (187) * 256 in a + GOTO or GOSUB statement. + + + 195 C3 ERRSAVE + + The number of the error code that caused the stop or the TRAP. + You can use this location in a program in a line such as: + + 10 IF PEEK(195) <> 144 THEN 100 + + + 201 C9 PTABW + + This location specifies the number of columns between TAB + stops. The first tab will beat PEEK(201). The default is ten. This is + the value between items separated in a PRINT statement by com- + mas -- such as PRINT AS, LOOP, C(12) -- not by the TAB key + spacing. + The minimum number of spaces between TABS is three. If you + POKE 201,2, it will be treated as four spaces, and POKE 201,1 is + treated as three spaces. POKE 201,0 will cause the system to + hang when it encounters a PRINT statement with commas. To + change the TAB key settings, see TABMAP (locations 675 to 689; + $2A3 - $2B1). PTABW is not reset to the default value by pressing + RESET or changing GRAPHICS modes (unlike TABMAP). + PTABW works in all GRAPHICS modes, not merely in text + modes. The size of the spaces between items depends on the pixel + size in the GRAPHICS mode in use. For example, in GR.0, each + space is one character wide, while in GR.8 each space is one-half + color clock (one dot) wide. + + + 203-207 CB-CF .... + + Unused by either the BASIC or the Assembler cartridges. + + + 208-209 D0-D1 .... + + Unused by BASIC. The only time I have seen any of these unused + locations in use is in COMPUTE! (March 1982 and October + 1981), when they were used for user sort routines, and in ANTIC + (June 1982), where they were used as flags in a graphic + demonstration. The bytes from 203 to 209 ($CB to $D1) are the + only page zero bytes uncontestably left free by BASIC. + + + 210-211 D2-D3 .... + + Reserved for BASIC or other cartridge use. + + Locations 212 to 255 ($D4 to $FF) are reserved for the floating point + package use. The FP routines are in ROM, from locations 55296 to + 57393 ($D800 to $E031). These page zero locations may be used if the + FP package is not called by the user's program. However, do not use + any of these locations for an interrupt routine, since such routines + might occur during an FP routine called by BASIC, causing the + system to crash. + + Floating Point uses a six-byte precision. The first byte of the Binary + Coded Decimal (BCD) number is the exponent (where if BIT 7 equals + zero, then the number is positive; if one, then it is negative). The next + five bytes are the mantissa. If only that were all there was to it. The + BCD format is rather complex and is best explained in chapter eight of + De Re Atari. + + + 212-217 D4-D9 FR0 + + Floating point register zero; holds a six-byte internal form of the + FP number. The value at locations 212 and 213 are used to return + a two-byte hexadecimal value in the range of zero to 65536 + ($FFFF) to the BASIC program (low byte in 212, high byte in + 213). The floating point package, if used, requires all locations + from 212 to 255. All six bytes of FR0 can be used by a machine + language routine, provided FR0 isn't used and no FP functions + are used by that routine. To use 16 bit values in FP, you would + place the two bytes of the number into the least two bytes of FR0 + (212, 213; $D4, $D5), and then do a JSR to $D9AA (55722), which + will convert the integer to its FP representation, leaving the result + in FR0. To reverse this operation, do a JSR to $D9D2 (55762). + + + 218-223 DA-DF FRE + + FP extra register (?) + + + 224-229 E0-E5 FR1 + + Floating point register one; holds a six-byte internal form of the + FP number as does FR0. The FP package frequently transfers + data between these two registers and uses both for two-number + arithmetic operations. + + + 230-235 E6-EB FR2 + + FP register two. + + + 236 EC FRX + + FP spare register. + + + 237 ED EEXP + + The value of E (the exponent). + + + 238 EE NSIGN + + The sign of the FP number. + + + 239 EF ESIGN + + The sign of the exponent. + + + 240 F0 FCHRFLG + + The first character flag. + + 241 Fl DIGRT + The number of digits to the right of the decimal. + + + 242 F2 CIX + + Character (current input) index. Used as an offset to the input + text buffer pointed to by INBUFF below. + + + 243,244 F3,F4 INBUFF + + Input ASCII text buffer pointer; the user's program line input + buffer, used in the translation of ATASCII code to FP values. The + result output buffer is at locations 1408 to 1535 ($580 to $5FF). + + + 245,246 F5,F6 ZTEMP1 + + Temporary register. + + + 247,248 F7,F8 ZTEMP4 + + Temporary register. + + + 249,250 F9,FA ZTEMP3 + + Temporary register. + + + 251 FB RADFLG + + Also called DEGFLG. When set to zero, all of the trigonometric + functions are performed in radians; when set to six, they are done + in degrees. BASIC's NEW command and RESET both restore + RADFLG to radians. + + + 252,253 FC,FD FLPTR + + Points to the user's FP number. + + + 254,255 FE,FF FPTR2 + + Pointer to the user's second FP number to be used in an + operation. + + End of the page zero RAM. + + --------------------------------------------------------------------------- + + PAGE ONE: THE STACK + + Locations 256 to 511 ($100 to $1FF) are the stack area for the OS, DOS + and BASIC. This area is page one. Machine language JSR, PHA and + interrupts all cause data to be written to page one, and RTS, PLA and + RTI instructions all read data from page one. On powerup or RESET, + the stack pointer is initialized to point to location 511 ($1FF). The stack + then pushes downward with each entry to 256 ($100). In case of + overflow, the stack will wrap around from 256 back to 511 again. + + --------------------------------------------------------------------------- + + PAGES TWO TO FOUR + + Locations 512 to 1151 ($200 to $47F) are used by the OS for working + variables, tables and data buffers. In this area, locations 512 to 553 + ($200 to $229) are used for interrupt vectors, and locations 554 to 623 + ($22A to $26F) are for miscellaneous use. Much of pages two through + five cannot be used except by the OS unless specifically noted. A + number of bytes are marked as "spare", i.e., not in use currently. The + status of these bytes may change with an Atari upgrade, so their use is + not recommended. + + There are two types of interrupts: Non-Maskable Interrupts (NMI) + processed by the ANTIC chip and Interrupt Requests (IRQ) processed + by the POKEY and the PIA chips. NMI's are for the VBLANK interrupts + (VBI's; 546 to 549, $222 to $225), display list interrupts (DLI) and + RESET key interrupts. They initiate the stage one and stage two + VBLANK procedures; usually vectored through an OS service routine, + they can be vectored to point to a user routine. IRQ's are for the timer + interrupts, peripheral and serial bus interrupts, BREAK and other key + interrupts, and 6502 BRK instruction interrupts. They can usually be + used to vector to user routines. See NMIST 54287 ($D40F) and IRQEN + 53774 ($D20E) for more information. NMI interrupt vectors are marked + NMI; IRQ interrupt vectors are marked IRQ. + Refer to the chart below location 534 for a list of the interrupt vectors in + the new OS "B" version ROMs. + + + 512,513 200,201 VDSLST + + The vector for NMI Display List Interrupts (DLI): containing the + address of the instructions to be executed during a DLI (DLI's are + used to interrupt the processor flow for a few microseconds at the + particular screen display line where the bit was set, allowing you + to do another short routine such as music, changing graphics + modes, etc.). The OS doesn't use DLI's; they must be user- + enabled, written and vectored through here. The NMI status + register at 54287 ($D40F) first tests to see if an interrupt was + caused by a DLI and, if so, jumps through VDSLST to the routine + written by the user. DLI's are disabled on powerup, but VBI's are + enabled (see 546 to 549; $222 to $225). + + VDSLST is initialized to point to 59315 ($E7B3), which is merely + an RTI instruction. To enable DLI's, you must first POKE 54286 + ($D40E) with 192 ($C0); otherwise, ANTIC will ignore your + request. You then POKE 512 and 513 with the address (LSB/MSB) + of the first assembly language routine to execute during the DLI. + You must then set BIT 7 of the Display List instruction(s) where + the DLI is to occur. You have only between 14 and 61 machine + cycles available for your DLI, depending on your GRAPHICS + mode. You must first push any 6502 registers onto the stack, and + you must end your DLI with an RTI instruction. Because you are + dealing with machine language for your DLI, you can POKE + directly into the hardware registers you plan to change, rather + than using the shadow registers that BASIC uses. + + There is, unfortunately, only one DLI vector address. If you use + more than one DLI and they are to perform different activities, + then changing the vectoring to point to a different routine must + be done by the previous DLI's themselves. + + Another way to accomplish interrupts is during the VBLANK + interval with a VBI. One small problem with using DLI's is that + the keyboard "click" routine interferes with the DLI by throwing + off the timing, since the click is provided by several calls to the + WSYNC register at 54282 ($D40A). Chris Crawford discusses + several solutions in De Re Atari, but the easiest of them is not to + allow input from the keyboard! See Micro, December 1981, + Creative Computing, July 1981 and December 1981. + Here's a short example of a DLI. It will print the lower half of your + text screen upside down: + + 10 START = PEEK(560) + PEEK(561) * + 256: POKE START + 16,130 + 20 PAGE = 1536: FOR PGM = PAGE TO P + AGE + 7: READ BYTE: POKE PGM, BYTE + : NEXT PGM + 30 DATA 72,169,4,141,1,212,104,64 + 40 POKE 512,0: POKE 513,6: POKE 542 + 86,192 + 50 FOR TEST = 1 TO 240: PRINT"SEE " + ;: NEXT TEST + 60 GOTO 60 + + DOWNLOAD VDSLST.BAS + + Another example of a DLI changes the color of the bottom half of + the screen. To use it, simply change the PAGE + 7 to PAGE + 10 + in the program above and replace line 30 with: + + 30 DATA 72,169,222,141,10,212,141,2 + 4,208,104,64 + + Finally, delete lines 50 and 60. See also location 54282 ($D40A). + + + 514,515 202,203 VPRCED + + Serial (peripheral) proceed line vector, initialized to 59314 + ($E7B2), which is merely a PLA, RTI instruction sequence. It is + used when an IRQ interrupt occurs due to the serial I/O bus + proceed line which is available for peripheral use. According to + De Re Atari, this interrupt is not used and points to a PLA, RTI + instruction sequence. This interrupt is handled by the PIA chip + and can be used to provide more control over external devices. + See the OS Listing, page 33. + + + 516,517 204,205 VINTER + + Serial (peripheral) interrupt vector, initialized to 59314 ($E7B2). + Used for the IRQ interrupt due to a serial bus I/O interrupt. + According to De Re Atari, this interrupt is not used and points to + a PLA, RTI sequence. This interrupt is processed by PIA. See the + OS Listing, page 33. + + + 518,519 206,207 VBREAK + + Software break instruction vector for the 6502 BRK ($00) + command (not the BREAK key, which is at location 17; $11), + initialized to 59314 ($E7B2). This vector is normally used for + setting break points in an assembly language debug operation. + IRQ. + + + 520,521 208,209 VKEYBD + + POKEY keyboard interrupt vector, used for an interrupt + generated when any keyboard key is pressed other than BREAK + or the console buttons. Console buttons never generate an + interrupt unless one is specifically user-written. VKEYBD can be + used to process the key code before it undergoes conversion to + ATASCII form. Initialized to 65470 ($FFBE) which is the OS + keyboard IRQ routine. + + + 522,523 20A,20B VSERIN + + POKEY serial I/O bus receive data ready interrupt vector, + initialized to 60177 ($EB11), which is the OS code to place a byte + from the serial input port into a buffer. Called INTRVEC by DOS, + it is used as an interrupt vector location for an SIO patch. DOS + changes this vector to 6691 ($1A23), the start of the DOS + interrupt ready service routine. IRQ. + + + 524,525 20C,20D VSEROR + + POKEY serial I/O transmit ready interrupt vector, initialized to + 60048 (EA90), which is the OS code to provide the next byte in a + buffer to the serial output port. DOS changes this vector to 6630 + ($19E6), the start of the DOS output needed interrupt routine. + IRQ. + + + 526,527 20E,20F VSEROC + + POKEY serial bus transmit complete interrupt vector, initialized + to 60113 ($EAD1), which sets a transmission done flag after the + checksum byte is sent. IRQ. + + SIO uses the three last interrupts to control serial bus + communication with the serial bus devices. During serial bus + communication, all program execution is halted. The actual + serial I/O is interrupt driven; POKEY waits and watches for a flag + to be set when the requested I/O operation is completed. During + this wait, POKEY is sending or receiving bits along the seriai + bus. When the entire byte has been transmitted (or received), the + output needed (VSEROR) or the input ready (VSERIN) IRQ is + generated according to the direction of the data flow. This causes + the next byte to be processed until the entire buffer has been sent + or is full, and a flag for "transmission done" is set. At this point, + SIO exits back to the calling routine. You can see that SIO wastes + time waiting for POKEY to send or receive the information on the + bus. + + + 528,529 210,211 VTIMR1 + + POKEY timer one interrupt vector, initialized to 59314 ($E7B2), + which is a PLA, RTI instruction sequence. Timer interrupts are + established when the POKEY timer AUDF1 (53760; $D200) + counts down to zero. Values in the AUDF registers are loaded + into STIMER at 53769 ($D209). IRQ. + + + 530,531 212,213 VTIMR2 + + POKEY timer two vector for AUDF2 (53762, $D202), initialized to + 59314 ($E7B2). IRQ. + + + 532,533 214,215 VTIMR4 + + POKEY timer four vector for AUDF4 (53766, $D206), initialized + to 59314 ($E7B2). This IRQ is only vectored in the "B" version of + the OS ROMs. + + + 534,535 216,217 VIMIRQ + + The IRQ immediate vector (general). Initialized to 59126 + ($E6F6). JMP through here to determine cause of the IRQ + interrupt. Note that with the new ("B") OS ROMs, there is a + BREAK key interrupt vector at locations 566, 567 ($236, $237). + See 53774 ($D20E) for more information on IRQ interrupts. + + The new "B" version OS ROMs change the vectors above as + follows: + + VDSLST 59280 ($E790) + VPRCED 59279 ($E78F) + VINTER 59279 ($E78F) + VBREAK 59279 ($E78F) + VKEYBD NO CHANGE + VSERIN 60175 ($EB0F) + VSEROR NO CHANGE + VSEROC 60111 ($EACF) + VTIMR 1-4 59279 ($E78F) + VIMIRQ 59142 ($E706) + VVBLKI 59310 ($E7AE) + VVBLKD 59653 ($E905) + + --------------------------------------------------------------------------- + The locations from 536 to 558 ($218 to $22E) are used for the system + software timers. Hardware timers are located in the POKEY chip and + use the AUDF registers. These timers count backwards every 1/60 + second (stage one VBLANK) or 1/30 second (stage two VBLANK) + interval until they reach zero. If the VBLANK process is disabled or + intercepted, the timers will not be updated. See De Re Atari for + information regarding setting these timers in an assembly routine + using the SETVBV register (58460; $E45C). These locations are user- + accessible and can be made to count time for music duration, game + I/O, game clock and other functions. + Software timers are used for durations greater than one VBLANK + interval (1/60 second). For periods of shorter duration, use the + hardware registers. + + + 536,537 218,219 CDTMV1 + + System timer one value. Counts backwards from 255. This SIO + timer is decremented every stage one VBLANK. When it reaches + zero, it sets a flag to jump (JSR) through the address stored in + locations 550, 551 ($226, $227). Only the realtime clock + (locations 18-20; $12-14), timer one, and the attract mode + register (77; $4D) are updated when the VBLANK routine is cut + short because time-critical code (location 66; $42 set to non-zero + for critical code) is executed by the OS. Since the OS uses timer + one for its I/O routines and for timing serial bus operations + (setting it to different values for timeout routines), you should use + another timer to avoid conflicts or interference with the operation + of the system. + + + 538,539 21A,21B CDTMV2 + + System timer two. Decremented at the stage two VBLANK. Can + be decremented every stage one VBLANK, subject to critical + section test as defined by setting of CRITIC flag (location 66; + $42). This timer may miss (skip) a count when time-critical code + (CRITIC equals non-zero) is being executed. It performs a JSR + through location 552, 553 ($228, $229) when the value counts + down to zero. + + + 540,541 21C,21D CDTMV3 + + System timer three. Same as 538. Timers three, four, and five are + stopped when the OS sets the CRITIC flag to non-zero as well. + The OS uses timer three to OPEN the cassette recorder and to set + the length of time to read and write tape headers. Any prior value + in the register during this function will be lost. + + + 542,543 21E,21F CDTMV4 + + System timer four. Same as 538 ($21A). + + + 544,545 220,221 CDTMV5 + + System timer five. Same as 538 ($21A). Timers three, four, and + five all set flags at 554, 556 and 558 ($22A, $22C, $22E), + respectively, when they decrement to zero. + + + 546,547 222,223 VVBLKI + + VBLANK immediate register. Normally jumps to the stage one + VBLANK vector NMI interrupt processor at location 59345 + ($E7D1); in the new OS "B" ROMs; 59310, $E7AE). The NMI + status register tests to see if the interrupt was due to a VBI (after + testing for a DLI) and, if so, vectors through here to the VBI + routine, which may be user-written. On powerup, VBI's are + enabled and DLI's are disabled. See location 512; $200. + + + 548,549 224,225 VVBLKD + + VBLANK deferred register; system return from interrupt, + initialized to 59710 ($E93E, in the new OS "B" ROMs; 59653; + $E905), the exit for the VBLANK routine. NMI. + + These two VBLANK vectors point to interrupt routines that occur + at the beginning of the VBLANK time interval. The stage one + VBLANK routine is executed; then location 66 ($42) is tested for + the time-critical nature of the interrupt and, if a critical code + section has been interrupted, the stage two VBLANK routine is + not executed with a JMP made through the immediate vector + VVBLKI. If not critical, the deferred interrupt VVBLKD is used. + Normally the VBLANK interrupt bits are enabled (BIT 6 at + location 54286; $D40E is set to one). To disable them, clear BIT 6 + (set to zero). + + The normal seguence for VBLANK interrupt events is: after the + OS test, JMP to the user immediate VBLANK interrupt routine + through the vector at 546, 547 (above), then through SYSVBV at + 58463 ($E45F). This is directed by the OS through the VBLANK + interrupt service routine at 59345 ($E7D1) and then on to the + user-deferred VBLANK interrupt routine vectored at 548, 549. it + then exits the VBLANK interrupt routine through 58466 ($E462) + and an RTI instruction. + + If you are changing the VBLANK vectors during the interrupt + routine, use the SETVBV routine at 58460 ($E45C). An + immediate VBI has about 3800 machine cycles of time to use a + deferred VBI has about 20,000 cycles. Since many of these cycles + are executed while the electron beam is being drawn, it is + suggested that you do not execute graphics routines in deferred + VBI's. See the table of VBLANK processes at the end of the map + area. + + if you create your own VBI's, terminate an immediate VBI with a + JMP to 58463 ($E45F) and a deferred VBI with a JMP to 58466 + ($E462). To bypass the OS VBI routine at 59345 ($E7D1) entirely, + terminate your immediate VBI with a JMP to 58466 ($E462). + + Here's an example of using a VBI to create a flashing cursor. It + will also blink any text you display in inverse mode. + + 10 FOR BLINK = 1664 TO 1680: READ B + YTE: POKE BLINK, BYTE: NEXT BLINK + 20 POKE 548,128: POKE 549,6 + 30 DATA 8,72,165,20,41,16,74,74,74, + 141 + 40 DATA 243,2,104,40,76,62,233 + + DOWNLOAD VVBLKD.BAS + + To restore the normal cursor and display, POKE 548,62 and + POKE 549,233. + + + 550,551 226,227 CDTMA1 + + System timer one jump address, initialized to 60400 ($EBF0). + When locations 536, 537 ($218, $219) reach (count down to) zero, + the OS vectors through here (jumps to the location specified by + these two addresses). You can set your machine code routine + address here for execution when timer one reaches (counts down + to) zero. Your code should end with the RTS instruction. + Problems may occur when timer values are set greater than 255, + since the 6502 cannot manipulate 16-bit values directly (a + number in the range of zero to 255 is an eight-bit value; if a value + requires two bytes to store, such as a memory location, it is a + 16-bit value). Technically, a VBLANK interrupt could occur + when one timer byte is being initialized and the other not yet set. + To avoid this, keep timer values less than 255. See the Atari OS + User's Manual, page 106, for details. + + Since the OS uses timer one, it is recommended that you use + timer two instead, to avoid conflicts with the operation of the + Atari. Initialized to 60396 ($EBEA) in the old ROMs, 60400 + ($EBF0) in the new ROMs. NMI + + + 552,553 228,229 CDTMA2 + + System timer two jump address. Not used by the OS, available to + user to enter the address of his or her own routine to JMP to when + the timer two (538, 539; $21A, $21B) count reaches zero. + Initialized to zero; the address must be user specified. NMI + + + 554 22A CDTMF3 + + System timer three flag, set when location 540, 541 ($21C, $21D) + reaches zero. This register is also used by DOS as a timeout flag. + + + 555 22B SRTIMR + + Software repeat timer, controlled by the IRQ device routine. It + establishes the initial 1/2 second delay before a key will repeat. + Stage two VBLANK establishes the 1/10 second repeat rate, + decrements the timer and implements the auto repeat logic. + Every time a key is pressed, STIMER is set to 48 ($30). Whenever + SRTIMR is equal to zero and a key is being continuously pressed, + the value of that key is continually stored in CH, location 764 + ($2FC). + + + 556 22C CDTMF4 + + System timer four flag. Set when location 542, 543 ($21E, $21F) + counts down to zero. + + + 557 22D INTEMP + + Temporary register used by the SETVBL routine at 58460 + ($E45C). + + + 558 22E CDTMF5 + + System timer five flag. Set when location 558, 559 ($22E, $22F) + counts down to zero. + + --------------------------------------------------------------------------- + + 559 22F SDMCTL + + Direct Memory Access (DMA) enable. POKEing with zero allows + you to turn off ANTIC and speed up processing by 30%. Of + course, it also means the screen goes blank when ANTIC is + turned off! This is useful to speed things up when you are doing a + calculation that would take a long time. It is also handy to turn off + the screen when loading a drawing, then turning it on when the + screen is loaded so that it appears instantly, complete on the + screen. To use it you must first PEEK(559) and save the result in + order to return your screen to you. Then POKE 559,0 to turn off + ANTIC. When you are ready to bring the screen back to life, + POKE 559 with the number saved earlier. + + This location is the shadow register for 54272 ($D400), and the + number you PEEKed above defines the playfield size, whether or + not the missiles and players are enabled, and the player size + resolution. To enable your options by using POKE 559, simply + add up the values below to obtain the correct number to POKE + into SDMCTL. Note that you must choose only one of the four + playfield options appearing at the beginning of the list: + + Option Decimal Bit + No playfield 0 0 + Narrow playfield 1 0 + Standard playfield 2 0,1 + Wide playfield 3 0,1 + Enable missle DMA 4 2 + Enable player DMA 8 3 + Enable player and missile + DMA 12 2,3 + One line player resolution 16 4 + Enable instructions to fetch + DMA 32 5 (see below) + + Note that two-line player resolution is the default and that it is not + necessary to add a value to 559 to obtain it. I have included the + appropriate bits affected in the table above. The default is 34 + ($22). + + The playfield is the area of the TV screen you will use for display, + text, and graphics. Narrow playfield is 128 color clocks (32 + characters wide in GR.0), standard playfield is 160 color clocks + (40 characters), and wide playfield is 192 color clocks wide (48 + characters). A color clock is a physical measure of horizontal + distance on the TV screen. There are a total of 228 color clocks on + a line, but only some of these (usually 176 maximum) will be + visible due to screen limitations. A pixel, on the other hand, is a + logical unit which varies in size with the GRAPHICS mode. Due + to the limitations of most TV sets, you will not be able to see all of + the wide playfield unless you scroll into the offscreen portions. + BIT 5 must be set to enable ANTIC operation; it enables DMA for + fetching the display list instructions. + + + 560,561 230,231 SDLSTL + + Starting address of the display list. The display list is an + instruction set to tell ANTIC where the screen data is and how to + display it. These locations are the shadow for 54274 and 54275 + ($D402, $D403). You can also find the address of the DL by + PEEKing one byte above the top of free memory: + + PRINT PEEK(741) + PEEK(742) * 256 + 1. + + However, 560 and 561 are more reliable pointers since custom + DL's can be elsewhere in memory. Atari standard display lists + simply instruct the ANTIC chip as to which types of mode lines to + use for a screen and where the screen data may be found in + memory. Normally, a DL is between 24 and 256 bytes long (most + are less than 100 bytes, however), depending on your + GRAPHICS mode (see location 88,89 for a chart of DL sizes and + screen display use). + + By altering the DL, you can mix graphics modes on the same + screen; enable fine scrolling; change the location of the screen + data; and force interrupts (DLI's) in order to perform short + machine language routines. + + DL bytes five and six are the addresses of the screen memory + data, the same as in locations 88 and 89 ($58, $59). Bytes four, + five, and six are the first Load Memory Scan (LMS) instruction. + Byte four tells ANTIC what mode to use; the next two bytes are + the location of the first byte of the screen RAM (LSB/MSB). + Knowing this location allows you to write directly to the screen by + using POKE commands (you POKE the internal character codes, + not the ATASCII codes -- see the BASIC Reference Manual, p. + 55). + + For example, the program below will POKE the internal codes to + the various screen modes. You can see not only how each screen + mode handles the codes, but also roughly where the text window + is in relation to the display screen (the 160 bytes below + RAMTOP). Note that the GTIA modes have no text window. If + you don't have the GTIA chip, your Atari will default to + GRAPHICS 8, but with GTIA formatting. + + 1 TRAP 10: GRAPHICS Z + 5 SCREEN = PEEK(560) + PEEK(561) * + 256 + 6 TV = SCREEN + 4: TELE = SCREEN + 5 + 8 DISPLAY = PEEK(TV) + PEEK(TELE) * + 256 + 10 FOR N = 0 TO 255: POKE DISPLAY + + N,N: NEXT N + 20 DISPLAY = DISPLAY + N + 30 IF DISPLAY > 40959 THEN Z = Z + 1 + : GOTO 1 + 40 GOTO 10 + 50 Z = Z + 1:IF Z > 60 THEN END + 60 GOTO 1 + + Here's another short program which will allow you to examine the + DL in any GRAPHICS mode: + + 10 REM CLEAR SCREEN FIRST + 20 PRINT"ENTER GRAPHICS MODE": REM A + DD 16 TO THE MODE TO SUPPRESS THE + TEXT WINDOW + 30 INPUT A: GRAPHICS A + 40 DLIST = PEEK(560) + PEEIK(561) * 2 + 56 + 50 LOOK = PEEK(DLIST): PRINT LOOK;" + "; + 60 IF LOOK <> 65 THEN DLIST = DLIST + + 1: GOTO 50 + 70 LPRINT PEEK(DLIST + 1);" ";PEEK(D + LIST + 2) + 80 END + + The value 65 in the DL is the last instruction encountered. It tells + ANTIC to jump to the address in the next two bytes to re-execute + the DL, and wait for the next VBLANK. If you don't have a + printer, change the LPRINT commands to PRINT and modify the + routine to save the data in an array and PRINT it to the screen + after (in GR.0). + + If you would like to examine the locations of the start of the + Display List, screen, and text window, try: + + 5 REM CLEAR SCREEN FIRST + 6 INPUT A: GRAPHICS A + 10 DIM DLIST$(10), SAVMSC$(10), TXT$ + (10) + 15 DLIST$ = "DLIST": SAVMSC$ = "SAVM + SC": TXT$ = "TEXT" + 20 DLIST = PEEK(560) + PEEK(561) * 2 + 56 + 30 SAV = PEEK(88) + PEEK(89) * 256: + TXT = PEEK(660) + PEEK(66l) * 256 + 40 PRINT DLIST$;" "; DLIST,SAVMSC$;" + ";SAV + 50 PRINT TXT$;" "; TEXT + 60 INPUT A: GRAPHICS A: GOTO 20 + + Since an LMS is simply a map mode (graphics) or character + mode (text) instruction with BIT six set, you can make any or all of + these instructions into LMS instructions quite easily, pointing + each line to a different RAM area if necessary. This is discussed + in De Re Atari on implementing horizontal scrolling. + + DL's can be used to help generate some of the ANTIC screen + modes that aren't supported by BASIC, such as 7.5 (ANTIC + mode E) or ANTIC mode three, the lowercase with descenders + mode (very interesting; ten scan lines in height which allow true + descenders on lowercase letters). + + If you create your own custom DL, you POKE its address here. + Hitting BESET or changing GRAPHICS modes will restore the + OS DL address, however. The display list instruction is loaded + into a special register called the Display Instruction Register (IR). + which processes the three DL instructions (blank, jump, or + display). It cannot be accessed directly by the programmer in + either BASIC or machine language. A DL cannot cross a 1K + boundary unless a jump instruction is used. + + There are only four display list instructions: blank line (uses BAK + color), map mode, text mode, and jump. Text (character mode) + instructions and map mode (graphics) instructions range from + two to 15 ($2 to $F) and are the same as the ANTIC GRAPHICS + modes. A DL instruction byte uses the following conventions + (functions are enabled when the bit is set to one): + + Bit Decimal Function + 7 128 Display List Interrupt when set (enabled + equals one) + 6 64 Load Memory Scan. Next two bytes are the + LSB/MSB of the data to load. + 5 32 Enable vertical fine scrolling. + 4 16 Enable horizontal fine scrolling. + 3-0 8-1 Mode + 0 0 1 0 Character + to Modes + 0 1 1 1 + . . . . . . . + 1 0 0 0 Map + to Modes + 1 1 1 1 + + The above bits may be combined (i.e., DLI, scrolling and LMS + together) if the user wishes. + + Special DL instructions (with decimal values): + Blank 1 line = 0 5 lines = 64 + 2 lines = 16 6 lines = 80 + 3 lines = 32 7 lines = 96 + 4 lines = 48 8 lines = 112 + + Jump instruction (JMP) = zero (three-byte instruction). + Jump and wait for Vertical Blank (JVP) = 65 (three-byte + instruction). + Special instructions may be combined only with DL interrupt + instructions. + + A Display List Interrupt is a special form of interrupt that takes + place during the screen display when the ANTIC encounters a + DL instruction with the interrupt BIT 7 set. See location 512 + ($200) for DLI information. + + Since DL's are too large a topic to cover properly in this manual, + I suggest you look in the many magazines (i.e., Creative + Computing, July 1981, August 1981; Micro, December 1981; + Softside, #30 to 32, and BYTE, December 1981) for a more + detailed explanation + + + 562 232 SSKCTL + + Serial port control register, shadow for 53775 ($D20F). Setting + the bits in this register to one has the following effect: + + Bit Decimal Function + 0 1 Enable the keyboard debounce circuit. + 1 2 Enable the keyboard scanning circuit. + 2 4 The pot counter completes a read within two + scan lines instead of one frame time. + 3 8 Serial output transmitted as two-tone instead + of logic true/false (POKEY two-tone mode). + 4-6 16-64 Serial port mode control. + 7 128 Force break; serial output to zero. + + Initialized to 19 ($13) which sets bits zero, one and four. + + + 563 233 SPARE + + No OS use. See the note at location 651 regarding spare bytes. + + + 564 234 LPENH + + Light pen horizontal value shadow for 54284 ($D40C). Values + range from zero to 227. + + + 565 235 LPENV + + Light pen vertical value: shadow for 54285 ($D40D). Value is the + same as VCOUNT register for two-line resolution (see 54283; + $D40B). Both light pen values are modified when the trigger is + pressed (pulled low). The light pen positions are not the same as + the normal screen row and column positions. There are 96 + vertical positions, numbered from 16 at the top to 111 at the + bottom, each one equivalent to a scan line. Horizontal positions + are marked in color clocks. There are 228 horizontal positions, + numbered from 67 at the left. When the LPENH value reaches + 255, it is reset to zero and begins counting again by one to the + rightmost edge, which has a value of seven. + + Obviously, because of the number of positions readable and the + small size of each, a certain leeway must be given by the + programmer when using light pen readouts on a program. At the + time of this writing, Atari had not yet released its light pen onto + the market, although other companies have. + + + 566,567 236,237 BRKKY + + BREAK key interrupt vector. This vector is available only with + the version "B" OS ROMs, not the earlier version. You can use + this vector to write your own BREAK key interrupt routine. + Initialized to 59220 ($E754). + + + 568,569 238,239 .... + + Two spare bytes. + + + 570 23A CDEVIC + + Four-byte command frame buffer (CFB) address for a device -- + used by SIO while performing serial I/O, not for user access. + CDEVIC is used for the SIO bus ID number The other three CFB + bytes are: + + + 571 23B CCOMND + + The SIO bus command code. + + + 572 23C CAUX1 + + Command auxiliary byte one, loaded from location 778 ($30A) + by SIO. + + + 573 23D CAUX2 + + Command auxiliary byte two, loaded from location 779 ($30B) by + SIO. + + + 574 23E TEMP + + Temporary RAM register for SIO. + + + 575 23F ERRFLG + + SIO error flag; any device error except the timeout error (time + equals zero). + + + 576 240 DFLAGS + + Disk flags read from the first byte of the boot file (sector one) of + the disk. + + + 577 241 DBSECT + + The number of disk boot sectors read from the first disk record. + + + 578,579 242,243 BOOTAD + + The address for where the disk boot loader will be put. The + record just read will be moved to the address specified here, + followed by the remaining records to be read. Normally, with + DOS, this address is 1792 ($700), the value also stored + temporarily in RAMLO at 4, 5. Address 62189 ($F2ED) is the OS + disk boot routine entry point (DOBOOT). + + + 580 244 COLDST + + Coldstart flag. Zero is normal, if zero, then pressing RESET will + not result in reboot. If POKEd with one (powerup in progress + flag), the computer will reboot whenever the RESET key is + pressed. Any non-zero number indicates the initial powerup + routine is in progress. + + If you create an AUTORUN.SYS file, it should end with an RTS + instruction. If not, it should POKE 580 with zero and POKE 9 with one. + You can turn any binary file that boots when loaded with DOS menu + selection "L" into an auto-boot file simply by renaming it + "AUTORUN.SYS". Be careful not to use the same name for any two + files on the same disk. + + When this is combined with the disabling of the BREAK key discussed + in location 16 ($10) and the program protection scheme discussed in + location 138 ($8A), you have the means to protect your BASIC + software fairly effectively from being LISTed or examined, although + not from being copied. + + + 581 245 .... + + Spare byte. + + + 582 246 DSKTIM + + Disk time-out register (the address of the OS worst case disk time- + out). It is said by many sources to be set to 160 at initialization + which represents a 171 second time-out, but my system shows a + value of 224 on initialization. Timer values are 64 seconds for + each 60 units of measurement expressed. + It is updated after each disk status request to contain the value of + the third byte of the status frame (location 748; $2EC). All disk + operations have a seven second time-out (except FORMAT), + established by the disk handler (you had noticed that irritating + little delay, hadn't you?). The "sleeping disk syndrome" (the + printer suffers from this malady as well) happens when your drive + times out, or the timer value reaches zero. This has been cured + by the new OS "B" version ROMs. + + + 583-622 247-26E LINBUF + + Forty-byte character line buffer, used to temporarily buffer one + physical line of text when the screen editor is moving screen + data. The pointer to this buffer is stored in 100, 101 ($64, $65) + during the routine. + + + 623 26F GPRIOR + + Priority selection register, shadow for 53275 ($D01B). Priority + options select which screen objects will be "in front" of others. It + also enables you to use all four missiles as a fifth player and + allows certain overlapping players to have different colors in the + areas of overlap. You add your options up as in location 559, + prior to POKEing the total into 623. In this case, choose only one + of the four priorities stated at the beginning. BAK is the + background or border. You can also use this location to select + one of GTIA GRAPHICS modes nine, ten, or eleven. + + Priority options in order Decimal Bit + Player 0 - 3, playfield 0 - 3, BAK + (background) 1 0 + Player 0 - 1, playfield 0 - 3, player 2 - 3, + BAK 2 1 + Playfield 0 - 3, player 0 - 3, BAK 4 2 + Playfield 0 - 1, player 0 - 3, playfield 2 -3, + BAK 8 3 + Other options + Four missiles = fifth player 16 4 + Overlaps of players have 3rd color 32 5 + GRAPHICS 9 (GTIA mode) 64 6 + GRAPHICS 10 (GTIA mode) 128 7 + GRAPHICS 11 (GTIA mode) 192 6, 7 + + It is quite easy to set conflicting priorities for players and + playfields. In such a case, areas where both overlap when a + conflict occurs will turn black. The same happens if the overlap + option is not chosen. + With the color/overlap enable, you can get a multicolor player + by combining players. The Atari performs a logical OR to colors + of players 0/1 and 2/3 when they overlap. Only the 0/1, 2/3 + combinations are allowed; you will not get a third color when + players 1 and 3 overlap, for example (you will get black instead). + If player one is pink and player 0 is blue, the overlap is green. If + you don't enable the overlap option, the area of overlap for all + players will be black. + In GTIA mode nine, you have 16 different luminances of the + same hue. In BASIC, you would use SETCOLOR 4,HUE,0. To + see an example of GTIA mode nine, try: + + 10 GRAPHICS 9: SETCOLOR 4,9,0 + 20 FOR LOOP = 1 TO 15: COLOR LOOP + 30 FOR LINE = 1 TO 2 + 40 FOR TEST = 1 TO 25: PLOT 4 + TES + T, LOOP + LINE + SPACE: NEXT TEST + 45 NEXT LINE + 50 SPACE = SPACE + 4 + 60 NEXT LOOP + 70 GOTO 70: REM WITHOUT THIS LINE, + SCREEN WILL RETURN TO GR.0 + + DOWNLOAD GTIA9.BAS + + In GTIA mode ten, you have all nine color registers available; + hue and luminance may be set separately for each (it would + otherwise allow 16 colors, but there are only nine registers). Try + this to see: + + 10 N = 0: GRAPHICS 10 + 20 FOR Q = 1 TO 2 + 30 FOR B = 0 TO 8: POKE 704 + B, N + * 16 + A + 35 IF A > 15 THEN A = 0 + 40 COLOR B + 45 A = A + 1: N = N + 1 + 50 IF N > 15 THEN N = 0 + 60 NEXT B + 65 TRAP 70: NEXT Q + 70 POP: N = N + 1: FOR Z = 1 TO 200 + : NEXT Z + 75 GOTO 30 + + DOWNLOAD GTIA10.BAS + + GTIA mode eleven is similar to mode nine except that it allows 16 + different hues, all of the same luminance. In BASIC, use + SETCOLOR 4,O,luminance. Try this for a GTIA mode eleven + demonstration: + + 10 GRAPHICS 11 + 20 FOR LOOP = 0 TO 79: COLOR LOOP: + PLOT LOOP,0: DRAWTO LOOP,191: NEXT + LOOP + 30 GOTO 30 + + DOWNLOAD GTIA11.BAS + + You can use these examples with the routine to rotate colors, + described in the text preceding location 704. GTIA mode pixels + are long and skinny; they have a four to one horizontal length to + height ratio. This obviously isn't very good for drawing curves + and circles! + + GTIA modes are cleared on the OPEN command. How can you + tell if you have the GTIA chip? Try POKE 623,64. If you have the + GTIA, the screen will go all black. If not, you don't have it. Here + is a short routine, written by Craig Chamberlain and Sheldon + Leemon for COMPUTE!, which allows an Atari to test itself for the + presence of a CTIA or GTIA chip. The routine flashes the answer + on the screen, hut can easily be modified so a program will + "know" which chip is present so it can adapt itself accordingly: + + 10 POKE 66,1:GRAPHICS 8:POKE 709,0:PO + KE 710,0:POKE 66,0:POKE 623,64:P0K + E 53248,42:POKE 5326l,3:PUT#6,1 + 20 POKE 53278,0:FOR K=1 TO 300:NEXT K + :GRAPHICS 18:POKE 53248,0:POSITION + 8,5:? #6;CHR$(71-PEEK(53252));"TI + A" + 30 POKE 708,PEEK(20):GOTO 30 + + DOWNLOAD CTIAGTIA.BAS + + How can you get the GTIA if you don't have one? Ask your local + Atari service representative or dealer, or write directly to Atari in + Sunnyvale, California. + + See the GTIA/CTIA introduction at location 53248 ($D000) for + more discussion of the chip. See BYTE, May 1982, COMPUTE!, + July through September 1982, and De Re Atari for more on the + GTIA chip, and the GTIA Demonstration Diskette from the Atari + Program Exchange (APX). + + --------------------------------------------------------------------------- + Locations 624 to 647 ($270 to $287) are used for game controllers: + paddle, joystick and lightpen values. + + + 624 270 PADDL0 + + The value of paddle 0 (paddles are also called pots, short for + potentiometer); PEEK 624 returns a number between zero and + 228 ($E4), increasing as the knob is turned counter-clockwise. + When used to move a player or cursor (i.e., PLOT + PADDLE(0),0), test your screen first. Many sets will not display + locations less than 48 ($30) or greater than 208 ($D0), and in + many GRAPHICS modes you will get an ERROR 141 -- cursor + out of range. Paddles are paired in the controller jacks, so paddle + 0 and paddle 1 both use jack one. PADDL registers are shadows + for POKEY locations 53760 to 53767 ($D200 to $D207). + + + 625 271 PADDL1 + + This and the next six bytes are the same as 624, but for the other + paddles. + + + 626 272 PADDL2 + + 627 273 PADDL3 + + 628 274 PADDL4 + + 629 275 PADDL5 + + 630 276 PADDL6 + + 631 277 PADDL7 + + 632 278 STICK0 + + The value of joystick 0. STICK registers are shadow locations for + PIA locations 54016 and 54017 ($D300, $D301). There are nine + possible decimal values (representing 45 degree incrememts) + read by each joystick register (using the STICKn command), + depending on the position of the stick: + + Decimal Binary + 14 1110 + | | + 10 | 6 1010 | 0110 + \ |/ \ |/ + 11-- 15 ---7 1011-- 1111 --0111 + / |\ / |\ + 9 | 5 1001 | 0101 + | | + 13 1101 + + 15 (1111) equals stick in the upright (neutral) position. + See Micro, December 1981,for an article on making a + proportional joystick. For an example of a machine language + joystick driver you can add to your BASIC program, see + COMPUTE!, July 1981. + One machine language joystick reader is listed below, based on + an article in COMPUTE!, August 1981: + + 1 GOSUB 1000 + 10 LOOK = STICK(0) + 20 X = USR(1764,LOOK): Y = USR(1781, + LOOK) + 30 ON X GOTO 120, 100, 110 + . + . + . + 100 REM YOUR MOVE LEFT ROUTINE HERE + 105 GOTO 10 + 110 REM YOUR MOVE RIGHT ROUTINE HERE + 115 GOTO 10 + 120 ON Y GOTO 150, 130, 140 + 130 REM YOUR MOVE DOWN ROUTINE HERE + 135 GOTO 10 + 140 REM YOUR MOVE UP ROUTINE HERE + 145 GOTO 10 + 150 REM IF X <> 1 THEN NOTHING DOING. + BRANCH TO YOUR OTHER ROUTINES OR + TO 155 + 155 GOTO 10 + . + . + . + 1000 FOR LOOP = 1764 TO 1790: READ BY + TE: POKE LOOP, BYTE: NEXT LOOP + 1010 DATA 104,104,133,213,104,41,12,7 + 4,74,73,2,24,105,1 + 1020 DATA 133,212,96,104,104,133,213, + 104,41,3,76,237,6 + 1030 RETURN + + DOWNLOAD STICK0.BAS + + See locations 88, 89 ($58, $59) for an example of a USR call using + a string instead of a fixed memory location. + + + 633 279 STICK1 + + This and the next two locations are the same as 632, but for the + other joysticks. These four locations are also used to determine if + a lightpen (PEN 0 - 3) switch is pressed. + + + 634 27A STICK2 + + 635 27B STICK3 + + 636 27C PTRIG0 + + Paddle trigger 0. Used to determine if the trigger or hutton on + paddle 0 is pressed (zero is returned) or not (one is returned). + Since these are the same lines as the joystick left/right switches, + you can use PTRIG for horizontal movement. PTRIG(1) - + PTRIG(0) returns -1 (left), 0 (center), + 1 (right). The next seven + locations are for the other paddle buttons. PTRIG 0 - 3 are + shadows for PIA register 54016 ($D300). + + + 637 27D PTRIG1 + + 638 27E PTRIG2 + + 639 27F PTRIG3 + + 640 280 PTRIG4 + + PTRIG 4-7 are shadows for PIA register 54017 ($D301). + + + 641 281 PTRIG5 + + 642 282 PTRIG6 + + 643 283 PTRIG7 + + 644 284 STRIG0 + + Stick trigger 0. This and the next three locations perform the + same function as the PTRIG locations except for the joysticks. + Like PTBIG, zero is returned when the button is pressed; one is + returned when it is not. STRIG registers are shadow registers for + GTIA/CTIA locations 53264 to 53267 ($D010 to $D013). + + + 645 285 STRIG1 + + 646 286 STRIG2 + + 647 287 STRIG3 + + --------------------------------------------------------------------------- + Locations 648 to 655 ($288 to $28F) are for miscellaneous OS use. + + + 648 288 CSTAT + + Cassette status register. + + + 649 289 WMODE + + Register to store either the read or the write mode for the cassette + handler, depending on the operation: zero equals read, 128 ($80) + equals write. + + + 650 28A BLIM + + Cassette data record buffer size; contains the number of active + data bytes in the cassette buffer for the record being read or + written, at location 1021 ($3FD). Values range from zero to 128 + (cassette record size is 128; $80). The pointer to the byte being + read or written is at 61 ($3D). The value of BLIM is drawn from + the control bytes that precede every cassette record, as + explained in location 1021. + + + 651-655 28B-28F .... + + Spare bytes. It is not recommended that you use the spare bytes + for your own program use. In later upgrades of the OS, these + bytes may be used, causing a conflict with your program. For + example, the new OS ROMs use locations 652 and 653 ($28C, + $28D) in the new IRQ interrupt handler routines. It is best to use a + protected area of memory such as page six, locations 1536 to + 1791 ($600 to $6FF). + + --------------------------------------------------------------------------- + Locations 656 to 703 ($290 to $2BF) are used for the screen RAM + display handler (depending on GRAPHICS mode). + In split-screen mode, the text window is controlled by the screen editor + (E:), while the graphics region is controlled by the display handler + (S:), using two separate IOCB's. Two separate cursors are also + maintained. The display handler will set AUX1 of the IOCB to split- + screen option. Refer to the IOCB area, locations 832 to 959 ($340 to + $3BF). See COMPUTE!, February 1982, for a program to put GR.1 + and GR.2 into the text window area. The text window uses 160 bytes of + RAM located just below RAMTOP (see location 106; $6A). See + location 88 ($58) for a chart of screen RAM use. + + + 656 290 TXTROW + + Text window cursor row; value ranges from zero to three (the text + window has only four lines). TXTROW specifies where the next + read or write in the text window will occur + + + 657,658 291,292 TXTCOL + + Text window cursor column; value ranges from zero to 39. Unless + changed by the user, location 658 will always be zero (there are + only 40 columns in the display, so the MSB will be zero). Since + POSITION, PLOT, LOCATE and similar commands refer to the + graphics cursor in the display area above the text window, you + must use POKE statements to write to this area if PRINT + statements are insufficient. + + + 659 293 TINDEX + + Contains the current split-screen text window GRAPHICS mode. + It is the split-screen equivalent to DINDEX (location 87; $57) and + is always equal to zero when location 128 ($7B) equals zero. + Initialized to zero (which represents GR.0). You can alter the + display list to change the text window into any GRAPHICS mode + desired. If you do so, remember to change TINDEX to reflect that + alteration. + + + 660,661 294,295 TXTMSC + + Address of the upper left corner of the text window. Split-screen + equivalent of locations 88, 89 ($58, $59). + + + 662-667 296-29B TXTOLD + + These locations contain the split-screen equivalents of OLDROW + (90; $5A), OLDCOL (91, 92; $5B, $5C), OLDCHR (location 93, + $5D) and OLDADR (locations 94, 95; $5E, $5F). They hold the + split-screen cursor data. + + + 668 29C TMPX1 + + Temporary register, used by the display handler for the scroll + loop count record. + + + 669 29D HOLD3 + + Temporary register. + + + 670 29E SUBTMP + + Temporary storage. + + + 671 29F HOLD2 + + Temporary register. + + + 672 2A0 DMASK + + Pixel location mask. DMASK contains zeroes tor all bits which do + not correspond to the specific pixel to be operated upon, and + ones for bits which do correspond, according to the GRAPHICS + mode in use, as follows: + + 11111111 Modes 0, 1 and 2: one pixel per screen display + byte. + 11110000 Modes 9, 10 and 11: two pixels per byte. + 00001111 + 11000000 Modes 3, 5 and 7: four pixels per byte. + 00110000 + 00001100 + 00000011 + 10000000 Modes 4, 6 and 8: eight pixels per byte. + 01000000 + + etc. to: + + 00000001 + + A pixel (short for picture cell or picture element) is a logical unit + of video size which depends on the GRAPHICS mode in use for + its dimensions. The smallest pixel is in GR.8 where it is only .5 + color clock wide and one scan line high. In GR.0 it is also only .5 + color clock wide, but it is eight scan lines high. Here is a chart of + the pixel sizes for each mode: + + Text Modes Graphics modes + GR. mode 0 1 2 3 4 5 6 7 8 + Scan lines + per pixel 8 8 16 8 4 4 2 2 1 + Bits + per pixel 1 1 1 2 1 2 1 2 1 + Color clocks + per pixel .5 1 1 4 2 2 1 1 .5 + Characters + per line 40 20 20 -- -- -- -- -- -- + Pixels + per width -- -- -- 40 80 80 160 160 320 + + The number of pixels per screen width is based on the normal + playfield screen. See location 559 ($22F) for information on + playfield size. + + + 673 2A1 TMPLBT + + Temporary storage for the bit mask. + + + 674 2A2 ESCFLG + + Escape flag. Normally zero, it is set to 128 ($80) if the ESC key is + pressed (on detection of the ESC character; 27, $1B). It is reset to + zero following the output of the next character. To display + ATASCII control codes without the use of an ESC character, set + location 766 ($2FE) to a non-zero value. + + + 675-689 2A3-2B1 TABMAP + + Map of the TAB stop positions. There are 15 byte (120 bits) here, + each bit corresponding to a column in a logical line. A one in any + bit means the TAB is set; to clear all TABs simply POKE every + location with zero. There are 120 TAB locations because there + are three physical lines to one logical line in GRAPHICS mode + zero, each consisting of 40 columns. Setting the TAB locations for + one logical line means they will also be set for each subsequent + logical line until changed. Each physical line in one logical line + can have different TAB settings, however. + + To POKE TAB locations from BASIC, you must POKE in the + number (i.e., set the bit) that corresponds to the location of the + bit in the byte (there are five bytes in each line). For example: + To set tabs at locations 5, 23, 27 and 32, first visualize the line as a + string of zeros with a one at each desired tab setting: + + 0000100000000000000000100010000100000000 + + Then break it into groups of eight bits (one byte units). There are + three bytes with ones (bits set), two with all zeros: + + 00001000 = 8 + 00000000 = 0 + 00000010 = 2 + 00100001 = 33 + 00000000 = 0 + + Converting these to decimal, we get the values listed at the right + of each byte. These are the numbers you'd POKE into locations + 675 (the first byte) to 679 (the fifth byte on the line). On powerup + or when you OPEN the display screen (S: or E:), each byte is + given a value of one (i.e., 00000001) so that there are tab default + tab stops at 7, 15, 23, etc., incrementing by eight to 119. Also, + the leftmost screen edge is also a valid TAB stop (2, 42, and 82). + In BASIC, these are set by the SET-TAB and CLR-TAB keys. + TABMAP also works for the lines in the text display window in + split-screen formats. TABMAP is reset to the default values on + pressing RESET or changing GRAPHICS modes. + See location 201 ($C9) about changing the TAB settings used + when a PRINT statement encounters a comma. + + + 690-693 2B2-2B5 LOGMAP + + Logical line start bit map. These locations map the beginning + physical line number for each logical line on the screen (initially + 24, for GR.0). Each bit in the first three bytes shows the start of a + logical line if the bit equals one (three bytes equals eight bits * + three equals 24 lines on the screen). The map format is as follows: + + Bit 7 6 5 4 3 2 1 0 Byte + ------------------------------------------------------------ + Line 0 1 2 3 4 5 6 7 690 + 8 9 10 11 12 13 14 15 691 + 16 17 18 19 20 21 22 23 692 + -- -- -- -- -- -- -- -- 693 + + The last byte is ignored. The map bits are all set to one when the + text screen is OPENed or CLEARed, when a GRAPHICS com- + mand is issued or RESET is pressed. The map is updated as + logical lines are entered, edited, or deleted. + + + 694 2B6 INVFLG + + Inverse character flag; zero is normal and the initialization value + (i.e., normal ATASCII video codes have BIT 7 equals zero). You + POKE INVFLG with 128 ($80) to get inverse characters (BIT 7 + equals one). This register is normally set by toggling the Atari + logo key; however, it can be user-altered. The display handler + XOR's the ATASCII codes with the value in INVFLG at all times. + See location 702 ($2BE) below. + + INVFLG works to change the input, not the output. For example, + if you have A$ = "HELLO", POKE 694, 128 will not change A$ + when you PRINT it to the screen. However, if you POKE 694, 128 + before an INPUT A$, the string will be entered as inverse. + + + 695 2B7 FILFLG + + Right fill flag for the DRAW command. If the current operation is + a DRAW, then this register reads zero. If it is non-zero, the + operation is a FILL. + + + 696 2B8 TMPROW + + Temporary register for row used by ROWCRS (location 84; $54). + + + 697,698 2B9,2BA TMPCOL + + Temporary register for column used by COLCRS (locations 85, + 86; $55, $56). + + + 699 2BB SCRFLG + + Scroll flag; set if a scroll occurs. It counts the number of physical + lines minus one that were deleted from the top of the screen. This + moves the entire screen up one physical line for each line + scrolled off the top. Since a logical line has three physical lines, + SCRFLG ranges from zero to two. + + Scrolling the text window is the equivalent to scrolling an entire + GR.0 screen. An additional 20-line equivalent of bytes (800) is + scrolled upwards in the memory below the text window address. + This can play havoc with any data such as P/M graphics you have + stored above RAMTOP + + + 700 2BC HOLD4 + + Temporary register used in the DRAW command only; used to + save and restore the value in ATACHR (location 763; $2FB) + during the FILL process. + + + 701 2BD HOLD5 + + Same as the above register. + + + 702 2BE SHFLOK + + Flag for the shift and control keys. It returns zero for lowercase + letters, 64 ($40) for all uppercase (called caps lock: uppercase is + required for BASIC statements and is also the default mode on + powerup). SHFLOK will set characters to all caps during your + program if 64 is POKEd here. Returns the value 128 ($80; + control-lock) when the CTRL key is pressed. Forced control-lock + will cause all keys to output their control-code functions or + graphics figures. Other values POKEd here may cause the + system to crash. You can use this location with 694 ($2B6) above + to convert all keyboard entries to uppercase, normal display by: + + 10 OPEN #2,4,0,"K:" + 20 GET #2,A + 30 GOSUB 1000 + 40 PRINT CHR$(A);: GOTO 20 + . + . + . + 1000 IF A = 155 THEN 1030: REM RETURN + KEY + 1010 IF A > = 128 THEN A = A - 128: R + EM RESTORE TO NORMAL DISPLAY + 1020 IF PEEK (702) = 0 AND A > 96 THEN + A = A - 32: REM LOWERCASE TO UP + PER + 1030 POKE 702,64: POKE 694,0 + 1040 RETURN + + DOWNLOAD SHFLOK.BAS + + + 703 2BF BOTSCR + + Flag for the number of text rows available for printing. 24 ($18) is + normal for text mode GR.0; four for the text window, zero for all + graphics modes. In all GRAPHICS modes except zero, if there is + no text window then 703 will also read zero. The large-text + displays in GR.1 and GR.2 are treated as graphics displays for + this purpose. The display handler specifically checks for split- + screen mode by looking for the variable 24 or four here. If it finds + 24 here, it assumes there is no text window; if not, it looks for the + variable four. + + You can add a text window to GR.0 by POKEing here with four. + The top portion (20 lines) of the screen will not scroll with the + bottom. To write to the top part of the screen you will have to use + the PRINT#6 statement as with modes one and two. One possible + application of this would be to keep a fixed menu at the top of the + screen while scrolling the bottom part, as done with the DOS + menu. + + --------------------------------------------------------------------------- + Locations 704 to 712 ($2C0 to $2C8) are the color registers for players, + missiles, and playfields. These are the RAM shadow registers for + locations 53266 to 53274 ($D012 to $D01A). For the latter, you can use + the SETCOLOR command from BASIC. For all registers you can + POKE the desired color into the location by using this formula: + + COLOR = HUE * 16 + LUMINANCE + + It is possible to get more colors in GR.8 than the one (and a half) that + Atari says is possible by using a technique called artifacting. There is a + small example of artifacting shown at location 710 ($2C6). See De Re + Atari, Your Atari 400/800, Creative Computing, June 1981, and + COMPUTE!, May 1982. + + Here are the 16 colors the Atari produces, along with their POKE + values for the color registers. The POKE values assume a luminance of + zero. Add the luminance value to the numbers to brighten the color. + The color registers ignore BIT 0; that's why there are no "odd" values + for luminance, just even values. + + Color Value Color Value + Black 0, 0 Medium blue 8, 128 + Rust 1, 16 Dark blue 9, 144 + Red-orange 2, 32 Blue-grey 10, 160 + Dark orange 3, 48 Olive green 11, 176 + Red 4, 64 Medium green 12, 192 + Dk lavender 5, 80 Dark green 13, 208 + Cobalt blue 6, 96 Orange-green 14, 224 + Ultramarine 7, 112 Orange 15, 240 + + The bit use of the PCOLR and COLOR registers is as follows: + + Bit 7 6 5 4 3 2 1 0 + --color-- luminance unused + Grey 0 0 0 0 0 0 0 Darkest + Rust 0 0 0 1 0 0 1 + etc. to: etc. to: + Orange 1 1 1 1 1 1 1 Lightest + + When you enable the color overlap at location 623 ($26F), ANTIC + performs a logical OR on the overlap areas. For example: + + 01000010 Red, luminance two + OR 10011010 Darkblue,luminance ten + -------- + Result = 10011010 Dark green, luminance ten + + Here's a short machine language routine which will rotate the colors in + registers 705 to 712: + + 10 DIM ROT$(30) + 20 FOR LOOP = 1 TO 27: READ BYTE: R + OT$(LOOP,LOOP) = CHR$(BYTE): NEXT + LOOP + . + . PUT YOUR GRAPHICS ROUTINE HERE + . + 100 CHANGE = USR(ADR(ROT$)) + 105 FOR LOOP = 1 TO 200: NEXT LOOP: + GOTO 100 + 110 DATA 104,162,0,172,193,2,189,194 + ,2,157 + 120 DATA 193,2,232,224,8,144,245,140 + ,200,2 + 130 DATA 96,65,65,65,65,65,65 + + If you wish to rotate the colors in registers 704 to 711 instead, change + lines 110 and 120 to read as follows: + + 110 DATA 104,162,0,172,192,2,189,193 + ,2,157 + 120 DATA 192,2,232,224,8,144,245,140 + ,199,2 + + DOWNLOAD BOTSCR.BAS + + If you wish to include all of the registers 704 to 712 in the routine, make + the changes as above and change the eight in line 120 to nine and + restore the 199 to 200 in line 120. This routine works well with the + GTIA demos at location 623 ($26F). + + For further detail, refer to your Atari BASIC Reference Manual, pp. 45 + -56, and the GTIA Demo Disk from APX. + + + 704 2C0 PCOLR0 + + Color of player 0 and missile 0. Locations 704 to 707 are also + called COLPM# in some sources. This is the shadow for 53266 + ($D012). In GTIA mode ten, 704 holds the background color + (BAK; normally held by 712). You cannot use the SETCOLOR + commands to change the PCOLR registers; color values must be + POKEd into them. + + + 705 2C1 PCOLR1 + + Color of player and missile 1. Shadow for 53267 ($D013). + + + 706 2C2 PCOLR2 + + Color of player and missile 2. Shadow for 53268 ($D014). + + + 707 2C3 PCOLR3 + + Color of player and missile 3. When the four missiles are + combined to make a fifth player, it takes on the color in location + 711 (COLOR3). Shadow for 53269 ($D015). + + + 708 2C4 COLOR0 + + Color register zero, color of playfield zero, controlled by the + BASIC SETCOLOR0 command. In GRAPHICS 1 and + GRAPHICS 2, this color is used for the uppercase letters. + Shadow for 53270 ($D016). You can change the values in all of + the COLOR registers from BASIC by using either the + SETCOLOR command or a POKE. + + + 709 2C5 COLOR1 + + The next four locations are the same as location 708 for the + different playfields and SETCOLOB commands. In GR.1 and + GR.2, this register stores the color for lowercase letters. + COLOR1 is also used to store the luminance value of the color + used in GR.0 and GR.8. Shadow for 53271 ($D017). + + + 710 2C6 COLOR2 + + The same as above for playfield two; in GR.1 and GR.2, this + register stores the color of the inverse uppercase letters. Shadow + for 53272 ($D018). Used for the background color in GR.0 and + GR.8. Both use COLOR1 for the luminance value. + + Despite the official limitations of color selection in GR.8, it is + possible to generate additional colors by "artifacting", turning + on specific pixels (.5 color clock each) on the screen. Taking + advantage of the physical structure of the TV set itself, we + selectively turn on vertical lines of pixels which all show the same + color. For example: + + 10 A = 40: B = 30: C = 70: D = 5: F + = 20 GRAPHICS 8: POKE 87,7: P0K + E 710,0: POKE 709,15: COLOR 1 + 30 PLOT A,D: DRAWTO A,C: COLOR 2: P + LOT F,D: DRAWTO F,C: + 40 PLOT A + 1,D: DRAWTO A + 1,C + 50 COLOR 3: PLOT B,D: DRAWTO B,C + 60 GOTO 60 + + DOWNLOAD COLOR2.BAS + + A little experimentation with this will show you that the colors + obtained depend on which pixels are turned on and how close + together the pixel columns are. There are four "colors" you can + obtain, as shown before. Pixels marked one are on; marked zero + means they are off. Each pair of pixels is one color clock. Three + color clocks are shown together for clarity: + + 00:01:00 = color A 00:11:00 = color B + 00:10:00 = color C 00:01:10 = color D + + See BYTE, May 1982, De Re Atari, and Your Atari 400/800. + + + 711 2C7 COLOR3 + + The same as the above but for playfield three. Also, the color for + GR.1 and GR.2 inverse lowercase letters. Shadow for 53273 + ($D019). + + + 712 2C8 COLOR4 + + The same as the above but for the background (BAK) and border + color. Shadow for 53274 ($D01A). In GTIA mode ten, 704 stores + the background color (BAK), while 712 becomes a normal color + register. + + Here are the default (powerup) values for the COLOR registers + (PCOL registers are all set to zero on powerup): + + Register Color = Hue Luminance + 708 (CO.0) 40 2 8 + 709 (CO.1) 202 12 10 + 710 (CO.2) 148 9 4 + 711 (CO.3) 70 4 6 + 712 (CO.4) 0 0 0 + + ---------------------------------------------------------------------------- + Locations 713 to 735 ($2C9 to $2DF) are spare bytes. Locations 736 to + 767 ($2E0 to $2FF) are for miscellaneous use. + + + 736-739 2E0-2E3 GLBABS + + Global variables, or, four spare bytes for non DOS users. For + DOS users they are used as below: + + + 736-737 2E0-2E1 RUNAD + + Used by DOS for the run address read from the disk sector one or + from a binary file. Upon completion of any binary load, control + will normally be passed back to the DOS menu. However, DOS + can be forced to pass control to any specific address by storing + that address here. If RUNAD is set to 40960 ($A000), then the left + cartridge (BASIC if inserted) will be called when the program is + booted. + + With DOS 1.0, if you POKE the address of your binary load file + here, the file will be automatically run upon using the DOS + Binary Load (selection L). Using DOS 1.0's append (/A) option + when saving a binary file to disk, you can cause the load address + POKEd here to be saved with the data. In DOS 2.0, you may + specify the initialization and the run address with the program + name when you save it to disk (i.e., + GAME.OBJ,2000,4FFF,4F00,4000). DOS 2.0 uses the /A option + to merge files. In order to prevent your binary files from running + automatically upon loading in DOS 2.0, use the /N appendage to + the file name when loading the file. + + For users of CompuServe, there is an excellent little BASIC + program (with machine language subroutines) to create autoboot + files, chain machine language files with BASIC and to add an 850 + autoboot file in the Popular Electronics Magazine (PEM) access + area. It is available free for downloading. + + + 738-739 2E2-2E3 INITAD + + Initialization address read from the disk. An autoboot file must + load an address value into either RUNAD above or INITAD. The + code pointed to by INITAD will be run as soon as that location is + loaded. The code pointed to by RUNAD will be executed only + after the entire load process has been completed. To return + control to DOS after the execution of your program, end your + code with an RTS instruction. + + + 740 2E4 RAMSIZ + + RAM size, high byte only; this is the number of pages that the top + of RAM represents (one page equals 256 bytes). Since there can + never be less than a whole page, it becomes practical to measure + RAM in those page units. This is the same value as in RAMTOP, + location 106 ($6A), passed here from TRAMSZ, location 6. Space + saved by moving RAMSIZ or RAMTOP has the advantage of + being above the display area. Initialized to 160 for a 48K Atari. + + + 741,742 2E5,2E6 MEMTOP + + Pointer to the top of free memory used by both BASIC (which + calls it HIMEM) and the OS, passed here from TRAMSZ, location + 6 after powerup. This address is the highest free location in RAM + for programs and data. The value is updated on powerup, when + RESET is pressed, when you change GRAPHICS mode, or when + a channel (IOCB) is OPENed to the display. The display list starts + at the next byte above MEMTOP. + + The screen handler will only OPEN the S: device if no RAM is + needed below this value (i.e. there is enough free RAM below + here to accommodate the requested GRAPHICS mode change). + Memory above this address is used for the display list and the + screen display RAM. Also, if a screen mode change would + extend the screen mode memory below APPMHI (locations 14, + 15: $E, $F), then the screen is set back for GR.0, MEMTOP is + updated, and an error is returned to the user. Otherwise the + mode change will take place and MEMTOP will be updated. + + Space saved by moving MEMTOP is below the display list. Be + careful not to overwrite it if you change GRAPHICS modes in + mid-program. When using memory below MEMTOP for storage, + make sure to set APPMHI above your data to avoid having the + screen data descend into it and destroy it. + + + 743,744 2E7,2E8 MEMLO + + Pointer to the bottom of free memory, initialized to 1792 ($700) + and updated by the presence of DOS or any other low-memory + application program. It is used by the OS; the BASIC pointer to + the bottom of free memory is at locations 128, 129 ($80, $81). The + value in MEMLO is never altered by the OS after powerup. + + This is the address of the first free location in RAM available for + program use. Set after all FMS buffers have been allocated (see + locations 1801 and 1802; $709 and $70A). The address of the last + sector buffer is incremented by 128 (the buffer size in bytes) and + the value placed in MEMLO. The value updates on powerup or + when RESET is pressed. This value is passed back to locations + 128, 129 ($80, $81) on the execution of the BASIC NEW + command, but not RUN, LOAD or RESET. + + If you are reserving space for your own device driver(s) or + reserving buffer space, you load your routine into the address + specified by MEMLO, add the size of your routine to the MEMLO + value, and POKE the new value plus one back into MEMLO. + + When you don't have DOS or any other application program + using low-memory resident, MEMLO points to 1792 ($700. With + DOS 2.0 present, MEMLO points to 7420 ($1CFC). If you change + the buffer defaults mentioned earlier, you will raise or lower this + latter value by 128 ($80) bytes for every buffer added or deleted, + respectively. When you boot up the 850 Interface with or without + disk, you add another 1728 ($6C0) bytes to the value in MEMLO. + + You can alter MEMLO to protect an area of memory below your + program. This is an alternative to protecting an area above + RAMTOP (location 106; $6A) and avoids the problem of the + CLEAR SCREEN routine destroying data. However, unless you + have created a MEM.SAV file, the data will be wiped out when + you call DOS. To alter MEMLO, you start by POKEing WARMST + (location 8) with zero, then doing a JMP to the BASIC cartridge + entry point at 40960($A000) after defining your area to protect. + For example, try this: + + 10 DIM MEM$(24):PROTECT=700:REM NUMBE + R OF BYTES TO CHANGE + 15 HIBYTE=INT(PROTECT/256):LOBYTE=PRO + TECT-256*HIBYTE + 20 FOR N=1 TO 24:READ PRG:MEM$(N)=CHR + $(PRG):NEXT N + 30 MEM$(6,6)=CHR$(LOBYTE):MEM$(14,14) + =CHR$(HIBYTE) + 40 RESERVE=USR(ADR(MEM$)) + 50 DATA 24,173,231,2,105,0,141,231,2, + 173,232,2,105 + 60 DATA 0,141,232,2,169,0,133,8,76,0, + 160 + + DOWNLOAD MEMLO.BAS + + You will find the address of your reserved memory by: PRINT + PEEK(743) + PEEK(744) * 256 before you run the program. This + program will wipe itself out when run. Altering MEMLO is the + method used by both DOS and the RS-232 port driver in the 850 + Interface. See COMPUTE!, July 1981. + + + 745 2E9 .... + + Spare byte. + + + 746-749 2EA-2ED DVSTAT + + Four device status registers used by the I/O status operation as + follows: + + 746 ($2EA) is the device error status and the command status + byte. If the operation is a disk I/O, then the status returned is that + of the 1771 controller chip in your Atari disk drive. Bits set to one + return the following error codes: + + Bit Decimal Error + 0 1 An invalid command frame was received (error). + 1 2 An invalid data frame was received. + 2 4 An output operation was unsuccessful. + 3 8 The disk is write-protected. + 4 16 The system is inactive (on standby). + 7 32 The peripheral controller is "intelligent" (has its + own microprocessor: the disk drive). All Atari + devices are intelligent except the cassette + recorder, so BIT 7 will normally be one when a + device is attached. + + 747 ($2EB) is the device status byte. For the disk, it holds the + value of the status register of the drive controller. For the 850 + Interface, it holds the status for DSR,CTS,CRX and RCV when + concurrent I/O is not active (see the 850 Interface Manual). It also + contains the AUX2 byte value from the previous operation (see + the IOCB description at 832 to 959; $340 to $3AF). + 748 ($2EC) is the maximum device time-out value in seconds. A + value of 60 here represents 64 seconds. This value is passed back + to location 582 ($246) after every disk status request. Initialized to + 31. + 749 ($2ED) is used for number of bytes in output buffer. See 850 + Manual, p. 43. + When concurrent I/O is active, the STATUS command returns + the number of characters in the input buffer to locations 747 and + 748, and the number of characters in the output buffer to location + 749. + + + 750,751 2EE,2EF CBAUDL/H + + Cassette baud rate low and high bytes. Initialized to 1484 + ($5CC), which represents a nominal 600 baud (bits per second). + After baud rate calculations, these locations will contain POKEY + values for the corrected baud rate. The baud rate is adjusted by + SIO to account for motor variations, tape stretch, etc. The + beginning of every cassette record contains a pattern of + alternating off/on bits (zero/one) which are used solely for speed + (baud) correction. + + + 752 2F0 CRSINH + + Cursor inhibit flag. Zero turns the cursor on; any other number + turns the cursor off. A visible cursor is an inverse blank (space) + character. Note that cursor visibility does not change until the + next time the cursor moves (if changed during a program). If you + wish to change the cursor status without altering the screen data, + follow your CRSINH change with a cursor movement (i.e., up, + down) sequence. This register is set to zero (cursor restored) on + powerup, RESET, BREAK, or an OPEN command to either the + display handler (S:) or screen editor (E:). See location 755 for + another means to turn off the cursor. + + + 753 2F1 KEYDEL + + Key delay flag or key debounce counter; used to see if any key + has been pressed. If a zero is returned, then no key has been + pressed. If three is returned, then any key. It is decremented + every stage two VBLANK (1/60 or 1/30th second) until it reaches + zero. If any key is pressed while KEYDEL is greater than zero, it + is ignored as "bounce." See COMPUTE!, December 1981, for a + routine to change the keyboard delay to suit your own typing + needs. + + + 754 2F2 CH1 + + Prior keyboard character code (most recently read and + accepted). This is the previous value passed from 764 ($2FC). If + the value of the new key code equals the value in CH1, then the + code is accepted only if a suitable key debounce delay has taken + place since the prior value was accepted. + + + 755 2F3 CHACT + + Character Mode Register. Zero means normal inverse + characters, one is blank inverse characters (inverse characters + will be printed as blanks, i.e., invisible), two is normal + characters, three is solid inverse characters. Four to seven is the + same as zero to three, but prints the display upside down. + This register also controls the transparency of the cursor. It is + transparent with values two and six, opaque with values three + and seven. The cursor is absent with values zero, one, four and + five. + + Toggling BIT 0 on and off can be a handy way to produce a + blinking effect for printed inverse characters (characters with + ATASCII values greater than 128 -- those that have BIT 7 set). + Shadow for 54273 ($D401). There is no visible cursor for the + graphics mode output. CHACT is initialized to two. + Here's an example of blinking text using this register: + + 10 CHACT=755:REM USE INVERSE FOR WORD + S BELOW + 15 PRINT "[THIS IS A TEST OF BLINKING ] + [TEXT]" + 20 POKE CHACT,INT(RND(0)*4) + 30 FOR N=1 TO 100:NEXT N:GOTO 15 + + See COMPUTE!, December 1981. + Using a machine language routine and page six space, try: + + 10 PAGE=1536:EXIT=1568 + 20 FOR N=PAGE TO EXIT:READ BYTE:POKE + N,BYTE:NEXT N + 30 PGM=USR(PAGE) + 40 PRINT "[THIS] IS A [TEST] OF [BLINKING] + TEXT":REM MAKE SOME WORDS INVERSE + 50 GOTO 50 + 60 DATA 104,169,17,141,40,2,169,6,141 + ,41 + 70 DATA 2,169,30,141,26,2,98,173,243, + 2 + 80 DATA 41,1,73,1,141,243,2,169,30,14 + 1,26,2,96 + + DOWNLOAD CHACT.BAS + + The blink frequency is set .5 second; to change it, change the + 30 in line 80 to any number from one (1/30 second) to 255 (eight + .5 seconds). For another way to make the cursor visible or + invisible, see locations 752 above. + + + 756 2F4 CHBAS + + Character Base Register, shadow for 54281 ($D409). The default + (initialization value) is 224 ($E0) for uppercase characters and + numbers; POKE CHBAS with 226 ($E2) to get the lowercase and + the graphics characters in GR.1 and GR.2. In GR.0 you get the + entire set displayed to the screen, but in GR.1 and GR.2, you + must POKE 756 for the appropriate half-set to be displayed. + + How do you create an altered character set? First you must + reserve an area in memory for your set (512 or 1024 bytes; look at + location 106; $6A to see how). Then either you move the ROM set + (or half set, if that's all you intend to change) into that area and + alter the selected characters, or you fill up the space with bytes + which make up your own set. Then you POKE 756 with the MSB + of the location of your set so the computer knows where to find it. + + What does an altered character set look like? Each character is a + block one byte wide by eight bytes high. You set the bits for the + points on the screen you wish to be "on" when displayed. Here + are two examples: + + one byte wide: + 00100000 = 32 # + 00010000 = 16 # + 00010000 = 16 # + 00010000 = 16 # + 00011110 = 30 #### + 00000010 = 2 # + 00001100 = 12 ## + 00010000 = 16 # + + Hebrew letter Lamed + + + one byte wide: + 10000001 = 129 # # + 10011001 = 153 # ## # + 10111101 = 189 # #### # + 11111111 = 255 ######## + 11111111 = 255 ######## + 10111101 = 189 # #### # + 10011001 = 153 # ## # + 10000001 = 129 # # + + Tie-fighter + + You can turn these characters into DATA statements to be POKEd + into your reserved area by using the values for the bytes as in the + above examples. To change the ROM set once it is moved, you + look at the internal code (see the BASIC Reference Manual, p. + 55) and find the value of the letter you want to replace--such as + the letter A--code 33. Multiply this by eight bytes for each code + number from the start of the set (33 * eight equals 264). You then + replace the eight bytes used by the letter A, using a FOR-NEXT + loop with the values for your own character. For example, add + these lines to the machine language found a few pages further on: + + 1000 FOR LOOP=1 TO 4:READ CHAR:SET=CH + ACT+CHAR*8 + 1010 FOR TIME=0 TO 7:READ BYTE:POKE S + ET+TIME,BYTE: NEXT TIME + 1020 NEXT LOOP + 1030 DATA 33,0,120,124,22,22,124,120, + 0 + 1040 DATA 34,0,126,82,82,82,108,0,0 + 1050 DATA 35,56,84,254,238,254,68,56, + 0 + 1060 DATA 36,100,84,76,0,48,72,72,48 + 2000 END + + RUN it and type the letters A to D. + Why 224 and 226? Translated to hex, these values are $E0 and + $E2, respectively. These are the high bytes (MSB) for the location + of the character set stored in ROM: $E000 (57344) is the address + for the start of the set (which begins with punctuation, numbers + and uppercase letters), and $E200 (57856), for the second half of + the ROM set, lowercase and graphic control characters (both + start on page boundaries). The ROM set uses the internal order + given on page 55 of your BASIC Reference Manual, not the + ATASCII order. See also location 57344 ($E000). + + You will notice that using the PRINT#6 command will show you + that your characters have more than one color available to them + in GR.1 and GR.2. Try PRINTing lowercase or inverse + characters when you are using the uppercase set. This effect can + be very useful in creating colorful text pages. Uppercase letters, + numbers, and special characters use color register zero (location + 708; $2C4 - orange) for normal display, and color register two + (710; $2C6 - blue) for inverse display. Lowercase letters use + register one (709; $2C5 - aqua) for normal display and register + three (711; $2C7 - pink) for inverse. See COMPUTE!, December + 1981, page 98, for a discussion of using the CTRL keys with letter + keys to get different color effects. + + One problem with POKEing 756 with 226 is that there is no blank + space character in the second set: you get a screen full of hearts. + You have two choices: you can change the color of register zero + to the same as the background and lose those characters which + use register zero--the control characters--but get your blanks + (and you still have registers one, two and three left). Or you can + redefine your own set with a blank character in it. The latter is + obviously more work. See "Ask The Readers," COMPUTE!, July + 1982. + + It is seldom mentioned in the manuals, but you cannot set 756 to + 225 ($El) or any other odd number. Doing so will only give you + screen garbage. The page number 756 points to must be evenly + divisible by two. + + When you create your own character set and store it in memory, + you need to reserve at least 1K for a full character set (1024 bytes + --$400 or four pages), and you must begin on a page boundary. + In hex these are the numbers ending with $XX00 such as $C000 + or $600 because you store the pointer to your set here in 756; it + can only hold the MSB of the address and assumes that the LSB is + always zero--or rather a page boundary. You can reserve + memory by: + + POKE 106,PEEK(106)-4 (or any multiple of four) + + And do a GRAPHICS command immediately after to have your + new memory value accepted by the computer. If you are using + only one half of the entire set, for GR.1 or GR.2, you need only + reserve 512 bytes, and it may begin on a .5K boundary (like + $E200; these are hexadecimal memory locations that end in + $X200). If you plan to switch to different character sets, you will + need to reserve the full 1K or more, according to the number of + different character sets you need to display. RAM for half-K sets + can be reserved by: + + POKE 106,PEEK(106)-2 (or a multiple of two) + + The location for your set will then begin at PEEK(106)*256. + Because BASIC cannot always handle setting up a display list for + GR.7 and GR.8 when you modify location 106 by less than 4K (16 + pages), you may find you must use PEEK(106)-16. See location + 88,89 ($58,$59) and 54279 ($D407) for information regarding + screen use and reserving memory. + + Make sure you don't have your character set overlap with your + player/missile graphics. Be very careful when using altered + character sets in high memory. Changing GRAPHICS modes, a + CLEAR command, or scrolling the text window all clear memory + past the screen display. When you scroll the text window, you + don't simply scroll the four lines; you actually scroll a full 24 (20 + additional lines * 40 bytes equals 800 bytes scrolled past + memory)! This messes up the memory past the window display + address, so position your character sets below all possible + interference (or don't scroll or clear the screen). + + You can create and store as many character sets as your memory + will allow. You switch back and forth between them and the ROM + set by simply POKEing the MSB of the address into 756. Of + course, you can display only one set at a time unless you use an + altered display list and DLI to call up other sets. There are no + restrictions outside of memory requirements on using altered + character sets with P/M graphics as long as the areas reserved for + them do not overlap. + + A GRAPHICS command such as GR.0, RESET or a DOS call + restores the character set pointer to the ROM location, so you + must always POKE it again with the correct location of your new + set after any such command. A useful place to store these sets is + one page after the end of RAM, assuming you've gone back to + location 106 ($6A) and subtracted the correct number of pages + from the value it holds (by POKE 106,PEEK(106) minus the + number of pages to be reserved; see above). Then you can reset + the character set location by simply using POKE + 756,PEEK(106)+1 (the plus one simply makes sure you start at + the first byte of your set). + + A full character set requires 1024 bytes (1K: four pages) be + reserved for it. Why? Because there are 128 characters, each + represented by eight bytes, so 128 * eight equals 1024. If you are + using a graphics mode that uses only half the character set, you + need only reserve 512 bytes (64 * eight equals 512). Remember to + begin either one on a page boundary (1K boundary for full sets or + .5K for half sets). By switching back and forth between two + character sets, you could create the illusion of animation. + + Many magazines have published good utilities to aid in the + design of altered character sets, such as the January 1982 + Creative Computing, and SuperFont in COMPUTE!, January + 1982. I suggest that you examine The Next Step from Online, + Instedit from APX, or FontEdit from the Code Works for very + useful set generators. One potentially useful way to alter just a + few of the characters is to duplicate the block of memory which + holds the ROM set by moving it byte by byte into RAM. A BASIC + FOR-NEXT loop can accomplish this, although it's very slow. For + example: + + 5 CH=57344 + 10 START=PEEK(106)-4:PLACE=START*256: + POKE 106,PEEK(106)-5:GRAPHICS 0: RE + M RESERVE EXTRA IN CASE OF SCREEN + CLEAR + 20 FOR LOOP=0 TO 1023:POKE PLACE+LOOP + ,PEEK(CH+LOOP):NEXT LOOP:REM MOVE + THE ROM SET + 30 POKE 756,PLACE/256:REM TELL ANTIC + WHERE CHSET IS + + Here's a machine language routine to move the set: + + 10 DIM BYTE$(80) + 15 REM MEM-1 TO PROTECT SET FROM CLEA + R SCREEN DESTRUCTION (SEE LOC.88) + 20 MEM=PEEK(106)-4:POKE 106,MEM-1: CHA + CT=MEM*256:GRAPHICS 0 + 30 FOR LOOP=1 TO 32:READ PGM:BYTE$(LO + OP,LOOP)=CHR$(PGM):NEXT LOOP + 40 DATA 104,104,133,213,104,133,212 + 50 DATA 104,133,215,104,133,214,162 + 60 DATA 4,160,0,177,212,145,214 + 70 DATA 200,208,249,230,213,230,215 + 80 DATA 202,208,240,96 + 90 Z=USR(ADR(BYTE$),224*256,CHACT) + . + . ADD YOUR OWN ALTERATION PROGRAM OR + THE EARLIER EXAMPLE HERE + . + . + 1500 POKE MEM-1,0:POKE 756,MEM + + If you have Microsoft BASIC or BASIC A+, you can do this very + easily with the MOVE command! + + Remember, when altering the ROM set, that the characters aren't + in ATASCII order; rather they are in their own internal order. + Your own set will have to follow this order if you wish to have the + characters correlate to the keyboard and the ATASCII values. + See page 55 of your BASIC Reference Manual for a listing of the + internal order. Creative Computing, January 1982, had a good + article on character sets, as well as a useful method of + transferring the ROM set to RAM using string manipulation. See + also "Using Text Plot for Animated Games" in COMPUTE!, April + 1982, for an example of using character sets for animated + graphics. + + + 757-761 2F5-2F9 .... + + Spare bytes. + + + 762 2FA CHAR + + Internal code value for the most recent character read or written + (internal code for the value in ATACHR below). This register is + difficult to use with PEEK statements since it returns the most + recent character; most often the cursor value (128, $80 for a + visible, zero for an invisible cursor). + + + 763 2FB ATACHR + + Returns the last ATASCII character read or written or the value of + a graphics point. ATACHR is used in converting the ATASCII + code to the internal character code passed to or from CIO. It also + returns the value of the graphics point. The FILL and DRAW + commands use this location for the color of the line drawn, + ATACHR being temporarily loaded with the value in FILDAT, + location 765; $2FD. To force a color change in the line, POKE the + desired color number here (color * sixteen + luminance). To see + this register in use as character storage, try: + + 10 OPEN#2,4,0,"K:" + 20 GET#2,A + 30 PRINT PEEK(763);" "; CHR$(A) + 40 GOTO 20 + + Make sure the PEEK statement comes before the PRINT CHR$ + statement, or you will not get the proper value returned. When + the RETURN key is the last key pressed, ATACHR will show a + value of 155. + + + 764 2FC CH + + Internal hardware value for the last key pressed. POKE CH with + 255 ($FF; no key pressed) to clear it. The keyboard handler gets + all of its key data from CH. It stores the value 255 here to indicate + the key code has been accepted, then passes the code to CH1, + location 754 ($2F2). If the value in CH is the same as in CH1, a + key code will be accepted only if the proper key debounce delay + time has transpired. If the code is the CTRL-1 combination (the + CTRL and the "1" keys pressed simultaneously), then the + start/stop flag at 767 ($2FF) is complemented, but the value is not + stored in CH. The auto repeat logic will also store store key + information here as a result of the continuous pressing of a key. + This is neither the ATASCII nor the internal code value; it is the + "raw" keyboard matrix code for the key pressed. The table for + translation of this code to ATASCII is on page 50 of the OS User's + Manual. In a two-key operation, BIT 7 is set if the CTRL key is + pressed, BIT 6 if the SHIFT key is pressed. The rest of the bytes + are the code (ignored if both BITs 7 and 6 are set). Only the code + for the last key pressed is stored here (it is a global variable for + keyboard). + + When a read request is issued to the keyboard, CH is set to 255 + by the handler routine. After a keycode has been read from this + register, it is reset to 255. BREAK doesn't show here, and CTRL + and SHIFT will not show here on their own. However, the inverse + toggle (Atari logo key), CAPS/LOWR, TAB and the ESC keys + will show by themselves. You can examine this register with: + + 10 LOOK=PEEK(764) + 20 PRINT "KEY PRESSED = ";LOOK + 30 POKE 764,255 + 40 FOR LOOP=1 TO 250:NEXT LOOP + 50 GOTO 10 + + See COMPUTE!'s First Book of Atari for an example of using this + register as a replacement for joystick input. + + + 765 2FD FILDAT + + Color data for the fill region in the XIO FILL command. + + + 766 2FE DSPFLG + + Display flag, used in displaying the control codes not associated + with an ESC character (see location 674; $2A2). If zero is + returned or POKEd here, then the ATASCII codes 27 - 31, 123 - + 127, 187 - 191 and 251 - 255 perform their normal display screen + control functions (i.e., clear screen, cursor movement, + delete/insert line, etc.). If any other number is returned, then a + control character is displayed (as in pressing the ESC key with + CTRL-CLEAR for a graphic representation of a screen clear). + POKEing any positive number here will force the display instead + of the control code action. There is, however, a small bug, not + associated with location 766, in Atari BASIC: a PRINTed CTRL-R + or CTRL-U are both treated as a semicolon. + + + 767 2FF SSFLAG + + Start/stop display screen flag, used to stop the scrolling of the + screen during a DRAW or graphics routine, a LISTing or a + PRINTing. When the value is zero, the screen output is not + stopped. When the value is 255 ($FF; the one's complement), the + output to the screen is stopped, and the machine waits for the + value to become zero again before continuing with the scrolling + display. Normally SSFLAG is toggled by the user during these + operations by pressing the CTRL-1 keys combination to both start + and stop the scroll. Set to zero by RESET and powerup. + + --------------------------------------------------------------------------- + + PAGE THREE + + Locations 768 to 831 ($300 to $33F) are used for the device handler and + vectors to the handler routines (devices S:, P:, E:, D:, C:, R: and K:). + A device handler is a routine used by the OS to control the transfer of + data in that particular device for the task allotted (such as read, write, + save, etc.). The resident D: handler does not conform entirely with the + other handler--SIO calling routines. Instead, you use the DCB to + communicate directly with the disk handler. The device handler for R: + is loaded in from the 850 interface module. See De Re Atari, the 850 + Interface Manual, and the OS Listings pages 64 - 65. + + Locations 768 to 779 ($300 to $30B) are the resident Device Control + Block (DCB) addresses, used for I/O operations that require the serial + bus; also used as the disk DCB. DUP.SYS uses this block to interface + the FMS with the disk handler. The Atari disk drive uses a serial access + at 19,200 baud (about 20 times slower than the Apple!). It has its own + microprocessor, a 6507, plus 128 bytes of RAM, a 2316 2K masked + ROM chip (like a 2716), a 2332 RAM-I/O timer chip with another 128 + bytes of RAM (like the PIA chip) and a WD 1771 FD controller chip. + See the "Outpost Atari" column, Creative Computing, May 1982, for + an example of using the disk DCB. + + All of the parameters passed to SIO are contained in the DCB. SIO + uses the DCB information and returns the status in the DCB for + subsequent use by the device handler. + + + 768 300 DDEVIC + + Device serial bus ID (serial device type) set up by the handler, + not user-alterable. Values are: + + Disk drives Dl - D4 49-52 ($31-$34) + Printer P1 64 ($40) + Printer P2 79 ($4F) + RS232 ports R1-R4 80-83 ($50-$53) + + + 769 301 DUNIT + + Disk or device unit number: one to four, set up by the user. + + + 770 302 DCOMND + + The number of the disk or device operation (command) to be + performed, set by the user or by the device handler prior to + calling SIO. Serial bus commands are: + + Read 82 ($52) + Write (verily) 87 ($57) + Status 83 ($53) + Put (no verify) 80 (0) + Format 33 ($21) + Download 32 ($20) + Read address 84 ($54) + Read spin 81 ($51) + Motor on 85 ($55) + Verify sector 86 ($56) + + All of the above are disk device commands, except write and + status, which are also printer commands (with no verify). + + + 771 303 DSTATS + + The status code upon return to user. Also used to set the data + direction; whether the device is to send or receive a data frame. + This byte is used by the device handler to indicate to SIO what to + do after the command frame is sent and acknowledged. Prior to + the SIO call, the handler examines BIT 6 (one equals receive + data) and BIT 7 (one equals send data). If both bits are zero, then + no data transfer is associated with the operation. Both bits set to + one is invalid. SIO uses it to indicate to the handler the status of + the requested operation after the SIO call. + + + 772,773 304,305 DBUFLO/HI + + Data buffer address of the source or destination of the data to be + transferred or the device status information (or the disk sector + data). Set by the user, it need not be set if there is no data + transferred, as in a status request. + + + 774 306 DTIMLO + + The time-out value for the handler in one-second units, supplied + by the handler for use by SIO. The cassette time-out value is 35, + just over 37 seconds. The timer values are 64 seconds per 60 units + of measurement. Initialized to 31. + + + 775 307 DUNUSE + + Unused byte. + + + 776,777 308,309 DBYTLO/HI + + The number of bytes transferred to or from the data buffer (or the + disk) as a result of the most recent operation, set by the handler. + Also used for the count of bad sector data. There is a small bug in + SIO which causes incorrect system actions when the last byte in a + buffer is in a memory location ending with $FF, such as $A0FF. + + + 778,779 30A,30B DAUX1/2 + + Used for device specific information such as the disk sector + number for the read or write operation. Loaded down to locations + 572, 573 ($23C, $23D) by SIO. + + There are only five commands supported by the disk handler: + GET sector (82; $52), PUT sector (80; $50), PUT sector with + VERIFY (87; $57), STATUS request (83; $53) and FORMAT entire + disk (33; $21). There is no command to FORMAT a portion of the + disk; this is done by the INS 1771-1 formatter/controller chip in + the drive itself and isn't user-accessible. There is a new disk drive + ROM to replace the current "C" version. It is the "E" ROM. Not + only is it faster than the older ROMs, but it also allows for + selective formatting of disk sectors. Atari has not announced yet + whether this new 810 ROM will be made available. For more + information, see the OS User's Manual. + + Locations 780 to 793 ($30C to $319) are for miscellaneous use. + Locations 794 to 831 ($31A to $33F) are handler address tables. To use + these DCBs, the user must provide the required parameters to this + block and then do a machine language JSR to $E453 (58451) for disk + I/O or $E459 (58457; the SIO entry point) for other devices. + + + 780,781 30C,30D TIMER1 + + Initial baud rate timer value. + + + 782 30E ADDCOR + + Addition correction flag for the baud rate calculations involving + the timer registers. + + + 783 30F CASFLG + + Cassette mode when set. Used by SIO to control the program + flow through shared code. When set to zero, the current + operation is a standard SIO operation; when non-zero, it is a + cassette operation. + + + 784,785 310,311 TIMER2 + + Final timer value. Timer one and timer two contain reference + times for the start and end of the fixed bit pattern receive period. + The first byte of each timer contains the VCOUNT value (54283; + $D40B), and the second byte contains the current realtime clock + value from location 20 ($14). The difference between the timer + values is used in a lookup table to compute the interval for the + new values for the baud rate passed on to location 750, 751 + ($2EE, $2EF). + + + 786,787 312,313 TEMP1 + + Two-byte temporary storage register used by SIO for the + VCOUNT calculation during baud timer routines. See location + 54283 ($D40B). + + + 788 314 TEMP2 + + Temporary storage register. + + + 789 315 TEMP3 + + Ditto. + + + 790 316 SAVIO + + Save serial data-in port used to detect, and updated after, each + bit arrival. Used to retain the state of BIT 4 of location 53775 + ($D20F; serial data-in register). + + + 791 317 TIMFLG + + Time-out flag for baud rate correction, used to define an + unsuccessful baud rate value. Initially set to one, it is + decremented during the I/O operation. If it reaches zero (after + two seconds) before the first byte of the cassette record is read, + the operation will be aborted. + + + 792 318 STACKP + + SIO stack pointer register. Points to a byte in the stack being + used in the current operation (locations 256 to 511; $100 to $1FF). + + + 793 319 TSTAT + + Temporary status holder for location 48 ($30). + + + 794-831 31A-33F HATABS + + Handler Address Table. Thirty-eight bytes are reserved for up to + 12 entries of three bytes per handler, the last two bytes being set + to zero. On powerup, the HATABS table is copied from ROM. + Devices to be booted, such as the disk drive, add their handler + information to the end of the table. Each entry has the character + device name (C,D,E,K,P,S,R) in ATASCII code and the handler + address (LSB/MSB). Unused bytes are all set to zero. FMS + searches HATABS from the top for a device "D:" entry, and when + it doesn't find it, it then sets the device vector at the end of the + table to point to the FMS vector at 1995 ($7CB). CIO searches for + a handler character from the bottom up. This allows new handlers + to take precedence over the old. Pressing RESET clears HATABS + of all but the resident handler entries! + + 794 31A Printer device ID (P:), initialized to 58416 ($E430). + 797 31D Cassette device ID (C:), initialized to 58432 ($E440). + 800 320 Display editor ID (E:), initialized to 58368 ($E400). + 803 323 Screen handler ID (S:), initialized to 58384 ($E410). + 806 326 Keyboard handler ID (K:), initialized to 58400 + ($E420). + + HATABS unused entry points: + 809 ($329), 812 ($32C), 815 ($32F), 818 ($332), 821 ($335), 824 + ($338), 827 ($33B), and 830 ($33E). These are numbered + sequentially from one to eight. There are only two bytes in the last + entry (unused), both of which are set to zero. When DOS is + present, it adds an entry to the table with the ATASCII code for + the letter "D" and a vector to address 1995 ($7CB). + + The format for the HATABS table is: + + Device name + Handler vector table address + More entries + Zero fill to the end of the table + + The device handler address table entry above for the specific + handler points to the first byte (low byte/high byte) of the vector + table which starts at 58368 ($E400). Each handler is designed + with the following format: + + OPEN vector + CLOSE vector + GET BYTE vector + PUT BYTE vector + GET STATUS vector + SPECIAL vector + Jump to initialization code (JMP LSB/MSB) + + CIO uses the ZIOCB (see location 32; $20) to pass parameters to + the originating IOCB, the A, Y and X registers and CIO. It is + possible to add your own device driver(s) to OS by following + these rules: + 1) Load your routine, with necessary buffers at the address + pointed to by MEMLO: location 743 ($2E7). + 2) Add the size of your routine to the MEMLO value and POKE + the result back into MEMLO. + 3) Store the name and address of your driver in the handler + address table; HATABS. + 4) Change the vectors so that the OS will re-execute the above + steps if RESET has been pressed. This is usually done by + adjusting locations 12 ($C: DOSINIT) and 10 ($A; DOSVEC). + + See the "Insight: Atari" columns in COMPUTE!, January and + April 1982, for details. The APX program "T: A Text Display + Device" is a good example of a device handler application. + See De Re Atari for more information on the DCB and HATABS, + including the use of a null handler. + + --------------------------------------------------------------------------- + Locations 832 to 959 ($340 to $3BF) are reserved for the eight IOCB's + (input/output control blocks). IOCB's are channels for the transfer of + information (data bytes) into and out of the Atari, or between devices. + You use them to tell the computer what operation to perform, how + much data to move and, if necessary, where the data to be moved is + located. Each block has 16 bytes reserved for it. + + What is an IOCB? Every time you PRINT something on the screen or + the printer, every time you LOAD or SAVE a file, every time you OPEN + a channel, you are using an IOCB. In some cases, operations have + automatic OPEN and CLOSE functions built in--like LPRINT. In + others, you must tell the Atari to do each step as you need it. Some + IOCB's are dedicated to specific use, such as zero for the screen + display. Others can be used for any I/O function you wish. The + information you place after the OPEN command tells CIO how you + want the data transferred to or from the device. It is SIO and the device + handlers that do the actual transfer of data. + You can easily POKE the necessary values into the memory locations + and use a machine language subroutine through a USR function to call + the CIO directly (you must still use an OPEN and CLOSE statement for + the channel, however). This is useful because BASIC only supports + either record or single byte data transfer, while the CIO will handle + complete buffer I/O. See the CIO entry address, location 58454 + ($E456), for more details. These blocks are used the same way as the + page zero IOCB (locations 32 to 47; $20 to $2F). The OS takes the + information here, moves it to the ZIOCB for use by the ROM CIO, then + returns the updated information back to the user area when the + operation is done. + Note that when BASIC encounters a DOS command, it CLOSEs all + channels except zero. Refer to the Atari Hardware Manual and the 850 + Interface Manual for more detailed use of these locations. + + + 832-847 340-34F IOCB0 + + I/O Control Block (IOCB) zero. Normally used for the screen + editor (E:). You can POKE 838,166 and POKE 839,238 and send + everything to the printer instead of to the screen (POKE 838,163, + and POKE 839,246 to send everything back to the screen again). + You could use this in a program to toggle back and forth between + screen and printed copy when prompted by user input. This will + save you multiple PRINT and LPRINT coding. + + You can use these locations to transfer data to other devices as + well since they point to the address of the device's "put one byte" + routine. See the OS Manual for more information. Location 842 + can be given the value 13 for read from screen and 12 for write to + screen. POKE 842,13 puts the Atari into "RETURN key mode" by + setting the auxiliary byte one (ICAX1) to screen input and + output. POKEing 842 with 12 returns it to keyboard input and + screen output mode. The former mode allows for dynamic use of + the screen to act upon commands the cursor is made to move + across. + + You can use this "forced read" mode to read data on the screen + into BASIC without user intervention. For example, in the + program below, lines 100 through 200 will be deleted by the + program itself as it runs. + + 10 GRAPHICS 0:POSITlON 2,4 + 20 PRINT 100:PRINT 150:PRINT 200 + 25 PRINT "CONT" + 30 POSITION 2,0 + 50 POKE 842,13:STOP + 60 POKE 842,12 + 70 REM THE NEXT LINES WILL BE DELETED + 100 PRINT "DELETING..." + 150 PRINT "DELETING..." + 200 PRINT "DELETED!" + + DOWNLOAD FORCREAD.BAS + + See COMPUTE!, August 1981, for a sample of this powerful + technique. See Santa Cruz's Tricky Tutorial #1 (display lists) for + another application. The last four bytes (844 to 847; $34C to $34F + in this case) are spare (auxiliary) bytes in all IOCB's. + When you are in a GRAPHICS mode other than zero, channel + zero is OPENed for the text window area. If the window is absent + and you OPEN channel zero, the whole screen returns to mode + zero. A BASIC NEW or RUN command closes all channels + except zero. OPENing a channel to S: or E: always clears the + display screen. + See COMPUTE!, October 1981,for an example of using an IOCB + with the cassette program recorder, and September 1981 for + another use with the Atari 825 printer. + + + 848-863 350-35F IOCB1 + + IOCB one. + + + 864-879 360-36F IOCB2 + + IOCB two. + + + 880-895 370-37F IOCB3 + + IOCB three. + + + 896-911 380-38F IOCB4 + + IOCB four. + + + 912-927 390-39F IOCB5 + + IOCB five. + + + 928-943 3A0-3AF IOCB6 + + IOCB six. The GRAPHICS statement OPENs channel six for + screen display (S:), so once you are out of mode zero, you cannot + use channel six unless you first issue a CLOSE#6 statement. If + you CLOSE this channel, you will not be able to use the + DRAWTO, PLOT or LOCATE commands until you reOPEN the + channel. The LOAD command closes channel six; it also closes + all channels except zero. + + + 944-959 3B0-3BF IOCB7 + + IOCB seven. LPRINT automatically uses channel seven for its + use. If the channel is OPEN for some other use and an LPRINT is + done, an error will occur, the channel will be CLOSEd, and + subsequent LPRINTs will work. The LIST command also uses + channel seven, even if channel seven is already OPEN. However, + when the LIST is done, it CLOSEs channel seven. The LOAD + command uses channel seven to transfer programs to and from + the recorder or disk. LIST (except to the display screen), LOAD + and LPRINT also close all sound voices. The RUN from tape or + disk and SAVE commands use channel seven, as does LIST. + The bytes within each IOCB are used as follows: + + Label Offset Bytes Description + -------------------------------------------------------------------- + ICHID 0 1 Index into the device name + table for the currently OPEN file. Set by the OS. If not in use, the + value is 255 ($FF), which is also the initialization value. + + ICDNO 1 1 Device number such as one + for Dl: or two for D2:. Set by the OS. + + ICCOM 2 1 Command for the type of + action to be taken by the device, set by the user. This is the first + variable after the channel number in an OPEN command. See + below for a command summary. Also called ICCMD. + + ICSTA 3 1 The most recent status + returned by the device, set by the OS. May or may not be the + same value as that which is returned by the STATUS request in + BASIC. See the OS User's Manual, pp. 165-166, fora list of status + byte values. + + ICBAL/H 4,5 2 Two-byte (LSB,MSB) buffer + address for data transfer or the address of the file name for OPEN, + STATUS, etc. + + ICPTL/H 6,7 2 Address of the device's put- + one-byte routine minus one. Set by the OS at OPEN command, + but not actually used by the OS (it is used by BASIC, however). + Points to CIO's "IOCB NOT OPEN" message at powerup. + + ICBLL/H 8,9 2 Buffer length set to the + maximum number of bytes to transfer in PUT and GET + operations. Decremented by one for each byte transferred; + updated after each READ or WRITE operation. Records the + number of bytes actually transferred in and out of the buffer after + each operation. + + ICAX1 10 1 Auxiliary byte number one, + referred to as AUX1. Used in the OPEN statement to specify the + type of file access: four for READ, eight for WRITE, twelve for + both (UPDATE). Not all devices can use both kinds of operations. + This byte can be used in user-written drivers for other purposes + and can be altered in certain cases once the IOCB has been + OPENed (see the program example above). For the S: device, if + AUX1 equals 32, it means inhibit the screen clear function when + changing GRAPHICS modes. Bit use is as follows for most + applications: + Bit 7 6 5 4 3 2 1 0 + Use ....unused.... W R D A + + W equals write, R equals read, D equals directory, A equals + append. + + ICAX2 11 1 Auxiliary byte two, referred + to as AUX2. Special use by each device driver; some serial port + functions may use this byte. Auxiliary bytes two to five have no + fixed use; they are used to contain device-dependent and/or + user-established data. + + ICAX3/4 12,13 2 Auxiliary bytes three and + four; used to maintain a record of the disk sector number for the + BASIC NOTE and POINT commands. + + ICAX5 14 1 Auxiliary byte five. Used by + NOTE and POINT to maintain a record of the byte within a sector. + It stores the relative displacement in sector from zero to 124 + ($7C). Bytes 125 and 126 of a sector are used for sector-link + values, and byte 127 ($7F) is used as a count of the number of + data bytes in actual use in that sector. + + ICAX6 15 1 Spare auxiliary byte. + + Offset is the number you would add to the start of the IOCB in + order to POKE a value into the right field, such as POKE 832 + + OFFSET, 12. + + The following is a list of the values associated with OPEN + parameter number 1. Most of these values are listed in Your Atari + 400/800. These are the values found in ICAX1, not the ICCOM + values. + + Device Task # Description + ---------------------------------------------------------------------- + Cassette 4 Read + recorder 8 Write (can do either, not both) + + Disk 4 Read + file 6 Read disk directory + 8 Write new file. Any file OPENed in + this mode will be deleted, and the first byte written will be at the + start of the file. + 9 Write--append. In this mode the + file is left intact, and bytes written are put at the end of the file. + 12 Read and write--update. Bytes + read or written will start at the first byte in the file. + + D: if BIT 0 equals one and BIT 3 equals one in AUX1,then + operation will be appended output. + + Screen 8 Screen output + editor 12 Keyboard input and screen output + (E:) 13 Screen input and output + + E: BIT 0 equals one is a forced read (GET command). + + Keyboard 4 Read + + Printer 8 Write + + RS-232 5 Concurrent read + serial 8 Block write + port 9 Concurrent write + 13 Concurrent read and write + + Clear Text Read + Screen Window Oper- + after GR. also ation + + Screen 8 yes no no + display 12 yes no yes + (S:) 24 yes yes no + 28 yes yes yes + 40 no no no + 44 no no yes + 56 no yes no + 60 no yes yes + + Note that with S:, the screen is always cleared in GR.0 and there + is no separate text window in GR.0 unless specifically user- + designed. Without the screen clear, the previous material will + remain on screen between GRAPHICS mode changes, but will + not be legible in other modes. The values with S: are placed in + the first auxiliary byte of the IOCB. All of the screen values above + are also a write operation. + + The second parameter in an OPEN statement (placed in the + second auxiliary byte) is far more restricted in its use. Usually set + to zero. If set to 128 ($80) for the cassette, it changes from normal + to short inter-record gaps (AUX2). + + With the Atari 820 printer, 83 ($53; AUX byte two) means + sideways characters (Atari 820 printer only). Other printer + variables (all for AUX2 as well) are: 70 ($4E) for normal 40 + character per line printing and 87 ($57) for wide printing mode. + With the screen (S:), a number can be used to specify the + GRAPHICS modes zero through eleven. If mode zero is chosen, + then the AUX1 options as above are ignored. + For the ICCOM field, the following values apply (BASIC XIO + commands use the same values): + + Command Decimal Hex + ---------------------------------------------------------------------- + Open channel 3 3 + Get text record (line) 5 5 BASIC: + INPUT + #n,A + Get binary record (buffer) 7 7 BASIC: + GET #n,A + Put text record (line) 9 9 + Put binary record (buffer) 11 B BASIC: + PUT #n,A + Close 12 C + Dynamic (channel) status 13 D + + BASIC uses a special "put byte" vector in the IOCB to talk + directly to the handler for the PRINT#n,A$ command. + Disk File Management System Commands (BASIC XIO + command): + + Rename 32 20 + Erase (delete) 33 21 + Protect (lock) 35 23 + Unprotect (unlock) 36 24 + Point 37 25 + Note 38 26 + Format 254 FE + + In addition, XIO supports the following commands: + + Get character 7 7 + Put character 11 B + Draw line 17 11 Display + handler + only. + Fill area 18 12 Display + handler + only. + + FILL is done in BASIC with XIO 18,#6,12,0,"S:" (see the BASIC + Reference Manual for details). + + For the RS-232 (R:), XIO supports: + + Output partial block 32 20 + Control RTS,XMT,DTR 34 22 + Baud, stop bits, word size 36 24 + Translation mode 38 26 + Concurrent mode 40 28 + + (see the 850 Interface Manual for details) + + CIO treats any command byte value greater than 13 ($D) as a + special case, and transfers control over to the device handler for + processing. For more information on IOCB use, read Bill + Wilkinson's "Insight: Atari" columns in COMPUTE!, November + and December 1981, and in Microcomputing, August 1982. Also + refer to the OS User's Manual and De Re Atari. + + --------------------------------------------------------------------------- + + 960-999 3C0-3E7 PRNBUF + + Printer buffer. The printer handler collects output from LPRINT + statements here, sending them to the printer when an End of Line + (EOL; carriage return) occurs or when the buffer is full. Normally + this is 40 characters. However, if an LPRINT statement generates + fewer than 40 characters and ends with a semicolon or 38 + characters and ends with a comma, Atari sends the entire buffer + on each FOR-NEXT loop, the extra bytes filled with zeros. The + output of the next LPRINT statement will appear in column 41 of + the same line. According to the Operating System User's + Manual, the Atari supports an 80-column printer device called + P2:. Using OPEN and PUT statements to P2: may solve this + problem. Here is a small routine for a GR.0 BASIC screen dump: + + 10 DIM TEXT$(1000): OPEN#2,4,0,"S:": + TRAP 1050 + . + . + . + 1000 FOR LINE = 1 TO 24: POSITION PE + EK(82),LINE + 1010 FOR COL = 1 TO 38: GET#2,CHAR: + TEXT$(COL,COL)=CHR$(CHAR) + 1020 NEXT COL: GET#2,COL + 1030 LPRINT TEXT$ + 1040 NEXT LINE + 1050 RETURN + + You can use the PTABW register at location 201 ($C9) to set the + number of spaces between print elements separated by a comma. + The minimum number of spaces accepted is two. LPRINT + automatically uses channel seven for output. No OPEN statement + is necessary and CLOSE is automatic. + + --------------------------------------------------------------------------- + Locations 1000 to 1020 ($3E8 to $3FC) are a reserved spare buffer + area. + + + 1021-1151 3FD-47F CASBUF + + Cassette buffer. These locations are used by the cassette handler + to read data from and write data to the program (tape) recorder. + The 128 ($80) data bytes for each cassette record are stored + beginning at 1024 ($400 - page four). The current buffer size is + found in location 650 ($28A). Location 61 ($3D) points to the + current byte being written or read. + CASBUF is also used in the disk boot process; the first disk + record is read into this buffer. + + A cassette record consists of 132 bytes: two control bytes set to 85 + ($55; alternating zeros and ones) for speed measurement in the + baud rate correction routine; one control byte (see below); 128 + data bytes (compared to 125 data bytes for a disk sector), and a + checksum byte. Only the data bytes are stored in the cassette + buffer. See De Re Atari for more ~nformaUon on the cassette + recorder. + + + + CONTROL BYTE VALUES + + Value Meaning + 250 ($FA) Partial record follows. The actual number of bytes is stored + in the last byte of the record (127). + 252 ($FC) Record full; 128 bytes follow. + 254 ($FE) End of File (EOF) record; followed by 128 zero bytes. + + --------------------------------------------------------------------------- + Locations 1152 to 1791 ($480 to $6FF) are for user RAM (outer + environment) requirements, depending on the amount of RAM + available in the machine. Provided you don't use the FP package or + BASIC, you have 640 ($280) free bytes here. + Locations 1152 to 1279 ($480 to $4FF) are 128 ($80) spare bytes. + The floating point package, when used, requires locations 1406 to 1535 + ($57E to $5FF). + + + 1406 57E LBPR1 + + LBUFF prefix one. + + + 1407 57F LBPR2 + + LBUFF prefix two. + + + 1408-1535 580-5FF LBUFF + + BASIC line buffer; 128 bytes. Used as an output result buffer for + the FP to ASCII routine at 55526 ($D8E6). The input buffer is + pointed to by locations 243, 244 ($F3, $F4). + + + 1504 5E0 PLYARG + + Polynomial arguments (FP use). + + + 1510-1515 5E6-5EB FPSCR + + FP scratch pad use. + + + 1516-1535 5EC-5FF FPSCR1 + + Ditto. The end of the buffer is named LBFEND. + + --------------------------------------------------------------------------- + + 1536-1791 600-6FF .... + + Page six: 256 ($FF) bytes protected from OS use. Page six is not + used by the OS and may be safely used for machine language + subroutines, special I/O handlers, altered character sets, or + whatever the user can fit into the space. Some problem may arise + when the INPUT statement retrieves more than 128 characters. + The locations from 1536 to 1663 ($600 to $67F) are then + immediately used as a buffer for the excess characters. To avoid + overflow, keep INPUT statements from retrieving more than 128 + characters. The valFORTH implementation of fig-FORTH (from + ValPar International) uses all of page six for its boot code, so it is + not available for your use. However, FORTH allows you to + reserve other blocks of memory for similar functions. BASIC A+ + uses locations $0600 - $67F. + + --------------------------------------------------------------------------- + Locations 1792 to the address specified by LOMEM (locations + 128, 129; ($80, $81) - the pointer to BASIC low memory) are also + used by DOS and the File Management System (FMS). Refer to + the DOS source code and Inside Atari DOS for details. The + addresses which follow are those for DOS 2.0S, the official Atari + DOS at the time of this writing. Another DOS is available as an + alternative to DOS 2.0 -- K-DOS (TM), from K-BYTE (R). K-DOS + is not menu driven but command driven. It does not use all of the + same memory locations as the Atari DOS although it does use a + modified version of the Atari FMS. (Another command-driven + DOS, called OS/A+, is completely compatible with DOS 2.OS + and is available from OSS, the creators of DOS 2.0S.) + + + 1792-5377 700-1501 + + File management system RAM (pages seven to fifteen). FMS + provides the interface between BASIC or DUP and the disk + drive. It is a sophisticated device driver for all I/O operations + involving the D: device. It allows disk users to use the special + BASIC XIO disk commands (see the IOCB area 832 to 959: $340 + to $3BF). It is resident in RAM below your BASIC RAM and + provides the entry point to DOS when called by BASIC. + + + 5440-13062 1540-3306 + + DUP.SYS RAM. The top will vary with the amount of buffer + storage space allocated to the drive and sector buffers. + + + 6780-7547 1A7C-1D7B + + Drive buffers and sector-data buffers. The amount of memory will + vary with the number of buffers allocated. + + + 7548-MEMLO 1D7C-3306 (maximum) + + Non-resident portion of DUP.SYS, DOS utility routines. DUP + provides the utilities chosen from the DOS menu page, not from + BASIC. It is not resident in RAM when you are using BASIC or + another cartridge; rather it is loaded when DOS is called from + BASIC or on autoboot powerup (and no cartridge supersedes it). + When DUP is loaded, it overwrites the lower portion of memory. + If you wish to save your program from destruction, you must have + created a MEM.SAV file on disk before you called DOS from your + program. See the DOS Reference Manual. + + --------------------------------------------------------------------------- + Locations 1792 to 2047 ($700 to $7FF; page seven) are the user boot + area. MEMLO and LOMEM point to 1792 when no DOS or DUP + program is loaded. This area can then be used for your BASIC or + machine language programs. The lowest free memory address is 1792, + and programs may extend upwards from here. There is a one-page + buffer before the program space used for the tokenization of BASIC + statements, pointed to by locations 128, 129 ($80, $81). Actually a + program may start from any address above 1792 and below the screen + display list as long as it does not overwrite this buffer if it is a BASIC + program. Also, 1792 is the start of the FMS portion of DOS when + resident. + + When software is booted, the MEMLO pointer at 743,744 ($2E7,$2E8) + in the OS data base (locations 512 to 1151; $512 to $47F) points to the + first free memory location above that software; otherwise, it points to + 1792. The DUP portion of DOS is partly resident here, starting at 5440 + ($1540) and running to 13062 ($1540 to $3306). The location of the OS + disk boot entry routine (DOBOOT) is 62189 ($F2ED). The standard + Atari DOS 2.OS takes up sectors one through 83 ($53) on a disk. Sector + one is the boot sector. Sectors two through 40 ($28) are the FMS + portion, and sectors 41 ($29) through 83 are the DUP.SYS portion of + DOS. For more information, see the DOS and OS source listings and + Inside Atari DOS. + + --------------------------------------------------------------------------- + + FMS, DOS.SYS and DUP.SYS + + Disk boot records (sector one on a disk) are read into 1792 ($700). + Starting from $700 (1792), the format is: + + Byte Hex Label and use + 0 700 BFLAG: Boot flag equals zero (unused). + 1 701 BRCNT: Number of consecutive sectors to + read (if the file is DOS, then BRCNT equals + one). + 2,3 702,703 BLDADR: Boot sector load address ($700). + 4,5 704,705 BIWTARR: Initialization address. + 6 706 JMP XBCONT: Boot continuation vector; $4C + (76): JMP command to next address in bytes seven and eight. + + 7,8 707,708 Boot read continuation address + (LSB/MSB). + + 9 709 SABYTE: Maximum number of concurrently + OPEN files. The default is three (see 1801 below). + + 10 70A DRVBYT: Drive bits: the maximum number + of drives attached to the system. The default is two (see 1802 + below). + + 11 70B (unused) Buffer allocation direction, set to + zero. + + 12,13 70C,70D SASA: Buffer allocation start address. Points + to 1995 ($7CB) when DOS is loaded. + + 14 70E DSFLG: DOS flag. Boot flag set to non-zero + Must be non-zero for the second phase of boot process. Indicates + that the file DOS.SYS has been written to the disk; zero equals no + DOS file, one equals 128 byte sector disk, two equals 256 byte + sector disk. + + 15,16 70F,710 DFLINK: Pointer to the first sector of DOS.SYS + file. + + 17 711 BLDISP: Displacement to the sector link byte + 125 ($7D). The sector link byte is the pointer to the next disk + sector to be read. If it is zero, the end of the file has been + reached. + + 18,19 712,713 DFLADR: Address of the start of DOS.SYS + file. + + 20+ 714+ Continuation of the boot load file. See the + OS User's Manual and Chapter 20 of Inside Atari DOS. + + Data from the boot sector is placed in locations 1792 to 1916 ($700 + to $77C). Data from the rest of DOS.SYS is located starting from + 1917 ($77D). All binary file loads start with 255 ($FF). The next + four bytes are the start and end addresses (LSB/MSB), + respectively. + + + 1801 709 SABYTE + + This records the limit on the number of files that can be open + simultaneously. Usually set to three, the maximum is seven (one + for each available IOCB -- remember IOCB0 is used for the + screen display). Each available file takes 128 bytes for a buffer, + if you increase the number of buffers, you decrease your RAM + space accordingly. You can POKE 1801 with your new number to + increase or decrease the number of files and then rewrite DOS + (by calling DOS from BASIC and choosing menu selection "H") + and have this number as your default on the new DOS. + + + 1802 70A DRVBYT + + The maximum number of disk drives in your system, the DOS 2.0 + default value is two. The least four bits are used to record which + drives are available, so if you have drives one, three and four, + this location would read: + + 00001101 or 13 in decimal. + + Each drive has a separate buffer of 128 bytes reserved for it in + RAM. If you have more or less than the default (two), then POKE + 1802 with the appropriate number: + + 1 drive = 1 BIT 0 Binary 00000001 + 2 drives = 3 BITS 0 & 1 00000011 + 3 drives = 7 BITS 0, 1 & 2 00000111 + 4 drives = 15 BITS 0, 1, 2 & 3 00001111 + + This assumes you have them numbered sequentially. If not, + POKE the appropriate decimal translation for the correct binary + code: each drive is specified by one of the least four bits from one + in BIT 0 to four in BIT 3. If you PEEK (1802) and get back three, + for example, it means drives one and two are allocated, not three + drives. + + You can save your modification to a new disk by calling up DOS + and choosing menu selection "H." This new DOS will then boot + up with the number of drives and buffers you have allocated. A + one-drive system can save 128 bytes this way (256 if one less data + buffer is chosen). See the DOS Manual, page G.87. + + + 1900 76C BSIO + + Entry point to FMS disk sector I/O routines. + + + 1906 772 BSIOR + + Entry point to the FMS disk handler (?). + + + 1913 779 .... + + Write verify flag for disk I/O operations. POKE with 80 ($50) to + turn off the verify function, 87 ($57) to turn it back on. Disk write + without verify is faster, but you may get errors in your data. I + have had very few errors generated by turning off the verify + function, but even one error in critical material can destroy a + whole program. Be careful about using this location. You can + save DOS (as above with menu selection "H") without write verify + as your new default by writing DOS to a new disk. See the DOS + Manual, page F.85. K-DOS's write-verify flag is located at 1907 + ($773). + + + 1995 7CB DFMSDH + + Entry point to a 21-byte FMS device (disk) handler. The address + of this handler is placed in HATABS (locations 794 to 831; $31A + to $33F) by the FMS initialization routine. When CIO needs to + call an FMS function, it will locate the address of that function via + the handler address table. See Chapters 8-11 of Inside Atari + DOS, published by COMPUTE! Books. + + + 2016 7E0 DINT + + FMS initialization routine. The entry point is 1995 ($7CB). DUP + calls FMS at this point. K-DOS uses the same location for its + initialization routine. + + + 2219 8AB DFMOPN + + OPEN routines, including open for append, update, and output. + + + 2508 900 DFMPUT + + PUT byte routines. + + + 2591 A1F WTBUR + + Burst I/O routines. + + + 2592-2773 A20-AD5 .... + + In COMPUTE!, May and July 1982, Bill Wilkinson discussed + BURST I/O, which should not take place when a file is OPEN for + update, but does, due to a minor bug in DOS 2.0 (see also Inside + Atari DOS, Chapter 12). This will cause update writes to work + properly, but update reads to be bad. The following POKEs will + correct the problem. Remember to save DOS back to a new disk. + + POKE 2592,130 ($A20,82) + POKE 2593,19 ($A21,13) + POKE 2594,73 ($A22,49) + POKE 2595,12 ($A23,0C) + POKE 2596,240 ($A24,F0) + POKE 2597,36 ($A25,24) + POKE 2598,106 ($A26,6A) + POKE 2599,234 ($A27,EA) + POKE 2625,16 ($A41,10) + POKE 2773,31 ($AD5,1F) + + (Note that the July 1982 issue of COMPUTE! contained a typo + where the value to be POKEd into 2773 was mistakenly listed as + 13, not 31!) Wilkinson points out that one way to completely + disable BURST I/O (useful in some circumstances such as using + the DOS BINARY SAVE to save the contents of ROM to disk!) is + by: + + POKE 2606,0 ($A2E,0) + + This, however, will make the system LOAD and SAVE files + considerably more slowly, so it's not recommended as a + permanent change to DOS. + + + 2751 ABF DFMGET + + GET byte routines, including GET file routines. + + 2817 B0l DFMSTA + Disk STATUS routines. + + + 2837 B15 DFMCLS + + IOCB CLOSE routines. + + + 2983 BA7 DFMDDC + + Start of the device-dependent command routines, including the + BASIC XIO special commands: + + + 3033 BD9 XRENAME + + RENAME a file. + + + 3122 C32 XDELETE + + DELETE a file. + + + 3196 C7C XLOCK, XUNLOCK + + LOCK and UNLOCK files. UNLOCK routines begin at 3203 + ($C83). + + + 3258 CBA XPOINT + + BASIC POINT command. + + + 3331 D03 XNOTE + + BASIC NOTE command. See the DOS Manual for information + regarding these two BASIC commands, and see De Re Atari for a + sample use. + + + 3352 D18 XFORMAT + + Format the entire diskette. + + + 3501 DAD LISTDIR + + List the disk directory. + + + 3742 E9E FNDCODE + + File name decode, including wildcard validity test. The current + file name is pointed to by ZBUFP at locations 67, 68 ($43, $44). + + + 3783 EC7 .... + + By POKEing the desired ATASCII value here, you can change + the wildcard character (*; ATASCII 42, $2A) used by DOS to any + other character of your choice. Your altered DOS can be saved + back to disk with DOS menu selection "H". + + + 3818,3822 EEA,EEE .... + + By POKEing 3818 with 33 and 3822 with 123 ($21 ,$7B;), you can + modify DOS to accept file names with punctuation, numbers and + lowercase as valid; 33 is the low range of the ATASCII code and + 127 the high range (lower or higher values are control and + graphics codes and inverse characters). Of course, any + unmodified DOS still won't accept such file names. You could + actually change the range to any value from zero to 255 at your + discretion. This, however, may cause other problems with such + ATASCII codes as spaces and the wildcard (*; see above). Can + be saved back to disk with menu selection "H". + + + 3850 F0A FDSCHAR + + Store the file name characters that result from the file name + decode routines. + + + 3873 F21 SFDIR + + Directory search routines; search for the user-specified file + name. + + + 3988 F94 WRTNXS + + Write data sector routine. + + + 4111 100F RDNXTS + + Read data sector routine. + + + 4206 106E RDDIR + + Read and write directory sector routines. + + + 4235 108B RDVTOC + + Read or write the volume table of contents (VTOC) sectors. + + + 4293 10C5 FRESECT + + Free sector(s) routine; returns the number of free sectors on a + disk that are available to the user. + + + 4358 1106 GETSECTOR + + Get sector routine; retrieves a free sector for use from the disk. + + + 4452 1164 SETUP + + SETUP -- initialization of the FMS parameters. Prepares FMS to + deal with the operation to be performed and to access a + particular file. See Inside Atari DOS, Chapter seven. + + + 4618 120A WRTDOS + + Write new DOS.SYS file to disk routine, including new FMS file + to DOS.SYS file. + + + 4789 12B5 ERRNO + + Start of the FMS error number table. + + + 4856-4978 12F8-1372 .... + + Miscellaneous FMS storage area: sector length, drive tape, stack + level, file number, etc. + + + 4993-5120 1381-1400 FCB + + Start of the FMS File Control Blocks (FCB's). FCB's are used to + store information about files currently being processed. The + eight FCB's are 16-byte blocks that correspond in a one-on-one + manner with the IOCB's. Each FCB consist of: + + Label Bytes Purpose + FCBFNO 1 File number of the current file being + processed. + + FCBOTC 1 Which mode the file has been OPENed for: + append is one, directory read is two, input is four, output is + eight, update is twelve. + + SPARE 1 Not used. + + FCBSLT 1 Flag for the sector length type; 128 or 256 + bytes + + FCBFLG 1 Working flag. If equal to 128 ($80), then the + file has been OPENed for output or append and may acquire new + data sectors. If the value is 64, then sector is in the memory buffer + awaiting writing to disk. + + FCBMLN 1 Maximum sector data length; 125 or 253 bytes + depending on drive type (single or double density). The last + three sector bytes are reserved for sector link and byte count + data. + + FCBDLN 1 Current byte to be read or modified in the + operation in a data sector. + + FCBBUF 1 Tell FMS which buffer has been allocated + to the file being processed. + + FCBCSN 2 Sector number of the sector currently in the + buffer. + + FCBLSN 2 Number of the next sector in data chain. + + FCBSSN 2 Starting sectors for appended data if the file + has been OPENed for append. + + FCBCNT 2 Sector count for the current file. + + DUP doesn't use these FCB's; it writes to the IOCB's directly. + CIO transfers the control to FMS as the operation demands, then + on to SIO. + + + 5121 1401 FILDIR + + File directory, a 256 ($100) byte sequential buffer for entries to + the disk directory. + + + 5377 1501 ENDFMS + + Disk directory (VTOC -- Volume Table Of Contents) buffer. 64 + ($40) bytes are reserved, one byte for each possible file. It also + marks the end of FMS. The VTOC (sector 360; $168) is a + sequential bit map of each of the 720 sectors on the disk. It starts + at byte ten and continues through to byte 99. When a bit is set + (one), it indicates that the sector associated is in use. + + + 5440 1540 DOS + + DUP.SYS initialization address. Beginning of mini-DOS; the + RAM-resident portion of DUP. Used for the same purpose in K- + DOS. + + + 5446,5450 1546,154A .... + + Contains the location (LSB/MSB) of the DOS VEC (location 10; + $A). This is the pointer to the address BASIC will jump to when + DOS is called. + + + 5533 159D DUPFLG + + Flag to test if DUP is already resident in memory. Zero equals + DUP is not there. + + + 5534 159E OPT + + Used to store the value of the disk menu option chosen by the + user. + + + 5535 159F LOADFLG + + If this location reads 128, then a memory file (MEM.SAV) file + doesn't have to be loaded. + + + 5540 15A4 SFLOAD + + Routines to load a MEM.SAV file if it exists. + + + 5888 1700 USRDOS + + Listed in the DUP.SYS equates file but never explained in the + listings. + + + 5899 170B MEMLDD + + Flags that the MEM.SAV file has been loaded. Zero means it has + not been loaded. + + + 5947 173B .... + + The MEM.SAV (MEMSAVE) file creation routines begin here. + They start with the file name MEM.SAV stored in ATASCII + format. The write routines begin at MWRITE, 5958 ($1746). The + DOS utility MEMSAVE copies the lower 6000 bytes of memory to + disk to save your BASIC program from being destroyed when + you call DOS, which then loads DUP.SYS into that area of + memory. + + + 6044,6045 179C-179D INISAV + + DOSINI (see location 12, 13; $C, $D) vector save location. Entry + point to DOS on a call from BASIC. + + + 6046 179E MEMFLG + + Flag to show if memory has been written to disk using a + MEM.SAV file. + + + 6418 1912 CLMJMP + + Test to see if DOS must load MEM.SAV from the disk before it + does a run at cartridge address, then jumps to the cartridge + address. + + + 6432 1920 LMTR + + Test to see if DOS must load MEM.SAV before it performs a run at + address command from the DOS menu. + + + 6457 1939 LDMEM + + MEMSAVE load routines (for the MEM.SAV file). + + + 6518 1979 INITIO + + DUP.SYS warmstart entry. An excellent program to eliminate the + need for DUP.SYS and MEM.SAV (not to mention the time + required to load them!) was presented in COMPUTE!, July 1982, + called MicroDOS; it's well worth examining. See also "The Atari + Wedge," COMPUTE!, December 1982. + + 663C 19E6 ISRODN + Start of the serial interrupt service routine to output data needed + routines in DUP.SYS. + + + 6691 1A23 ISRSIR + + Start of the serial interrupt ready service routines in DUP.SYS. + + + 6781 1A7D .... + + Start of the drive and data buffers. Drive buffers are numbered + sequentially one to four, data buffers one to eight, assuming that + many are allocated for each. Normally, the first two buffers are + allocated for drives and the next three for data. Buffers are 128 + ($80) bytes long each and start at 6908 ($1AFC), 7036 ($1B7C), + 7162 ($1BFA) and 7292 ($1C7C). See locations 1801 and 1802 + ($709, $70A). + + + 7420 1CFC .... + + MEMLO (743, 744; $2E7, $2E8) points here when DOS is resident + unless the buffer allocation has been altered. MEMLO will point + to 7164 for a one drive, two data buffer setup, a saving of 256 + bytes. Loading the RS-232 handler from the 850 Interface will + move MEMLO up another 1728 bytes. The RS-232 handler in the + 850 Interface will only boot (load into memory) if you first boot + the AUTORUN.SYS file on your Atari master diskette or use + another RS-232 boot program such as a terminal package. The + RS-232 handler will boot up into memory if you do not have a disk + attached and you have turned it on before turning on the + computer. You may still use the printer (parallel) port on the 850 + even if the RS-232 handler is not booted. + + + 7548 1D7C .... + + Beginning of non-resident portion of DUP; 40 ($28) byte + parameter buffer. + + + 7588 1DA4 LINE + + 80 ($50) byte line buffer. + + + 7668 1DF4 DBUF + + 256 ($100) byte data buffer for COPY routines. Copy routines + work in 125-byte passes, equal to the number of data bytes in + each sector on the disk. There are 256 bytes because Atari had + planned a double density drive which has 253 data bytes in each + sector. + + + 7924 1EF4 .... + + Miscellaneous variable storage area and data buffers. + + + 7951-8278 1F0F-2056 DMENU + + Disk menu screen display data is stored here. + + + 8191 1FFF .... + + This is the top of the minimum RAM required for operation (8K). + To use DOS, you must have a minimum of 16K. + + --------------------------------------------------------------------------- + + DUP.SYS ROUTINES + + Locations 8192 to 32767 ($2000 to $7FFF) are the largest part of the + RAM expansion area; this space is generally for your own use. If you + have DOS.SYS or DUP.SYS loaded in, they also use a portion of this + area to 13062 ($3306) as below: + + + 8309 2075 DOSOS + + Start of the DOS utility monitor, including the utilities called + when a menu selection function is completed and the display of + the "SELECT ITEM" message. + + + 8505 2139 DIRLST + + Directory listing. + + + 8649 21C9 DELFIL + + Delete a file. + + + 8990 231E .... + + Copy a file. This area starts with the copy messages. The copy + routines themselves begin at PYFIL, 9080 ($2378). + + + 9783 2637 RENFIL + + Rename a disk file routines. + + + 9856 2680 FMTDSK + + Format the entire disk. There is no way to format specific sectors + of a disk with the "C" ROMs currently used in your 810 drives. + There is a new ROM, the "E" version, which not only allows + selective sector formatting, but is also considerably faster. It was + not known at the time of this writing whether Atari would release + the "E" version. + + + 9966 26EE STCAR + + Start a cartridge. + + + 10060 274C BRUN + + Run a binary file at the user-specified address. + + + 10111 277F .... + + Start of the write MEM.SAV file to disk routine. The entry point is + at MEMSAV, 10138 ($279A). + + + 10201 27D9 WBOOT + + Write DOS/DUP files to disk. + + + 10483 28F3 TESTVER2 + + Test for version two DOS. DOS.20S is the latest official DOS, + considerably improved over the earlier DOS 1.0. The S stands for + single density. Atari had planned to release a dual density drive + (the 815), but pulled it out of the production line at the last minute + for some obscure high-level reason. A double density drive is + available from the Percom company. + + + 10522 291A LDFIL + + Load a binary file into memory. If it has a run address specified in + the file, it will autoboot. + + + 10608 2970 LKFIL, ULFIL + + Lock and unlock files on a disk. + + + 10690 29C2 DDMG + + Duplicate a disk. + + + 11528 2D08 DFFM + + Duplicate a file. + + + 11841 2E41 .... + + Miscellaneous subroutines. + + + 12078 2F2E SAVFIL + + Save a binary file. + + + 12348 303C .... + + Miscellaneous subroutines. + + + 13062 3306 .... + + End of DUP.SYS. + The rest of RAM is available to location 32767 ($7FFF). + + --------------------------------------------------------------------------- + + CARTRIDGE B: 8K + + Locations 32768 to 40959 ($8000 to $9FFF) are used by the right + cartridge (Atari 800 only), when present. When not present, this RAM + area is available for use in programs. When the 8K BASIC cartridge is + being used, this area most frequently contains the display list and screen + memory. As of this writing, the only cartridge that uses this slot is + Monkey Wrench from Eastern House Software. + + It is possible to have 16K cartridges on the Atari by either combining + both slots using two 8K cartridges or simply having one with large + enough ROM chips and using one slot. In this case, the entire area from + 32768 to 49151 ($8000 to $BFFF) would be used as cartridge ROM. + + Technically, the right cartridge slot is checked first for a resident + cartridge and initialized, then the left. You can confirm this by putting + the Assembler Editor cartridge in the right and BASIC in the left slots. + BASIC will boot, but not the ASED. Using FRE(0), you will see, + however, that you have 8K less RAM to use; and PEEKing through this + area will show that the ASED program is indeed in memory, but that + control was passed to BASIC. Control will pass to the ASED cartridge if + the cartridges are reversed. This is because the last six bytes of the + cartridge programs tell the OS where the program begins -- in both + cases, it is a location in the area dedicated to the left cartridge. The six + bytes are as follows: + + Byte Purpose + Left (A) Right(B) + 49146 ($BFFA) 40954 ($9FFA) Cartridge start address (low byte) + 49147 ($BFFB) 40955 ($9FFB) Cartridge start address (high byte) + 49148 ($BFFC) 40956,($9FFC) Reads zero if a cartridge is + inserted, non-zero when no cartridge is present. This information + is passed down to the page zero RAM: if the A cartridge is plugged + in, then location 6 will read one; if the B cartridge is plugged in, + then location 7 will read one; otherwise they will read zero. + 49149 ($BFFD) 40957 ($9FFD) Option byte. If BIT 0 equals one, + then boot the disk (else there is no disk boot). If BIT 2 equals one, + then initialize and start the cartridge (else initialize but do not + start). If BIT 7 equals one, then the cartridge is a diagnostic + cartridge which will take control, but not initialize the OS (else + non-diagnostic cartridge). Diagnostic cartridges were used by + Atari in the development of the system and are not available to the + public. + 49150 ($BFFE) 40958 ($9FFE) Cartridge initialization address + low byte. + 49151 ($BFFF) 40959 ($9FFF) Cartridge initialization address + high byte. This is the address to which the OS will jump during all + powerup and RESETs. + + The OS makes temporary use of locations 36876 to 36896 ($900C to + $9020) to set up vectors for the interrupt handler. See the OS + listings pages 31 and 81. This code was only used in the + development system used to design the Atari. + + --------------------------------------------------------------------------- + + CARTRIDGE A: 8K + + Locations 40960 to 49151 ($A000 to $BFFF) are used by the left + cartridge, when present. When not present, this RAM area is available + for other use. The display list and the screen display data will be in this + area when there is no cartridge present. + + Most cartridges use this slot (see above) including the 8K BASIC, + Assembler-Editor, and many games. Below are some of the entry + points for the routines in Atari 8K BASIC. There is no official Atari + listing of the BASIC ROM yet. Many of the addresses below are listed + in Your Atari 400/800. Others have been provided in numerous + magazine articles and from disassembling the BASIC cartridge. + + + BASIC ROUTINES + + 40960-41036 A000-A04C + Cold start. + + 41037-41055 A04D-A05F + Warm start. + + 41056-42081 A060-A461 + Syntax checking routines. + + 42082-42158 A462-A4AE + Search routines. + + 42159-42508 A4AF-A60C + STATEMENT name table. The statement TOKEN list begins at 42161 + ($A4B1). You can print a list of these tokens by: + + 5 ADDRESS = 42161 + 10 IF NOT PEEK(ADDRESS) THEN PRINT: + END + 15 PRINT TOKEN, + 20 BYTE = PEEK(ADDRESS): ADDRESS = A + DDRESS + 1 + 30 IF BYTE < 128 THEN PRINT CHR$(BYT + E);: GOTO 20 + 40 PRINT CHR$(BYTE - 128) + 50 ADDRESS = ADDRESS + 2: TOKEN = TO + KEN + 1: GOTO 10 + + DOWNLOAD STATMENT.BAS + + 42509-43134 A60D-A87E + Syntax tables. The OPERATOR token list begins at 42979 ($A7E3). You + can print a list of these tokens by: + + 5 ADDRESS = 42979: TOKEN = 16 + 10 IF NOT PEEK (ADDRESS) THEN PRINT: + END + 15 PRINT TOKEN, + 20 BYTE = PEEK(ADDRESS): ADDRESS = A + DDRESS + 1 + 30 IF BYTE < 128 THEN PRINT CHR$(BYT + E);: GOTO 20 + 40 PRINT CHR$(BYTE - 128) + 50 TOKEN = TOKEN + 1 + 60 GOTO 10 + + DOWNLOAD OPERATOR.BAS + + See COMPUTE!, January and February 1982; BYTE, February 1982, + and De Re Atari for an explanation of BASIC tokens. + + 43135-43358 A87F-A95E + Memory manager. + + 43359-43519 A95F-A9FF + Execute CONT statement. + + 43520-43631 AA00-AA6F + Statement table. + + 43632-43743 AA70-AADF + Operator table. + + 43744-44094 AAE0-AC3E + Execute expression routine. + + 44095-44163 AC3F-AC83 + Operator precedence routine. + + 44164-45001 AC84-AFC9 + Execute operator routine. + + 45002-45320 AFCA-B108 + Execute function routine. + + 45321-47127 B109-B817 + Execute statement routine. + + 47128-47381 B818-B915 + CONT statement subroutines. + + 47382-47542 B916-B9B6 + Error handling routines. + + 47543-47732 B9B7-BA74 + Graphics handling routines. + + 47733-48548 BA75-BDA4 + I/O routines. + + 48549-49145 BDA5-BFF9 + Floating point routines (see below). + + + 48551 BDA7 SIN + + Calculate SIN(FR0). Checks DEGFLG (location 251; $FB) to see if + trigonometric calculations are in radians (DEGFLG equals zero) + or degrees (DEGFLG equals six). + + + 48561 BDB1 COS + + Calculate Cosine (FR0) with carry. FR0 is Floating Point register + zero, locations 212-217; $D4-$D9. See the Floating Point package + entry points from location 55296 on. + + + 48759 BE77 ATAN + + Calculate Atangent using FR0, with carry. + + + 48869 BEE5 SQR + + Calculate square root (FR0) with carry. + Note that there is some conflict of addresses for the above + routines. The addresses given are from the first edition of De Re + Atari. The Atari OS Source Code Listing gives the following + addresses for these FP routines: + + These are entry points, not actual start addresses. + + SIN 48513 ($BD81) + COS 48499 ($BD73) + ATAN 48707 ($BE43) + SQR 48817 ($BEB1) + + However, after disassembling the BASIC ROMs, I found that the + addresses in De Re Atari appear to be correct. + + 49146,7 BFFA,B + Left cartridge start address. + + 49148 BFFC + A non-zero number here tells the OS that there is no cartridge in + the left slot. + + 49149 BFFD + Option byte. A cartridge which does not specify a disk boot may + use all of the memory from 1152 ($480) to MEMTOP any way it sees + fit. + + 49150,1 BFFE,F + Cartridge initialization address. See the above section on the right + slot, 32768 to 40959, for more information. + + --------------------------------------------------------------------------- + When a BASIC program is SAVEd, only 14 of the more than 50 + page zero locations BASIC uses are written to the disk or cassette + with the program. The rest are all recalculated with a NEW or + SAVE command, sometimes with RUN or GOTO. These 14 + locations are: + + 128,129 80,81 LOMEM + 130,131 82,83 VNTP + 132,133 84,85 VNTD + 134,135 86,87 VVTP + 136,137 88,89 STMTAB + 138,139 8A,8B STMCUR + 140,141 8C,8D STARP + + The string/array space is not loaded; STARP is included only to + point to the end of the BASIC program. + The two other critical BASIC page zero pointers, which are not + SAVEd with the program, are: + + 142,143 8E,8F RUNSTK + 144,145 90,91 MEMTOP + + For more information concerning Atari BASIC, see the appendix. + For detailed description, refer to the Atari BASIC Reference + Manual. For more technical information, see De Re Atari, BYTE, + February 1982, and COMPUTE!'s First Book of Atari and + COMPUTE!'s Second Book of Atari. + + --------------------------------------------------------------------------- + Locations 49152 to 53247 ($C000 to $CFFF) are unused. + Unfortunately, this rather large 4K block of memory cannot be written + to by the user, so it is presently useless. Apparently, this area of ROM + is reserved for future expansion. Rumors abound about new Atari OS's + that allow 3-D graphics, 192K of on-board RAM and other delights. + Most likely this space will be consumed in the next OS upgrade. + PEEKing this area will show it not to be completely empty; it was + apparently used for system development in Atari's paleozoic age. + Although the Atari is technically a 64K machine (1K equals 1024 bytes, + so 64K equals 65536 bytes), you don't really have all 64K to use. The + OS takes up 10K; there is the 4K block here that's unused, plus a few + other unused areas in the ROM and, of course, there are the hardware + chips. BASIC (or any cartridge) uses another 8K. The bottom 1792 + bytes are used by the OS, BASIC, and floating point package. Then + DOS and DUP take up their memory space, not to mention the 850 + handler if booted -- leaving you with more or less 38K of RAM to use + for your BASIC programming. + + --------------------------------------------------------------------------- + Locations 53248 to 55295 ($D000 to $D7FF) are for ROM for the special + I/O chips that Atari uses. The CTIA (or GTIA, depending on which + you have) uses memory locations 53248 to 53503 ($D000 to $D0FF). + POKEY uses 53760 to 54015 ($D200 to $D2FF). PIA uses 54016 to 54271 + ($D300 to $D3FF). ANTIC uses 54272 to 54783 ($D400 to $D5FF). + ANTIC, POKEY and G/CTIA are Large Scale Integration (LSI) circuit + chips. Don't confuse this chip ROM with the OS ROM which is be + found in higher memory. For the most extensive description of these + chips, see the Atari Hardware Manual. + + There are two blocks of unused, unavailable memory in the I/O areas: + 53504 to 53759 ($D100 to $D1FF) and 54784 to 55295 ($D600 to + $D7FF). + + Many of the following registers can't be read directly, since they are + hardware registers. Writing to them can often be difficult because in + most cases the registers change every 30th second (stage two + VBLANK) or even every 60th second (stage one VBLANK)! That's + where the shadow registers mentioned earlier come in. The values + written into these ROM locations are drawn from the shadow registers; + to effect any "permanent" change in BASIC (i.e., while your program + is running), you have to write to these shadow registers (in direct mode + or while your program is running; these values will all be reset to their + initialization state on RESET or powerup). + + Shadow register locations are enclosed in parentheses; see these + locations for further descriptions. If no shadow register is mentioned, + you may be able to write to the location directly in BASIC. Machine + language is fast enough to write to the ROM locations and may be able + to bypass the shadow registers entirely. + + Another feature of many of these registers is their dual nature. They + are read for one value and written to for another. The differences + between these functions are noted by the (R) for read and (W) for write + functions. You will notice that many of these dual-purpose registers + also have two labels. + + --------------------------------------------------------------------------- + + CTIA or GTIA + + 53248-53505 D000-D0FF + + GTIA (or CTIA) is a special television interface chip designed + exclusively for the Atari to process the video signal. ANTIC + controls most of the C/GTIA chip functions. The GTIA shifts the + display by one-half color clock off what the CTIA displays, so it + may display a different color than the CTIA in the same piece of + software. However, this shift allows players and playfields to + overlap perfectly. + + There is no text window available in GTIA modes, but you can + create a defined area on your screen with either a DLI (see + COMPUTE!, September 1982) or by POKEing the GTIA mode + number into location 87 ($57), POKEing 703 with four and then + setting the proper bits in location 623 ($26F) for that mode. Only in + the former method will you be able to get a readable screen, + however. In the latter you will only create a four line, scrolling, + unreadable window. You will be able to input and output as with + any normal text window; you just won't be able to read it! GTIA, + by the way, apparently stands for "George's Television Interface + Adapter." Whoever George is, thanks, but what is CTIA? + See the OS User's Manual, the Hardware Manual, De Re Atari and + COMPUTE!, July 1982 to September 1982, for more information. + + + 53248 D000 HPOSP0 + + (W) Horizontal position of player 0. Values from zero to 227 ($E3) + are possible but, depending on the size of the playfield, the range + can be from 48 ($30) as the leftmost position to 208 ($D0) as the + rightmost position. Other positions will be "off screen." + Here are the normal screen boundaries for players and missiles. + The values may vary somewhat due to the nature of your TV + screen. Players and missiles may be located outside these + boundaries, but will not be visible (off screen): + + Top + 32 for single, + 16 for double line + resolution + +--------------------------------+ + | | + | | + | | + 48 for both | | 208 for both + resolutions | | resolutions + | | + | | + | | + +--------------------------------+ + Bottom + 224 for single, + 112 for double line + resolution + + Although you can POKE to these horizontal position registers, they + are reset to zero immediately. The player or missile will stay on the + screen at the location specified by the POKE, but in order to move + it using the horizontal position registers, you can't use: + + POKE 53248, PEEK (53248) + n (or -n) + + which will end up generating an error message. Instead, you need + to use something like this: + + 10 POKE 704,220: GRAPHICS 1: HPOS = + 53248: POKE 623,8 + 20 N = 100: POKE HPOS,N: POKE 53261 + ,255 + 30 IF STICK(0) = 11 THEN N = N - 1: + POKE HPOS,N: PRINT N + 40 IF STICK(0) = 7 THEN N = N + 1: + POKE HPOS,N: PRINT N + 50 GOTO 30 + + There are no vertical position registers for P/M graphics, so you + must use software routines to move players vertically. One idea for + vertical motion is to reposition the player within the P/M region + rather than the screen RAM. For example, the program below uses + a small machine language routine to accomplish this move: + + 1 REM LINES 5 TO 70 SET UP THE PLAYER + 5 KEEP=PEEK(106)-16 + 10 POKE 106,KEEP:POKE 54279,KEEP + 20 GRAPHICS 7+16:POKE 704,78:POKE 559 + ,46:POKE 53277,3 + 30 PMBASE=KEEP*256 + 40 FOR LOOP=PMBASE+512 TO PMBASE+640: + POKE LOOP,0:NEXT LOOP:REM CLEAR OU + T MEMORY FIRST + 50 X=100:Y=10:POKE 53248,X + 60 FOR LOOP=0 TO 7:READ BYTE:POKE PMB + ASE+512+Y+LOOP,BYTE:NEXT LOOP:REM + PLAYER GRAPHICS INTO MEMORY + 70 DATA 129,153,189,255,255,189,153,1 + 29 + 80 REM LINES 100 TO 170 SET UP MACHIN + E LANGUAGE ROUTINE + 100 DIM UP$(21),DOWN$(21):UP=ADR(UP$) + :DOWN=ADR(DOWN$) + 110 FOR LOOP=UP TO UP+20:READ BYTE:PO + KE LOOP,BYTE:NEXT LOOP + 120 FOR LOOP=DOWN TO DOWN+20:READ BYT + E:POKE LOOP,BYTE:NEXT LOOP + 130 DATA 104,104,133,204,104,133,203, + 160,1,177 + 140 DATA 203,136,145,203,200,200,192, + 11,208,245,96 + 150 DATA 104,104,133,204,104,133,203, + 160,10,177 + 160 DATA 203,200,145,203,136,136,192, + 255,208,245,96 + 200 REM VERTICAL CONTROL + 210 IF STICK(0)=14 THEN GOSUB 300 + 220 IF STICK(0)=13 THEN D=USR(DOWN,PM + BASE+511+Y):Y=Y+1 + 250 GOTO 210 + 300 U=USR(UP,PMBASE+511+Y):Y=Y-l + 310 RETURN + + DOWNLOAD MOVEPM.BAS + + This will move any nine-line (or less) size player vertically with the + joystick. If you have a larger player size, increase the 11 in line 140 + to a number two larger than the number of vertical lines the player + uses, and change the ten in line 150 to one greater than the + number of lines. To add horizontal movement, add the following + lines: + + 6 HPOS = 53248 + 230 IF STICK(0) = 11 THEN X = X - 1: + POKE HPOS, X + 240 IF STICK(0) = 7 THEN X = X + 1: + POKE HPOS, X + + You can use the routine to move any player by changing the + number 511 in the USR calls to one less than the start address of the + object to be moved. See the appendix for a map of P/M graphics + memory use. Missiles are more difficult to move vertically with this + routine, since it moves an entire byte, not bits. It would be useful + for moving all four missiles vertically if you need to do so; they + could still be moved horizontally in an individual manner. + See COMPUTE!, December 1981, February 1982, and May 1982, + for some solutions and some machine language move routines, and + COMPUTE!, October 1981, for a solution with animation involving + P/M graphics. + + + M0PF + + (R) Missile 0 to playfield collision. This register will tell you which + playfield the object has "collided" with, i.e., overlapped. If missile + 0 collides with playfield two, the register would read four and so + on. Bit use is: + + Bit 7 6 5 4 3 2 1 0 + Playfield .....unused..... 3 2 1 0 + Decimal ................ 8 4 2 1 + + + 53249 D00l HOPSP1 + + (W) Horizontal position of player 1. + + + M1PF + + (R) Missile 1 to playfield collision. + + + 53250 D002 HPOSP2 + + (W) Horizontal position of player 2. + + + M2PF + + (R) Missile 2 to playfield collision. + + + 53251 D003 HPOSP3 + + (W) Horizontal position of player 3. + + + M3PF + + (R) Missile 3 to playfield collision. + + + 53252 D004 HPOSM0 + + (W) Horizontal position of missile 0. Missiles move horizontally like + players. See the note in 53248 ($D000) concerning the use of + horizontal registers. + + + P0PF + + (R) Player 0 to playfield collisions. There are some problems using + collision detection in graphics modes nine to eleven. There are no + obviously recognized collisions in GR.9 and GR.11. In GR.10 + collisions work only for the playfield colors that correspond to the + usual playfield registers. Also, the background (BAK) color is set + by PCOLR0 (location 704; $2C0) rather than the usual COLOR4 + (location 712; $2C8), which will affect the priority detection. In + GR.10, playfield colors set by PCOLR0 to PCOLR3 (704 to 707; + $2C0 to $2C3) behave like players where priority is concerned. Bit + use is: + + Bit 7 6 5 4 3 2 1 0 + Playfield .....unused..... 3 2 1 0 + Decimal ................ 8 4 2 1 + + + 53253 D005 HPOSM1 + + (W) Horizontal position of missile 1. + + + P1PF + + (R) Player 1 to playfield collisions. + + + 53254 D006 HPOSM2 + + (W) Horizonal position of missile 2. + + + P2PF + + (R) Player 2 to playfield collisions. + + + 53255 D007 HPOSM3 + + (W) Horizontal position of missile 3. + + + P3PF + + (R) Player 3 to playfield collisions. + + + 53256 D008 SIZEP0 + + (W) Size of player 0. POKE with zero or two for normal size (eight + color clocks wide), POKE with one to double a player's width + (sixteen color clocks wide), and POKE with three for quadruple + width (32 color clocks wide). Each player can have its own width set. + A normal size player might look something like this: + + 00011000 + 00111100 + 01111110 + 11111111 + 11111111 + 01111110 + 00111100 + 00011000 + + In double width, the same player would like this: + + 0000001111000000 + 0000111111110000 + 0011111111111100 + 0011111111111100 + 0000111111110000 + 0000001111000000 + + In quadruple width, the same player would become: + + 00000000000011111111000000000000 + 00000000111111111111111100000000 + 00001111111111111111111111110000 + 11111111111111111111111111111111 + 11111111111111111111111111111111 + 00001111111111111111111111110000 + 00000000111111111111111100000000 + 00000000000011111111000000000000 + + Bit use is: + + Bit 7 6 5 4 3 2 1 0 + Size: .....unused..... 0 0 Normal (8 color clocks) + 0 1 Double (16 color clocks) + 1 0 Normal + 1 1 Quadruple (32 color clocks) + + + M0PL + + (R) Missile 0 to player collisions. There is no missile-to-missile + collision register. Bit use is: + + Bit 7 6 5 4 3 2 1 0 + Player ..unused.. 3 2 1 0 + Decimal .......... 8 4 2 1 + + + 53257 D009 SIZEP1 + + (W) Size of player 1. + + + M1PL + + (R) Missile 1 to player collisions. + + + 53258 D00A SIZEP2 + + (W) Size of player 2. + + + M2PL + + (R) Missile 2 to player collisions. + + + 53259 D00B SIZEP3 + + (W) Size of player 3. + + + M3PL + + (R) Missile 3 to player collisions. + + + 53260 D00C SIZEM + + (W) Size for all missiles; set bits as below (decimal values + included): + + Bits Size: + Normal Double Quadruple + 7 & 6: missile 3 0,128 64 192 + 5 & 4: missile 2 0, 32 16 48 + 3 & 2: missile l 0, 8 4 12 + 1 & 0: missile 0 0, 2 1 3 + + where turning on the bits in each each pair above does as follows: + + 0 and 0: normal size -- two color clocks wide + 0 and 1: twice normal size -- four color clocks wide + 1 and 0: normal size + 1 and 1: four times normal size -- eight color clocks wide + + So, to get a double-sized missile 2, you would set BITs 5 and 6, or + POKE 53260,48. Each missile can have a size set separately from + the other missiles or players when using the GRAF registers. + A number of sources, including De Re Atari, say that you can set + neither missile sizes nor shapes separately. Here's a routine to + show that you can in fact do both: + + 10 POKE 53265,255: REM SHAPE START + 15 GR.7 + 20 POKE 623,1: REM SET PRIORITIES + 30 FOR X = 1 TO 25 + 35 F = 50 + 40 FOR C = 704 TO 707: POKE C,F + X: + F = F + 50: NEXT C: REM COLOURS + 45 S = 100 + 50 FOR P = 53252 TO 53255: POKE P,S + + X: S = S + 20: NEXT P : REM SCRE + EN POSITIONS + 60 NEXT X + 70 INPUT A,B: REM MISSILE SIZE AND S + HAPES + 80 POKE 53260,A: POKE 53265,5 + 100 GOTO 30 + + Here's another example using DMA; GRACTL and DACTL + (53277 and 54272; $D0lD and $D400): + + 10 POKE 623,1: POKE 559,54: POKE 542 + 79, 224: POKE 53277,1 + 20 FOR N = 53252 TO 53255: POKE N, 1 + 00 + X: X = X + 10: NEXT N: X = 0 + 30 INPUT SIZE: POKE 53260, SIZE + 40 GOTO 30 + + See 54279 ($D407) for more information on P/M graphics. + + + P0PL + + (R) Player 0 to player collisions. Bit use is: + + Bit 7 6 5 4 3 2 1 0 + Player ...unused.... 3 2 1 0 + Decimal ............. 8 4 2 1 + + + 53261 D00D GRAFP0 + + (W) Graphics shape for player 0 written directly to the player + graphics register. In using these registers, you bypass ANTIC. + You only use the GRAFP# registers when you are not using + Direct Memory Access (DMA: see GRACTL at 53277). If DMA is + enabled, then the graphics registers will be loaded automatically + from the area specified by PMBASE (54279; $D407). + + The GRAF registers can only write a single byte to the playfield, + but it runs the entire height of the screen. Try this to see: + + 10 POKE 53248, 160: REM SET HORIZONT + AL POSITION OF PLAYER 0 + 20 POKE 704, 245: REM SET PLAYER 0 C + OLOUR TO ORANGE + 30 POKE 53261, 203: REM BIT PATTERN + 11001011 + + To remove it, POKE 53261 with zero. The bit order runs from + seven to zero, left to right across the TV screen. Each bit set will + appear as a vertical line on the screen. A value of 255 means all + bits are set, creating a wide vertical line. You can also use the + size registers to change the player width. Using the GRAF + registers will allow you to use players and missiles for such things + as boundaries on game or text fields quite easily. + + + P1PL + + (R) Player 1 to player collisions. + + + 53262 D00E GRAFP1 + + (W) Graphics for player 1. + + + P2PL + + (R) Player 2 to player collisions. + + + 53263 D00F GRAFP2 + + (W) Graphics for player 3. + + + P3PL + + (R) Player 3 to player collisions. + + + 53264 D010 GRAFP3 + + (W) Graphics for player 3. + + + TRIG0 + + (R) Joystick trigger 0 (644). Controller jack one, pin six. For all + triggers, zero equals button pressed, one equals not pressed. If + BIT 2 of GRACTL (53277; $D01D) is set to one, then all TRIG + BITs 0 are latched when the button is pressed (set to zero) and are + only reset to one (not pressed) when BIT 2 of GRACTL is reset to + zero. The effect of latching the triggers is to return a constant + "button pressed" read until reset. + + + 53265 D011 GRAFM + + (W) Graphics for all missiles, not used with DMA. GRAFM works + the same as GRAFP0 above. Each pair of bits represents one + missile, with the same allocation as in 53260 ($D00C) above. + + Bit 7 6 5 4 3 2 1 0 + Missile -3- -2- -1- -0- + + Each bit set will create a vertical line running the entire height of + the TV screen. Missile graphics shapes may be set separately + from each other by using the appropriate bit pairs. To mask out + unwanted players, write zeros to the bits as above. + + + TRIG1 + + (R) Joystick trigger 1 (645). Controller jack two, pin six. + + + 53266 D012 COLPM0 + + (W) Color and luminance of player and missile 0 (704). Missiles + share the same colors as their associated players except when + joined together to make a fifth player. Then they take on the same + value as in location 53733 ($D019; color register 3). + + + TRIG2 + + (R) Joystick trigger 2 (646). Controller jack three, pin six. + + + 53267 D013 COLPM1 + + (W) Color and luminance of player and missile 1 (705). + + + TRIG3 + + (R) Joystick trigger 3 (647). Controller jack four, pin six. + + + 53268 D014 COLPM2 + + (W) Color and luminance of player and missile 2 (706). + + + PAL + + (R) Used to determine if the Atari is PAL (European and Israeli + TV compatible when BITs 1 - 3 equal zero) or NTSC (North + American compatible when BITs 1 - 3 equal one; 14 decimal, $E). + European Ataris run 12% slower if tied to the VBLANK cycle (the + PAL VBLANK cycle is every 50th second rather than every 60th + second). They use only one CPU clock at three MHZ, so the 6502 + runs at 2.217 MHZ -- 25% faster than North American Ataris. + Also, their $E000 and $F000 ROMs are different, so there are + possible incompatibilities with North American Ataris in the + cassette handling routines. There is a third TV standard called + SECAM, used in France, the USSR, and parts of Africa. I am + unaware if there is any Atari support for SECAM standards. + + PAL TV has more scan lines per frame, 312 compared to 262. + NTSC Ataris compensate by adding extra lines at the beginning + of the VBLANK routine. Display lists do not have to be altered, + and colors are the same because of a hardware modification. + + + 53269 D015 COLPM3 + + Color and luminance of player and missile 3 (707). + + + 53270 D016 COLPF0 + + Color and luminance of playfield zero (708). + + + 53271 D017 COLPF1 + + Color and luminance of playfield one (709). + + + 53272 D018 COLPF2 + + Color and luminance of playfield two (710). + + + 53273 D019 COLPF3 + + Color and luminance of playfield three (711). + + + 53274 D01A COLBK + + Color and luminance of the background (BAK).(712). + + + 53275 D01B PRIOR + + (W) Priority selection register. PRIOR establishes which objects + on the screen (players, missiles, and playfields) will be in front of + other objects. Values used in this register are also described at + location 623 ($26F), the shadow register. If you use conflicting + priorities, objects whose priorities are in conflict will turn black + in their overlap region. + + Priority order + (Decimal values in brackets): + + Bit 0 = 1 (1): Bit 1 = 1 (2): + Player 0 Player 0 + Player 1 Player 1 + Player 2 Playfield 0 + Player 3 Playfield 1 + Playfield 0 Playfield 2 + Playfield 1 Playfield 3 and Player 5 + Playfield 2 Player 2 + Playfield 3 and Player 5 Player 3 + Background Background + + Bit 2 = 1 (4): Bit 3 = 1 (8): + Playfield 0 Playfield 0 + Playfield 1 Playfield 1 + Playfield 2 Player 0 + Playfield 3 and Player 5 Player 1 + Player 0 Player 2 + Player 1 Player 3 + Player 2 Playfield 2 + Player 3 Playfield 3 and Player 5 + Background Background + + Bit 4 = 1: Enable a fifth player out of the four missiles. + + Bit 5 = 1: Overlap of players 0 and 1, 2 and 3 is third color (else + overlap is black). The resulting color is a logical OR of the two + player colors. + + Bits 6 and 7 are used to select GTIA modes: + 0 0 = no GTIA modes + 0 1 = GTIA GR.9 + 1 0 = GTIA GR.10 + 1 1 = GTIA GR.11 + + + 53276 D01C VDELAY + + (W) Vertical delay register. Used to give one-line resolution + movement capability in the vertical positioning of an object when + the two line resolution display is enabled. Setting a bit in + VDELAY to one moves the corresponding object down by one TV + line. If DMA is enabled, then moving an object by more than one + line is accomplished by moving bits in the memory map instead. + + Bit Decimal Object + 7 128 Player 3 + 6 64 Player 2 + 5 32 Player 1 + 4 16 Player 0 + 3 8 Missile 3 + 2 4 Missile 2 + 1 2 Missile 1 + 0 1 Missile 0 + + + 53277 D01D GRACTL + + (W) Used with DMACTL (location 54272; $D400) to latch all stick + and paddle triggers (to remember if triggers on joysticks or + paddles have been pressed), to turn on players and to turn on + missiles. To get the values to be POKEd here, add the following + options together for the desired function: + + Decimal Bit + To turn on missiles 1 0 + To turn on players 2 1 + To latch trigger inputs 4 2 + + To revoke P/M authorization and turn off both players and + missiles, POKE 53277,0. Once latched, triggers will give a + continuous "button pressed" read the first time they are pressed + until BIT 2 is restored to zero. Triggers are placed in "latched" + mode when each individual trigger is pressed, but you cannot set + the latch mode for individual triggers. + + Have you ever hit BREAK during a program and still had players + or their residue left on the screen? Sometimes hitting RESET + doesn't clear this material from the screen. There are ways to get + rid of it: + + POKE 623,4: This moves all players behind playfields. + POKE 53277,0: This should turn them off. + POKE 559,2: This should return you to a blank screen. + + Make sure you SAVE your program before POKEing, just in + case! + + + 53278 D01E HITCLR + + (W) POKE with any number to clear all player/missile collision + registers. It is important to clear this register often in a program + -- such as a game -- which frequently tests for collisions. + Otherwise, old collision values may remain and confuse the + program. A good way to do this is to POKE HITCLR just before + an event which may lead to a collision; for example, right before + a joystick or paddle is "read" to move a player or fire a missile. + Then test for a collision immediately after the action has taken + place. Remember that multiple collisions cause sums of the + collision values to be written to the collision registers; if you do + not clear HITCLR often enough, a program checking for + individual collisions will be thrown off by these sums. + + + 53279 D01F CONSOL + + (W/R) Used to see if one of the three yellow console buttons has + been pressed (not the RESET button!). To clear the register, + POKE CONSOL with eight. POKEing any number from zero to + eight will cause a click from the speaker. A FOR-NEXT loop that + alternately POKEs CONSOL with eight and zero or just zero, + since the OS put in an 8 every 1/60 second, will produce a buzz. + Values PEEKed will range from zero to seven according to the + following table: + + |Key Value 0 1 2 3 4 5 6 7 | + | | + +------------------------------------------------------------+ + | | + |OPTION X X X X | + |SELECT X X X X | + |START X X X X | + | | + +------------------------------------------------------------+ + Bits 2 0 0 0 0 1 1 1 1 + 1 0 0 1 1 0 0 1 1 + 0 0 1 0 1 0 1 0 1 + + + Where zero means all keys have been pressed, one means + OPTION and SELECT have been pressed, etc., to seven, which + means no keys have been pressed. CONSOL is updated every + stage two VBLANK procedure with the value eight. + + It is possible to use the console speaker to generate different + sounds. Here is one idea based on an article in COMPUTE!, + August 1981: + + 10 GOSUB 1000 + 20 TEST = USR(1536) + 999 END + 1000 FOR LOOP = 0 TO 26: READ BYTE: P + OKE 1536 + LOOP, BYTE: NEXT LOOP + : RETURN + 1010 DATA 104,162,255,169,255,141,31, + 208,169 + 1020 DATA 0,160,240,136,208,253,141,3 + 1,208,160 + 1030 DATA 240,136,208,253,202,208,233 + ,96 + + To change the tone, you POKE 1547 and 1555 with a higher or + lower value (both are set to 240 above). To change the tone + duration, you POKE 1538 with a lower value (it is set to 255 in the + routine above). Do these before you do your USR call or alter the + DATA statements to permanently change the values in your own + program. Turn off DMA (see location 559) to get clearer tones. + + --------------------------------------------------------------------------- + Locations 53280 to 53503 ($D020 to $D0FF) are repeats of locations + 53248 to 53279 ($D000 to $D01F). You can't use any of the repeated + locations; consider them "filler." They maybe used for other purposes + in any Atari OS upgrade. + + --------------------------------------------------------------------------- + Locations 53504 to 53759 ($D100 to $D1FF) are unused. These loca- + tions are not empty; you can PEEK into them and find out what's + there. They cannot, however, be user-altered. + + --------------------------------------------------------------------------- + + + POKEY + + 53760-54015 D200-D2FF + + POKEY is a digital I/O chip that controls the audio frequency and + control registers, frequency dividers, poly noise counters, pot + (paddle) controllers, the random number generator, keyboard + scan, serial port I/O, and the IRQ interrupts. + + The AUDF# (audio frequency) locations are used for the pitch for + the corresponding sound channels, while the AUDC# (audio + control registers) are the volume and distortion values for those + same channels. To POKE sound values, you must first POKE zero + into locations 53768 ($D208) and a three into 53775 ($D20F). + + Frequency values can range from zero to 255 ($FF), although the + value is increased by the computer by one to range from one to + 256. Note that the sum of the volumes should not exceed 32, since + volume is controlled by the least four bits. It is set from zero as no + volume to 15 ($F) as the highest. A POKE with 16 ($10) forces + sound output even if volume is not set (i.e., it pushes the speaker + cone out. A tiny "pop" will be heard). The upper four bits control + distortion: 192 ($C0) is for pure tone; other values range from 32 to + 192. Note that in BASIC, the BREAK key will not turn off the + sound; RESET will, however. See De Re Atari and BYTE, April + 1982, for more information on sound generation. + + The AUDF registers are also used as the POKEY hardware timers. + These are generally used when counting an interval less than one + VBLANK. For longer intervals, use the software timers in locations + 536 to 545 ($218 to $221). You load the AUDCTL register with the + number for the desired clock frequency. You then set the volume + to zero in the AUDC register associated with the AUDF register + you plan to use as a timer. You load the AUDF register itself with + the number of clock intervals you wish to count. Then you load + your interrupt routine into memory, and POKE the address into the + appropriate timer vector between locations 528 and 533 ($210 and + $215). You must set the proper bit(s) in IRQEN and its shadow + register POKMSK at location 16 ($10) to enable the interrupt. + Finally, you load STIMER with any value to load and start the + timer(s). The OS will force a jump to the timer vector and then to + your routine when the AUDF register counts down to zero. Timer + processing can be preempted by ANTIC's DMA, a DLI, or the + VBLANK process. + + POT values are for the paddles, ranging from zero to 240, + increasing as the paddle knob is turned counterclockwise, but + values less than 40 and greater than 200 represent an area on + either edge of the screen that may not be visible on all TV sets or + monitors. + + + 53760 D200 AUDF1 + + (W) Audio channel one frequency. This is actually a number (N) + used in a "divide by N circuit"; for every N pulses coming in (as set + by the POKEY clock), one pulse goes out. As N gets larger, output + pulses will decrease, and thus the sound produced will be a lower + note. N can be in the range from one to 256; POKEY adds one to + the value in the AUDF register. See BYTE, April 1982, for a + program to create chords instead of single tones. + + + POT0 + + (R) Pot (paddle) 0 (624); pot is short for potentiometer. Turning the + paddle knob clockwise results in decreasing pot values. For + machine language use: these pot values are valid only 228 scan + lines after the POTGO command or after ALLPOT changes (see + 53768; $D208 and 53771; $D20B). POT registers continually count + down to zero, decrementing every scan line. They are reset to 228 + when they reach zero or by the values read from the shadow + registers. This makes them useful as system timers. See + COMPUTE!, February 1982, for an example of this use. + + The POTGO sequence (see 53771; $D20B) resets the POT + registers to zero, then reads them 228 scan lines later. For the fast + pot scan, BIT 2 of SKCTL at 53775 ($D20F) must be set. + + + 53761 D201 AUDC1 + + (W) Audio channel one control. Each AUDF register has an + associated control register which sets volume and distortion levels. + The bit assignment is: + + Bit 7 6 5 4 3 2 1 0 + Distortion Volume Volume + (noise) only level + 0 0 0 0 0 0 0 0 Lowest + 0 0 1 0 0 0 1 + etc. to: etc. to: + 1 1 1 1 1 1 1 1 Highest + (forced + output) + + The values for the distortion bits are as follows. The first process is + to divide the clock value by the frequency, then mask the output + using the polys in the order below. Finally, the result is divided by + two. + + Bit + 7 6 5 + 0 0 0 five bit, then 17 bit, polys + 0 0 1 five bit poly only + 0 1 0 five bit, then four bit, polys + 0 1 1 five bit poly only + 1 0 0 l7 bit poly only + 1 0 1 no poly counters (pure tone) + 1 1 0 four bit poly only + 1 1 1 no poly counters (pure tone) + + In general, the tones become more regular (a recognizable + droning becomes apparent) with fewer and lower value polys + masking the output. This is all the more obvious at low frequency + ranges. POKE with 160 ($A0) or 224 ($E0) plus the volume for pure + tones. + + See De Re Atari and the Hardware Manual for details. + + + POT1 + + (R) Pot 1 register (625). + + + 53762 D202 AUDF2 + + (W) Audio channel two frequency. Also used with AUDF3 to store + the 19200 baud rate for SIO. + + + POT2 + + (R) Pot 2 (626). + + + 53763 D203 AUDC2 + + (W) Audio channel two control. + + + POT3 + + (R) Pot 3 (627). + + + 53764 D204 AUDF3 + + (W) Audio channel three frequency. Used with AUDF3 above and + with AUDF4 to store the 600 baud rate for SIO. + + + POT4 + + (R) Pot 4 (628). + + + 53765 D205 AUDC3 + + (W) Audio channel three control. + + + POT5 + + (R) Pot 5 (629). + + + 53766 D206 AUDF4 + + (W) Audio channel four frequency. + + + POT6 + + (R) Pot 6 (630). + + + 53767 D207 AUDC4 + + (W) Audio channel four control. + + + POT7 + + (R) Pot 7 (631). + + + 53768 D208 AUDCTL + + (W) Audio control. To properly initialize the POKEY sound + capabilities, POKE AUDCTL with zero and POKE 53775,3 + ($D20F). These two are the equivalent of the BASIC statement + SOUND 0,0,0,0. AUDCTL is the option byte which affects all + sound channels. This bit assignment is: + + Bit Description: + 7 Makes the 17 bit poly counter into nine bit poly + (see below) + 6 Clock channel one with 1.79 MHz + 5 Clock channel three with 1.79 MHz + 4 Join channels two and one (16 bit) + 3 Join channels four and three (16 bit) + 2 Insert high pass filter into channel one, clocked by channel + two + 1 Insert high pass filter into channel two, clocked by channel + four + 0 Switch main clock base from 64 KHz to 15 KHz + + Poly (polynomial) counters are used as a source of random pulses + for noise generation. There are three polys: four, five and 17 bits + long. The shorter polys create repeatable sound patterns, while the + longer poly has no apparent repetition. Therefore, setting BIT 7 + above, making the 17-bit into a nine-bit poly will make the pattern + in the distortion more evident. You chose which poly(s) to use by + setting the high three bits in the AUDC registers. The 17-bit poly is + also used in the generation of random numbers; see 53770 + ($D20A). + + The clock bits allow the user to speed up or slow down the clock + timers, respectively, making higher or lower frequency ranges + possible. Setting the channels to the 1.79 MHz will produce a + much higher sound, the 64 KHz clock will be lower, and the 15 + KHz clock the lowest. The clock is also used when setting the + frequency for the AUDF timers. + + Two bits (three and four) allow the user to combine channels one + and two or three and four for what amounts to a nine octave range + instead of the usual five. Here's an example from De Re Atari of + this increased range, which uses two paddles to change the + frequency: the right paddle makes coarse adjustments, the left + paddle makes fine adjustments: + + 10 SOUND 0,0,0,0:POKE 53768,80:REM SE + T CLOCK AND JOIN CHANNELS 1 AND 2 + 20 POKE 53761,160:POKE 53763,168:REM + TURN OFF CHANNEL 1 AND SET 2 TO PU + RE TONE GENERATION + 50 POKE 53760,PADDLE(0):POKE 53762,PA + DDLE(1):GOTO 30 + + High pass filters allow only frequencies higher than the clock value + to pass through. These are mostly used for special effects. Try: + + 10 SOUND 0,0,0,0:POKE 53768,4:REM HIG + H PASS FILTER ON CHANNEL 1 + 20 POKE 53761,168:POKE 53765,168:REM + PURE TONES + 30 POKE 53760,254:POKE 53764,127 + 40 GOTO 40 + + See the excellent chapter on sound in De Re Atari: it is the best + explanation of sound functions in the Atari available. See also the + Hardware Manual for complete details. + + + ALLPOT + + (R) Eight line pot port state; reads all of the eight POTs together. + Each bit represents a pot (paddle) of the same number. If a bit is + set to zero, then the register value for that pot is valid (it's in use); if + it is one, then the value is not valid. ALLPOT is used with the + POTGO command at 53771 ($D20B). + + ---------------------------------------------------------------------- + + 53769 D209 STIMER + + (W) Start the POKEY timers (the AUDF registers above). You + POKE any non-zero value here to load and start the timers; the + value isn't itself used in the calculations. This resets all of the audio + frequency dividers to their AUDF values. If enabled by IRQEN + below, these AUDF registers generate timer interrupts when they + count down from the number you POKEd there to zero. The + vectors for the AUDF1, AUDF2 and AUDF4 timer interrupts are + located between 528 and 533 ($210 and $215). POKEY timer four + interrupt is only enabled in the new "B" OS ROMs. + + + KBCODE + + (R) Holds the keyboard code which is then loaded into the shadow + register (764; $2FC) when a key is hit. Usually read in response to + the keyboard interrupt. Compares the value with that in CH1 at + 754 ($2F2). If both values are the same, then the new code is + accepted only if a suitable key debounce delay time has passed. + The routines which test to see if the key code will be accepted start + at 65470 ($FFBE). BIT 7 is the control key flag, BIT 6 is the shift key + flag. + + + 53770 D20A SKREST + + (W) Reset BITs 5 - 7 of the serial port status register at 53775 to one. + + + RANDOM + + (R) When this location is read, it acts as a random number + generator. It reads the high order eight bits of the 17 bit + polynomial counter (nine bit if BIT 7 of AUDCTL is set) for the + value of the number. You can use this location in a program to + generate a random integer between zero and 255 by: + + 10 PRINT PEEK(53770) + + This is a more elegant solution than INT(RND(0) * 256). For a test of + the values in this register, use this simple program: + + 10 FOR N = 1 TO 20: PRINT PEEK(53770): NEXT N + + + 53771 D20B POTGO + + (W) Start the POT scan sequence. You must read your POT values + first and then start the scan sequence, since POTGO resets the + POT registers to zero. Written by the stage two VBLANK + sequence. + + + 53772 D20C .... + + Unused. + + + 53773 D20D SEROUT + + (W) Serial port data output. Usually written to in the event of a + serial data out interrupt. Writes to the eight bit (one byte) parallel + holding register that is transferred to the serial shift register when a + full byte of data has been transmitted. This "holding" register is + used to contain the bits to be transmitted one at a time (serially) as + a one-byte unit before transmission. + + + SERIN + + (R) Serial port input. Reads the one-byte parallel holding register + that is loaded when a full byte of serial input data has been + received. As above, this holding register is used to hold the bits as + they are received one bit at a time until a full byte is received. This + byte is then taken by the computer for processing. Also used to + verify the checksum value at location 49 ($31). + + The serial bus is the port on the Atari into which you plug your + cassette or disk cable. For the pin values of this port, see the OS + User's Manual, p. 133, and the Hardware Manual. + + + 53774 D20E IRQEN + + (W) Interrupt request enable. Zero turns off all interrupt requests + such as the BREAK key; to disable or re-enable interrupts, POKE + with the values according to the following chart (setting a bit to one + -- i.e., true -- enables that interrupt; decimal values are also + shown for each bit): + + Bit Decimal Interrupt Vector + 0 1 Timer 1 (counted down to zero) VTIMR1 + (528; $210) + 1 2 Timer 2 (counted down to zero) VTIMR2 + (530; $212) + 2 4 Timer 4 (counted down to zero) VTIMR4 + (532; $214), OS + "B" ROMs only) + 3 8 Serial output transmission done VSEROC (526; + $20E) + 4 16 Serial output data needed VSEROR + (524; $20C) + 5 32 Serial input data ready VSERIN + (522; $20A) + 6 64 Other key pressed VKEYBD + (520; $208) + 7 128 BREAK key pressed see below + + Here is the procedure for the BREAK key interrupt: clear the + interrupt register. Set BRKKEY (17; $11) to zero; clear the + start/stop flag SSFLAG at 767 ($2FF); clear the cursor inhibit flag + CRSINH at 752 ($2F0); clear the attract mode flag at 77 ($4D), and + return from the interrupt after restoring the 6502 A register. (There + is now (in the OS "B" ROMs) a proper vector for BREAK key + interrupts at 566, 567 ($236, $237) which is initialized to point to + 59220 ($E754).) If the interrupt was due to a serial I/O bus proceed + line interrupt, then vector through VPRCED at 514 ($202). If due to + a serial I/O bus interrupt line interrupt, then vector through + VINTER at 516 ($204). If due to a 6502 BRK instruction, then vector + through VBREAK at 518 ($206). + + Timers relate to audio dividers of the same number (an interrupt is + processed when the dividers count down to zero). These bits in + IRQEN are not set on powerup and must be initiated by the user + program before enabling the processor IRQ. + There are two other interrupts, processed by PIA, generated over + the serial bus Proceed and Interrupt lines, set by the bits in the + PACTL and PBCTL registers (54018 and 54019; $D302, $D303): + + Bit Decimal Locution Interrupt + 0 1 PACTL Peripheral A (PORTA) interrupt enable + bit. + 7 128 PACTL Peripheral A interrupt status bit. + 0 1 PBCTL Peripheral B (PORTB) interrupt enable + bit. + 7 128 PBCTL Peripheral B interrupt status bit. + + The latter PORT interrupts are automatically disabled on powerup. + Only the BREAK key and data key interrupts are enabled on + powerup. The shadow register is 16 ($10). + + + IRQST + + (R) Interrupt request status. Bit functions are the same as IRQEN + except that they register the interrupt request when it is zero rather + than the enable when a bit equals one. IRQST is used to determine + the cause of interrupt request with IRQEN, PACTL and PBCTL as + above. + + All IRQ interrupts are normally vectored through 65534 ($FFFE) to + the IRQ service routine at 59123 ($E6F3), which determines the + cause of the interrupt. The IRQ global RAM vector VIMIRQ at 534 + ($216) ordinarily points to the IRQ processor at 59126 ($E6F6). The + processor then examines 53774 ($D20E) and the PIA registers at + 54018 and 54019 to determine the interrupt cause. Once + determined, the routine vectors through one of the IRQ RAM + vectors in locations 514 to 526 ($202 to $20E). For Non-Maskable + Interrupts (NMI's), see locations 54286 to 54287 ($D40E; $D40F). + See the OS User's Manual for complete details. + + + 53775 D20F SKCTL + + (W) Serial port control. Holds the value 255 ($255) if no key is + pressed, 251 ($FB) for most other keys pressed, 247 ($F7) for + SHIFT key pressed (*M). See the (R) mode below for an + explanation of the bit functions. POKE with three to stop the + occasional noise from cassette after I/O to bring POKEY out of the + two-tone mode. (562). + + + SKSTAT + + (R) Beads the serial port status. It also returns values governed by + a signal on the digital track of the cassette tape. You can generate + certain values using the SOUND command in BASIC and a PEEK + to SKSTAT: + + SOUND 0,5,10,15 returns a value to here of 255 (or, on + occasion, 127). + SOUND 0,8,10,3 returns a value of 239. + + This is handy for adding a voice track to Atari tapes. You use the + left channel for your voice track and the right for the tone(s) you + want to use as cuing marks. You can use the speaker on your TV to + generate the tones by placing the right microphone directly in + front of the speaker. The computer will register these tones in this + register when it encounters them during a later cassette load. See + COMPUTE!, July 1981, for some other suggestions on doing this. + Bemember, you can turn the cassette off by POKEing 54018 + ($D302) with 60 ($3C) and back on with 52 ($34). + + Bits in the SKCTL (W) register are normally zero and perform the + functions below when set to one. The status when used as (R) is + listed below the write (W) function: + + Bit Function + 0 (W) Enable keyboard debounce circuits. + (R) Not used by SKSTAT. + 1 (W) Enable keyboard scanning circuit. + (R) Serial input shift register busy. + 2 (W) Fast pot scan: the pot scan counter completes its + sequence in two TV line times instead of one frame time (228 + scan lines). Not as accurate as the normal pot scan, + however. + (R) the last key is still pressed. + 3 (W) Serial output is transmitted as a two-tone signal rather + than a logic true/false. POKEY two-tone mode. + (R) The shift key is pressed. + 4,5,6 (W) Serial port mode control used to set the bi-directional + clock lines so that you can either receive external clock data + or provide clock data to external devices (see the Hardware + Manual, p. II.27). There are two pins on the serial port for + Clock IN and Clock OUT data. See the OS User's Manual, + p. 133. + 4 (R) Data can be read directly from the serial input port, + ignoring the shift register. + 5 (R) Keyboard over-run. Reset BITs 7 to 5 (latches) to one + using SKRES at 53770 ($D20A). + 6 (R) Serial data input over-run. Reset latches as above. + 7 (W) Force break (serial output to zero). + (R) Serial data input frame error caused by missing or extra + bits. Beset latches as above. + + BIT 2 is first set to zero to reset POT registers to zero (dumping the + capacitors used to change the POT registers). Then BIT 2 is set to + one to enable the fast scan. Fast scan is not as accurate as the + normal scan routine. BIT 2 must be reset to zero to enable the + normal scan mode; otherwise, the capacitors will never dump. + + --------------------------------------------------------------------------- + Locations 53776 to 54015 ($D210 to $D2FF) are duplications of locations + 53760 to 53775 and have no particular use at present. + + --------------------------------------------------------------------------- + + + PIA: 6520 CHIP + + 54016-54271 D300-D3FF + + The Peripheral Interface Adapter (PIA) integrated circuit is a + special microprocessor used to control the Atari ports, controller + jacks one to four. Ports can be used for both input and output + simultaneously or alternately. Barely tapped at the time of this + writing, the ports represent a major resource for external (and + internal) control and expansion. PIA also processes two of the IRQ + interrupts: VINTER and VPRCED, vectored at locations 514 to 517 + ($202 to $205). These interrupts are unused by the OS, but also + may be used to provide greater control over external devices. + + + 54016 D300 PORTA + + (W/R) Reads or writes data from controller jacks one and two if BIT + 2 of PACTL (location 54018) is one. Writes to direction control if + BIT 2 of PACTL is zero. + + These two port registers also control the direction of data flow to + the port, if the controller register (54018, below) is POKEd with 48 + ($30). Then, if the bits in the register read zero, it is in input (R) + mode; if they read one, it is in output (W) mode. A zero POKEd + here makes all bits input, a 255 ($FF) makes all bits output. BITs 0 + to 3 address pins one to four on jack one, BITs 4 to 7 address pins + one to four on jack two. POKE 54018 with 52 to make this location + into a data register again. Shadow registers are: STICK0 (632; + $278, jack one), STICK1 (633; $279, jack two) and PTRIG0-3 + (636-639; $27C-$27F). + + Bits used as data register + 7 6 5 4 3 2 1 0 + --Jack 0-- --Jack 1-- + --Stick 1-- --Stick 0-- + + Forward = BIT 0, 4 = 1 + Backward = BIT 1, 5 = 1 + Left = BIT 2,6 = 1 + Right = BIT 3,7 = 1 + Neutral = All four jack bits = 1 + + PORTA is also used to test if the paddle 0-3 triggers (PTRIG) have + been pressed, using these bits: + + Bit 7 6 5 4 3 2 1 0 + PTRIG 3 2 - - 1 0 - - + + Where zero in the appropriate bit equals trigger pressed, one + equals trigger not pressed. + + The PORT registers are also used in the keyboard controller (used + with a keypad) operation where: + + Bit 7 6 5 4 3 2 1 0 + Row 4 3 2 Top 4 3 2 Top + Jack ..........2.......... ..........1........... + + Columns for the keyboard operation are read through the POT + (PADDL) and TRIG registers. See Micro, May 1982, and the + Hardware Manual for more information on jacks and ports. + + + 54017 D301 PORTB + + (W/R) Port B. Reads or writes data to and/or from jacks three and + four. Same as PORTA, above, for the respective jacks. Shadow + registers are: STICK2 (634; $27A, jack three), STICK3 (635, $27B, + jack four), and PTRIG4-7 (640-643; $280-$283). + + + 54018 D302 PACTL + + (W/R) Port A controller (see 54016 above). POKE with 60 ($3C) to + turn the cassette motor off, POKE with 52 to turn it on. You can put + a music cassette in your program recorder, press PLAY and then + POKE 54018,52. Your music will play through the TV speaker or + external amplifier while you work at the Atari. You can use this + technique to add voice tracks to your programs. To turn off the + music or voice, type POKE 54018,60. + + PACTL can be used for other external applications by the user. Bit + use is as follows: + + Bit Function + 7 (read only) Peripheral A interrupt (IRQ) status bit. Set by + Peripheral (PORT) A. Reset by reading PORTA + (53774; $D20E). + 6 Set to zero. + 5 Set to one. + 4 Set to one. + 3 (write) Peripheral motor control line (turn the cassette on + or off; zero equals on). + 2 (write) Controls PORTA addressing. One equals PORTA + register; zero equals direction control register. + 1 Set to zero. + 0 (write) Peripheral A interrupt (IRQ) enable. One equals + enable. Set by the OS but available to the user; + reset on powerup. + + + 54019 D303 PBCTL + + (W/R) Port B controller. Initialized to 60 ($3C) by the OS IRQ + code. PBCTL is the same as PACTL, above, with the following + exception (this may actually perform the same function as in + PACTL, but I am not sure of the distinction between descriptions): + + Bit Function + 3 Peripheral command identification (serial bus + command), initialized to 60 ($3C). + + Ports can be used for external control applications by the + technically minded reader who is willing to do some soldering to + develop cables and connectors. A good example can be found in + COMPUTE!, February 1981, where the author gives directions for + using jacks three and four as a printer port. The Macrotronic + printer cables use just this method, bypassing the 830 interface + entirely (one way of reducing your hardware costs). Theoretically, + the entire Atari can be controlled through the ports! + + --------------------------------------------------------------------------- + Locations 54020 to 54271 ($D304 to $D3FF) are repeats of locations + 54016 to 54019 ($D300 to $D303). + + --------------------------------------------------------------------------- + + + ANTIC + + 54272-54783 D400-D5FF + + ANTIC is a special, separate microprocessor used in your Atari + to control C/GTIA, the screen display, and other screen-related + functions including processing the NMI interrupts. It uses its own + instruction set, called the display list, which tells ANTIC where to + find the screen data in RAM and how to display it. ANTIC also + uses an internal four bit counter called the Delta Counter (DCTR) + to control the vertical dimension of each block. + + + 54272 D400 DMACTL + + (W) Direct Memory Access (DMA) control. It is also used to + define one- or two-line resolution for players and to turn on + players and missiles. Values are POKEd into the shadow register, + 559 ($22F), and are also described there. You POKE the shadow + register with the following numbers in order to: + + Turn off the playfield 0 + Use narrow playfield 1 + Use normal playfield 2 + Use wide playfield 3 + Enable missile DMA 4 + Enable player DMA 8 + Enable both player and missile DMA 12 + Single line player resolution 16 + Enable DMA Fetch instructions 32 + + Double line resolution is the default status. Use this register in + conjunction with GRACTL at 53277 ($D01D). Both must be set + properly or no display will result. BIT 5 enables DMA to fetch the + display list instructions. If BIT 5 is not set (BIT 5 equals zero), + ANTIC will not work. DMACTL is initialized to 34 ($22). + A player in single line resolution might look like this: + + 00011000 ## + 00111100 #### + 01111110 ###### + 11111111 ######## + 11111111 ######## + 01111110 ###### + 00111100 #### + 00011000 ## + + so that each byte is displayed on one TV line. The same player in + double line resolution would look like this: + + 00011000 ## + 00011000 ## + 00111100 #### + 00111100 #### + 01111110 ###### + 01111110 ###### + 11111111 ######## + 11111111 ######## + 11111111 ######## + 11111111 ######## + 01111110 ###### + 01111110 ###### + 00111100 #### + 00111100 #### + 00011000 ## + 00011000 ## + + where every byte is displayed over two TV lines. + + + 54273 D401 CHACTL + + (W) Character mode control. See shadow register 755 for values + that can be POKEd in. Only the least three bits (decimal zero to + seven) are read, as below: + + Decimal 0 1 2 3 4 5 6 7 + Cursor + Transparent X X X X + Opaque X X X X + Present X X X X + Absent X X X X + ---------------------------------------------------------------------- + Characters + Normal X X X X + Inverted X X X X + + + 54274,5 D402,3 DLISTL/H + + Display list pointer. Tells the OS the address of the display list + instructions about what screen mode(s) to display and where to + find the screen data. See SDLIST (560, 561; $230, $231). + + + 54276 D404 HSCROL + + (W) Horizontal scroll enable, POKE HSCROL with from zero to + 16 clock cycles for the number of cycles to scroll. Horizontal fine + scrolls can be used only if BIT 4 of the display list instruction is + set. The difficulty in horizontal scrolling lies in arranging the + screen data to be scrolled in such a manner as to prevent + wraparound (i.e., the bit or byte scrolled off screen in one line + becomes the bit or byte scrolled on screen in an adjacent line). + Normal data arranged for TV display looks like this on the screen: + + +----------+ + |..........| + |..........| + |..........| + |..........| + |..........| + |..........| + +----------+ + + where it is a one-dimensional memory area "folded" at the proper + places to create the image of a two dimensional screen. This is + done by the DL character or map mode instruction. Without + other instructions, it reads the memory continuously from the first + specified location, each line taking the correct number of bytes + for the GRAPHICS mode specified. To properly scroll it + horizontally, you must arrange it in relation to the TV screen like + this: + + +----------+ + .....|..........|..... + .....|..........|..... + .....|..........|..... + .....|..........|..... + .....|..........|..... + .....|..........|..... + +----------+ + + Now you will have to make each display instruction for each line + into a Load Memory Scan (LMS) instruction. To direct each LMS + to the proper screen RAM for that line, you will have to increment + each memory location by the total length of the line. For + example, if you want to scroll a 256-byte horizontal screen, each + LMS instruction will have to point to a location in memory 256 + bytes above the last one. Of course, you will have to implement + error-trapping routines so that your screen does not extend + beyond your desired boundaries. + + Coarse scrolling, one byte at a time, can be done without setting + the HSCROL register by the method described above. For + smooth scrolling, you will have to use this register. See De Re + Atari. + + + 54277 D405 VSCROL + + (W) Vertical scroll enable, POKE VSCROL with from zero to 16 + scan lines, depending on the GRAPHICS mode of the screen for + the number of scan lines to scroll. Vertical fine scrolls can be + used only if BIT 5 of the display list instruction has been set. + + Coarse scrolling can be done without using this register, simply + by moving the top of the screen address (as defined by the DL + LMS instruction) up or down one mode line (plus or minus 40 or + 20 bytes, depending on the GRAPHICS mode). The top of the + screen address can be found by: + + 10 DLIST = PEEK(560) + PEEK(561) * 2 + 56 + 20 SCRNLO = DLIST + 4: SCRNHI = DLIS + T + 5: REM LSB/MSB OF SCREEN ADDRE + SS + 25 PRINT "SCREEN ADDRESS = " PEEK(SC + RNLO) + PEEK(SCRNHI) * 256 + + You could then add a routine to this for a coarse - scroll vertically + through the memory with a joystick, such as: + + 30 LOBYTE = 0: HIBYTE = 0 + 40 IF STICK(0) = 14 THEN LOBYTE = LO + BYTE + 40:GOTO 100 + 50 IF STICK(0) = 13 THEN LOBYTE = LO + BYTE - 40 + 60 IF LOBYTE < 0 THEN LOBYTE = LOBYT + E + 256: HIBYTE = HIBYTE - 1 + 70 IF HIBYTE < 0 THEN HIBYTE = 0 + 80 GOTO 200 + 100 IF LOBYTE 255 THEN LOBYTE = LOB + YTE - 256 + 110 HIBYTE = HIBYTE + 1 + 200 POKE SCRNLOW, LOBYTE: POKE SCRNHI + , HIBYTE + 210 GOTO 40 + + DOWNLOAD VSCROL.BAS + + Coarse scrolling is relatively easy to implement in the Atari: one + basically alters the screen RAM to display the new material. Fine + scrolling is more difficult: each scroll register must be POKEd + with the number of units to be scrolled -- color clocks or scan + lines -- and the corresponding display list instructions must have + the proper bits set. This means you can selectively fine scroll any + mode lines you wish by setting only those bits of the lines you + intend to scroll. Other lines will be displayed normally. You can + set a DL instruction for both horizontal and vertical scroll enable. + See the Hardware Manual for a discussion of the problems in fine + scrolling. + + Fine scrolling will allow only a certain amount of data to be + scrolled before the register must be reset (16 clock bits or scan + lines maximum). In order to make the scrolling activity + continuous, the register involved must be reset to zero when the + desired value is reached, a coarse scroll must be implemented + (usually during a DLI or VBLANK interval) and a new fine scroll + begun. This is not easily done in BASIC since it is too slow, and + changing registers during ANTIC's display process usually + causes rough or jerky motion. Assembly routines are suggested + for smooth display. See De Re Atari, Micro, November 1981, + BYTE, January 1982, and Santa Cruz's Tricky Tutorial #2 for + more information. + + + 54278 D406 .... + + Unused. + + + 54279 D407 PMBASE + + (W) MSB of the player/missile base address used to locate the + graphics for your players and missiles (the address equals + PMBASE * 256. P/M graphics are tricky to use since there are no + direct Atari 8K BASIC commands to either create or move them + (there are, however, commands for P/M graphics in BASIC A+ + and in valFORTH utilities). + + Your P/M graphics must always begin on a 1K boundary + (PEEK(RAMTOP)-4 for double line resolution players) or 2K + boundary (PEEK(RAMTOP)-5 for single line resolution), so the + LSB is always zero (page numbers always end in $XX00). For + example: + + 10 POKE 106, PEEK(106) - 8: GRAPHIC + S 8: SETCOLOR 2,3,4 + 20 POKE 559,62: POKE 53248,100: POK + E 704,160: POKE 53256,2 + 30 MEM = PEEK(106) - 8 + 40 POKE 54279, MEM: POKE 53277,3: S + TART = MEM * 256 + 1024 + 50 FOR LOOP = 100 TO 119: READ BYTE + : POKE START + LOOP, BYTE: NEXT LO + OP + 60 DATA 16,16,56,40,40,56,40,40,40 + 70 DATA 124,84,124,84,254,146,254,1 + 70,170,68 + 100 END + + You can change the color, width, resolution, and horizontal + position of the player in the example by altering the registers + used above. + + Each player is one byte (eight bits) wide. Single line resolution + P/M characters (POKE 559,62) can be up to 256 bytes high. + Double line resolution P/M characters (POKE 559,46) can be up + to 128 bytes high. In either case, they can map to the height of the + screen. Missiles have the same height, but are only two bits wide + each. Four missiles can be combined into a fifth player by setting + BIT 4 of location 623 ($26F). You need not fill the entire height of + a P/M character, but you should POKE unused bytes with zero to + eliminate any screen garbage. You can do this by: + + FOR N = PMBASE + 1024 TO PMBASE + 2048: + POKE N,0: NEXT N + + where PMBASE is the starting address of the reserve memory + area. In double line resolution, change the loop value to N = + PMBASE + 512 TO PMBASE + 1024. Here's a short machine + language routine to do the same thing. You would put the start + address of the area to be loaded with zero and the number of + bytes to be cleared in with the USR call as the first two + parameters. In this example, I have arbitrarily chosen 38012 and + 2048 for these values. + + 10 START = 38012: BYTE = 2048: DIM + PGM$(42) + 20 FOR LOOP = 1 TO 42: READ ML: PGM + $(LOOP, LOOP) = CHR$(ML): NEXT LOO + P + 30 DATA 104,104,133,204,104,133,203 + ,104,133,206,104 + 40 DATA 133,205,166,206,160,0,169,0 + ,145,203,136 + 50 DATA 208,251,230,204,202,48,6,20 + 8,244,164 + 60 DATA 205,208,240,198,204,160,0,1 + 45,203,96 + 70 A = USR(ADR(PGM$),START,BYTE) + + You can use this routine to clear out memory anywhere in the + Atari. You can also use it to load any one value into memory by + changing the second zero (after the 169) in line 40 to the value + desired. + + Locating your graphics tables at the high end of memory may + cause addressing problems for playfield graphics, or may leave + some of the display unusable and cause PLOT to malfunction. If + you locate your tables just before the screen display, it may be + erased if you change graphics modes. You can look at your + highest RAM use graphics statement and plan accordingly. To + calculate a safe starting address below the display list, try: + + 100 DLIST = PEEK(560) + PEEK(561) * 256: PMBASE = + INT (DLIST/SIZE -1) * SIZE + + where SIZE is 2048 for single line resolution, 1024 for double + line. + + Once you have the starting address, determine the ending + address of your table by adding the correct number of bytes for + the size (same as the SIZE variable above), and POKE this + number (LSB/MSB) into APPMHI at locations 14 and 15 ($E, $F). + This sets the lower limit for playfield graphics memory use. If you + change graphics modes in the program now, it should leave your + player tables intact. For example, if the DL is at 39968, the + PMBASE will equal 36864 in the equation above. Add 2048 + (single line resolution) to get 38912. This is $9800. In decimal, + the LSB is zero and the MSB is 152. POKE these values into + APPMHI. This sets the lowest limit to which the screen and DL + data may descend. + + The unused portion of the RAM set aside for P/M use, or any + RAM reserved for players, but not used, may be used for other + purposes in your program such as machine language routines. + See the appendix for a map of P/M memory use. The register + stores the address as below: + + Bit 7 6 5 4 3 2 1 0 + One line resolution: ......MSB....... ...unused... + Two line resolution: ........MSB......... unused.. + + There are some restrictions on locating your P/M data above the + display list. If not positioned far enough above your screen data, + you may end up with both the normal and screen data being + displayed at once, resulting in garbage on the screen. A display + list may not cross a 1K boundary without a jump instruction, and + the screen display RAM cannot cross a 4K boundary without an + LMS instruction to point to the proper byte(s). Due to problems + that arise when moving the GR.7 and GR.8 screens and data less + than 4K, you should never reserve less than 16 pages above + RAMTOP in these modes. If you are reserving more, add the + pages in blocks of 4K (16 pages). + See COMPUTE!, September 1981, for a discussion of the + problems of positioning P/M graphics in memory, and using P/M + graphics for animation. + See De Re Atari, COMPUTE!, June 1982, and Creative + Computing, April 1982, for a discussion of using string + manipulation with P/M graphics. See Your Atari 400/800 for a + general discussion of P/M graphics. Most of the popular + magazines have also carried articles on simplifying P/M + graphics. + + + 54280 D408 .... + + Unused. + + + 54281 D409 CHBASE + + (W) Character base address; the location of the start of the + character set, either the standard Atari set or a user-designed set. + The default is 224 ($E0), which points to the start of the Atari + ROM character set. Iridis, a short-lived disk -and- documentation + magazine, produced a good utility called FontEdit to aid in the + design of altered character sets. Online Systems' program The + Next Step is also very useful for this purpose, as is COMPUTE!'s + "SuperFont," January 1982. Uses shadow register 756 ($2F4). + Normally, this points to location 57344 or 57856 ($E000 or $E200) + depending on your choice of characters used in which text mode. + GRAPHICS mode zero uses the entire 128-character set; GR.1 + and GR.2 use only half the set (64 characters). You POKE a + different number into the shadow register at 756 ($2F4) to point to + your own character set in RAM. This must be an even number + that points to a page in memory that is evenly divisible by two. In + GR.1 and GR.2 this number is 224 (pointing to $E000), giving + you uppercase, punctuation and numbers. POKEing the shadow + or this location (in machine language) with 226 will give you + lowercase and control characters. + See the information about the ROM character set at 57344 + ($E000). + + + 54282 D40A WSYNC + + (W) Wait for horizontal synchronization. Allows the OS to + synchronize the vertical TV display by causing the 6502 to halt + and restart seven machine cycles before the beginning of the + next TV line. It is used to synchronize the VBI's or DLI's with the + screen display. + To see the effect of the WSYNC register, type in the second + example of a Display List Interrupt at location 512. RUN it and + observe that it causes a clean separation of the colors at the + change boundary. Now change line 50 to: + + 50 DATA 72,169,222,234,234,234,141,24,208,104,64 + + This eliminates the WSYNC command. RUN it and see the + difference in the boundary line. + + The keyboard handler sets WSYNC repeatedly while generating + the keyboard click on the console speaker at 53279 ($D01F). + When interrupts are generated during the WSYNC period, they + get delayed by one scan line. To bypass this, examine the + VCOUNT register below and delay the interrupt processing by + one line when no WSYNC delay has occurred. + + + 54283 D40B VCOUNT + + (R) Vertical line counter. Used to keep track of which line is + currently being generated on the screen. Used during Display + List Interrupts to change color or graphics modes. PEEKing here + returns the line count divided by two, ranging from zero to 130 + ($82; zero to 155 on the PAL system; see 53268; $D014) for the + 262 lines per TV frame. + + + 54284 D40C PENH + + (R) Light pen horizontal position (564). Holds the horizontal color + clock count when the pen trigger is pressed. + + + 54285 D40D PENV + + (R) Light pen vertical position (565). Holds the VCOUNT value + (above) when the pen trigger is pressed. See the Hardware + Manual, p. II-32, for a description of light pen operation. + + + 54286 D40E NMIEN + + (W) Non-maskable interrupt (NMI) enable. POKE with 192 to + enable the Display List Interrupts. When BIT 7 is set to one, it + means DL instruction interrupt; any display list instruction where + BIT 7 equals one will cause this interrupt to be enabled at the + start of the last video line displayed by that instruction. When BIT + 6 equals one, it allows the Vertical Blank Interrupt and when BIT + 5 equals one, it allows the RESET button interrupt. The RESET + interrupt is never disabled by the OS. You should never press + RESET during powerup since it will be acted upon. + + NMIEN is set to 64 ($40) by the OS IRQ code on powerup, + enabling VBI's, but disabling DLI's. All NMI interrupts are + vectored through 65530 ($FFFA) to the NMI service routine at + 59316 ($E7B4) to determine their cause. + + Bit 7 6 5 4 3 2 1 0 + Interrupt: DLI VBI RESET .... unused ..... + + + 54287 D40F NMIRES + + (W) Reset for NMIST (below); clears the interrupt request + register; resets all of the NMI status together. + + + NMIST + + (R) NMI status; holds cause for the NMI interrupt in BITs 5, 6 and + 7; corresponding to the same bits in NMIEN above. If a DLI is + pending, a jump is made through the global RAM vector + VDSLST (512; $200). The OS doesn't use DLI's, so 512 is + initialized to point to an RTI instruction and must be changed by + the user before a DLI is allowed. + + If the interrupt is not a DLI, then a test is made to see if the + interrupt was caused by pressing RESET key and, if so, a jump is + made to 58484 ($E474). If not a RESET interrupt, then the system + assumes the interrupt was a VBLANK interrupt, and a jump is + made through VVBLKI at 546 ($222), which normally points to + the stage one VBLANK processor. From there it checks the flag at + CRITIC (66; $42) and, if not from a critical section, jumps + through VVBLKD at 548 ($224), which normally points to the + VBLANK exit routine. On powerup, the VBLANK interrupts are + enabled while the display list interrupts are disabled. See the end + of the memory map for a description of the VBLANK procedures. + For IRQ interrupts, see location 53744 ($D20E). + + --------------------------------------------------------------------------- + Locations 54288 to 54303 ($D410 to $D41F) are repeats of locations + 54272 to 54287 ($D400 to $D40F). + + --------------------------------------------------------------------------- + Locations 54784 to 55295 ($D600 to $D7FF) are unused but not empty + nor user alterable. See the note at 53504 ($D100). + + --------------------------------------------------------------------------- + + OPERATING SYSTEM ROM + + Locations 55296 to 65535 ($D800 to $FFFF) are the OS ROM. + These locations are contained in the 10K ROM cartridge, which sits in + the front slot of the Atari 800 or inside the Atari 400. The OS is + identical for both computers. + + The locations given here are for the "A" version of the OS ROMs. + There are changes in the new "B" version ROMs, which are explained + in the appendix. Most of the changes affect the interrupt handler + routines and SIO. In making these changes, Atari cured some bugs + such as the device time-out problem. Unfortunately, there is a cloud + with this silver lining: not all of your old software will run with the new + ROMs. Megalegs, one of my favorite games, cannot run under the new + ROMs. A pity that. There are others; I'm sure you'll find them. The + solution is to have both sets of ROMs so you can use all of your + software. + + + FLOATING POINT PACKAGE ROM + + Locations 55296 to 57343 ($D800 to $DFFF) are reserved for the ROM's + Floating Point Mathematics Package. There are other areas used by the + FP package: page zero (locations 212 to 254; $D4 to $FE) and page five + (locations 1406 to 1535; $57E to $5FF), which are used only if FP + routines are called. There are also trigonometric functions in the BASIC + cartridge located between 48549 and 49145 ($BDA5 to $BFF9) which + use the FP routines. See De Re Atari for more information. + + These are the entry points to some of the subroutines; unless otherwise + noted, they use FP register zero (FR0 at 212 to 217, $D4 to $DB): + + + 55296 D800 AFP + + ASCII to Floating Point (FP) conversion. + + + 55526 D8E6 FASC + + FP value to ASCII conversion. + + + 55722 D9AA IFP + + Integer to FP conversion. + + + 55762 D9D2 FPI + + FP to integer conversion. + + + 55876 DA44 ZFR0 + + Clear FR0 at 212 to 217 ($D4-$DB) by setting all bytes to zero. + + + 55878 DA46 ZF1 + + Clear the FP number from FR1, locations 224 to 229 ($E0 to $E5), + by setting all bytes to zero. Also called AF1 by De Re Atari. + + + 55904 DA60 FSUB + + FP subtract routine, the value in FR0 minus the value in FR1. + + + 55910 DA66 FADD + + FP addition routine; FR0 plus FR1. + + + 56027 DADB FMUL + + FP multiplication routine; FR0 times FR1. + + + 56104 DB28 FDIV + + FP division routine; FR0 divided by FR1. + + + 56640 DD40 PLYEVL + + FP polynomial evaluation. + + + 56713 DD89 FLD0R + + Load the FP number into FR0 from the 6502 X,Y registers. + + + 56717 DD8D FLD0P + + Load the FP number into FR0 from user routine, using FLPTR at + 252 ($FC). + + + 56728 DD98 FLD1R + + Load the FP number into FR1 from the 6502 X,Y registers. + + + 56732 DD9C FLD1P + + Load the FP number into FR1 from user program, using FLPTR. + + + 56743 DDA7 FST0R + + Store the FP number into the 6502 X,Y registers from FR0. + + + 56747 DDAB FST0P + + Store the FP number from FR0, using FLPTR. + + + 56758 DDB6 FMOVE + + Move the FP number from FR0 to FR1. + + + 56768 DDC0 EXP + + FP base e exponentiation. + + + 56780 DDCC EXP10 + + FP base 10 exponentiation. + + + 57037 DECD LOG + + FP natural logarithm. + + + 57041 DED1 LOG10 + + FP base 10 logarithm. + + --------------------------------------------------------------------------- + Locations 57344 to 58367 ($E000 to $E3FF) hold the standard Atari + character set: at $E000 the special characters, punctuation and numbers + begin; at $E100 (57600) the capital letters begin; at $E200 (57856) the + special graphics begin, and at $E300 (58112) the lowercase letters + begin. + + There are 1024 bytes here ($400), with each character requiring eight + bytes, for a total of 128 characters (inverse characters simply manipulate + the information here to reverse the bits by performing an OR with 128 -- + the value in location 694 ($2B6) when the Atari logo key is toggled -- on + the bits. To return to the normal ATASCII display, the inverse characters + are EORed with 128). The first half of the memory is for numerals, + punctuation, and uppercase characters; the second half ($E200 to + $E3FF) is for lowercase and control characters. When you POKE 756 + ($2F4) with 224 ($E0), you are POKEing it with the MSB of this address + ($E000). When you POKE it with 226 ($E2), you are moving the address + pointer to the second half of the character set. In GR.0, you have the + entire character set to use. In GR.1 and GR.2, you can use only one half + of the set at a time. You can't POKE it with 225 because the number + POKEd must be evenly divisible by two. + + The characters stored here aren't in ATASCII order; they have their own + internal order for storage. The order of the characters is listed on page + 55 of your BASIC Reference Manual. + + Here's an example of how a letter (A) is stored in ROM. Each line + represents a byte. The decimal values are those you'd find if you + PEEKed the eight locations where "A" is stored (starting at 57608; + $E108): + + Bit 76543210 Decimal + +--------+ + 00000000 0 | | + 00011000 24 | ## | + 00111100 60 | #### | + 01100110 102 | ## ## | + 01100110 102 | ## ## | + 01111110 126 | ###### | + 01100110 102 | ## ## | + 00000000 0 | | + +--------+ + + When you create your own character sets (or alter the Atari set + when you move it to RAM -- see location 756; $2F4 for a routine + to do this), you do a "bit-map" for each character as in the + example above. It could as easily be a spaceship, a Hebrew + letter, an APL character, or a face. Chris Crawford's game + Eastern Front 1941 (APX) shows excellent use of an altered + character set to create his large map of Russia, plus the symbols + for the armies. + + Here's an example of using the bit-mapping of the character set + to provide text in GRAPHICS 8: + + 1 GRAPHICS 8 + 5 DLIST = PEEK(560) + PEEK(561)*256 + 6 LOBYTE = DLIST+4: HIBYTE = DLIST + + 5 + 7 REAL = PEEK(LOBYTE) + PEEK(HIBYTE) + *256: SCREEN = REAL: TV = SCREEN + 10 CHBASE = 57344 + 20 DIM A$(128),BYTE(128),WANT(128) + 27 PRINT "INPUT A 40 CHARACTER STRIN + G:" + 30 INPUT A$ + 35 TIME = TIME + 1 + 40 FOR LOOK = 1 TO LEN(A$) + 50 BYTE(LOOK) = ASC(A$(LOOK,LOOK)) + 51 IF BYTE(LOOK) > 127 THEN BYTE(LOO + K) = BYTE(LOOK) - 128 + 52 IF BYTE(LOOK) < 32 THEN BYTE(LOOK + ) = BVTE(LOOK) + 64: GOTO 55 + 53 IF BYTE(LOOK) < 97 THEN BVTE(LOOK + ) = BYTE(LOOK) - 32 + 55 NEXT LOOK + 59 FOR EXTRA = 0 TO 7 + 60 FOR LOOK = 1 TO LEN(A$) + 70 WANT(LOOK) = PEEK(CHBASE + EXTRA + + BYTE(LOOK)*8) + 80 POKE TV + EXTRA, WANT(LOOK): TV = + TV + 1 + 82 NEXT LOOK + 85 SCREEN = SCREEN + 39: TV = SCREEN + 90 NEXT EXTRA + 100 SCREEN = REAL + TIME*320 + 110 IF SCREEN > REAL + 6080 THEN TIM + E = 0: GOTO 100 + 120 GOTO 30 + + DOWNLOAD BITMAP8.BAS + + This program simply takes the bytes which represent the letters + you input as A$ and finds their places in the ROM character set. + It then proceeds to POKE the bytes into the screen RAM, using a + FOR-NEXT loop. + + To convert ATASCII codes to the internal codes, use this table: + + ATASCII value Operation for + internal code + 0 -- 31 add 64 + 32 -- 95 subtract 32 + 96 -- 127 remains the same + 128 -- 159 add 64 + 160 -- 223 subtract 32 + 224 -- 255 remains the same + + See COMPUTE!, November 1981, for the program "TextPlot" + which displays text in different sizes in GRAPHICS modes three + to eight, and January 1982 for a program to edit character sets, + "SuperFont." + + --------------------------------------------------------------------------- + + Locations 58368 to 58447 ($E400 to $E44F) are the vector tables, stored + as LSB, MSB. These base addresses are used by resident handlers. + Handler vectors use the following format: + + OPEN vector + CLOSE vector + GET BYTE vector + PUT BYTE vector + GET STATUS vector + SPECIAL vector + Jump to handler initialization routine (JMP LSB/MSB) + + The device tables in location 794 ($31A) point to the particular + vector(s) used in each appropriate table. In each case, the 6502 X + register is used to point to the originating IOCB. + + + 58368 E400 EDITRV + + Screen Editor (E:) entry point table. + + + 58383 E40F .... + + If you PEEK here and get back 56, then you have the older "A" + version of the OS ROMs. If you get back zero, then you have the + newer "B" version that was released in January 1982. The "B" + version fixes some minor bugs, including the device time-out + problems, enables POKEY timer four, and provides a vector for + BREAK key interrupts. See Appendix 4. + + + 58384 E410 SCRENV + + Display handler (television screen) (S:). + + + 58400 E420 KEYBDV + + Keyboard handler (K:). + + + 58416 E430 PRINTV + + Printer handler (P:). + + + 58432 E440 CASETV + + Cassette handler (C:). + + --------------------------------------------------------------------------- + Locations 58448 to 58533 ($E450 to $E4A5) are more vectors: those to + location 58495 ($E47F) are Jump vectors, those from 58496 to 58533 + ($E480 to $E4A5) are the initial RAM vectors. + + + 58448 E450 DISKIV + + Disk handler initialization vector, initialized to 60906 ($EDEA). + + + 58451 E453 DSKINV + + Disk handler (interface) entry; checks the disk status. Initialized + to 60912 ($EDF0). + + + 58454 E456 CIOV + + Central Input/Output (CIO) utility entry. CIO handles all of the + I/O operations or data transfers. Information placed in the + IOCB's tells CIO what operations are necessary. CIO passes this + information to the correct device driver routine and then passes + control to the Device Control Block (DCB). This in turn calls up + SIO (below) to control the actual peripheral(s). CIO treats all I/O + in the same manner: device independent. The differentiation + between operations is done by the actual device drivers. + + You jump to here to use the IOCB handler routines in ROM. + BASIC supports only record I/O or one-byte-at-a-time I/O (GET + and PUT). Addressing CIOV directly will allow the user to input + or output a buffer of characters at a time, such as loading a + machine language program directly into memory from a disk file. + This is considerably faster than using BASIC functions such as + GET. Here is a typical machine language subroutine to do this: + + PLA, PLA, PLA, TAX, JMP $E456 + (104,104,104,170,76,86,228) + ($68,$68,$68,$AA,$4C,$56,$E4) + + This gets the IOCB number into the 6502 X register and the + return address on the stack. CIOV expects to find the IOCB + number 16 in the 6502 X register (i.e., IOCB zero is zero, IOCB + one is 16; $10, IOCB two is 32, $20, etc.). $E456 is the CIO + initialization entry point (this address). + + To use CIOV in a program, first you must have OPENed a + channel for the appropriate actions, POKEd the correct IOCB + (locations 848 to 959; $350 to $3BF) with the correct values, and + established a location in which to load your file (IOCB address + plus four and plus five). One use is calling up a high-res picture + from a disk and storing it in the screen memory (locations 88, 89; + $58, $59). You can POKE the appropriate decimal values into + memory and call it with a USR call, or make it into a string + (START$ = "hhh*LVd" where the * and the d are both inverse + characters) and call it by: + + JUMP = USR(ADR(START$)) + + This method is used to start the concurrent mode in the RS-232 of + the 850 interface in the 850 Interface Manual. See location 88, 89 + ($58, $59) for another example of the machine language routine + technique. Still another use of this method can be found in De Re + Atari. Initialized to 58564 ($E4C4). + + + 58457 E459 SIOV + + Serial Input/Output (SIO) utility entry point. SIO drives the + serial bus and the peripherals. When a request is placed in the + Device Control Block (DCB) by a device handler, SIO takes + control and uses the data in the DCB to perform the operation + required. SIO takes care of the transfer of data as defined by the + DCB. CIO (above) is responsible for the "packaging" of the data + and transfers control to SIO when necessary. See the DCB + locations 768 to 779 ($300-$30B). + SIO first sends a command frame to the device, consisting of five + bytes: the device ID, the command BYTE, two auxiliary bytes for + device-specific information, then a checksum (which is the sum + of the first four bytes). If the device acknowledges this frame, it is + followed, if necessary, by the data frame of a fixed number of + bytes depending on the device record size, plus a checksum + byte. Initialized to 59737 ($E959). + + + 58460 E45C SETVBV + + Set system timers during the VBLANK routine. Uses the 6502 X + register for the MSB of vector/times, Y for the LSB and A for the + number of the vector to hack (change). SETVBV insures that both + bytes of the vector addressed will be updated while VBLANK is + enabled. You can JSR here when creating your own timer + routines. See COMPUTE!, November 1981, for an application. + Initialized to 59666 ($E912) old ROMs, 59629 ($E8ED) new + ROMs. + + + 58463 E45F SYSVBV + + Stage one VBLANK calculations entry. It performs the + processing of a VBLANK interrupt. Contains JMP instruction for + the vector in the next two addresses (58464, 58465; $E460, + $E461). This is the address normally found in VVBLKI (546, 547; + $222, $223). It is initialized to 59345 ($E7D1), which is the + VBLANK routine entry. Initialized to 59345 ($E7D1) old ROMs, + 59310 ($E7AE) new ROMs. + + + 58466 E462 XITVBV + + Exit from the VBLANK routine, entry point. Contains JMP to the + address stored in next two locations (58467, 58468; $E463, + $E464). This is the address normally found in VVBLKD (548, 549; + $224, $225). Initialized to 59710 ($E93E), which is the VBLANK + exit routine. It is used to restore the computer to its pre-interrupt + state and to resume normal processing. Initialized to 59710 + ($E93E) old ROMs, 59653 ($E905) new ROMs. + + + 58469 E465 SIOINV + + SIO utility initialization, OS use only. + + + 58472 E468 SENDEV + + Send enable routine, OS use only. + + + 58475 E46B INTINV + + Interrupt handler initialization, OS use only. + + + 58478 E46E CIOINV + + CIO utility initialization, OS use only. + + + 58481 E471 BLKBDV + + Blackboard mode entry. Blackboard mode is the "ATARI MEMO + PAD" mode. It can be reached from BASIC by typing "BYE", + "B." or by powering up with no peripherals or cartridges. + Nothing you write to the screen in blackboard mode is acted + upon by the computer. You can enter this mode to protect your + programs temporarily from prying and curious fingers. + + All of the screen editing commands continue to work in + blackboard mode. You can enter blackboard mode from any + graphics mode with a text window; the display screen will remain + intact on the screen while the text window will be in blackboard + mode. Pressing RESET will, of course, return the entire screen to + GR.0. You can also enter blackboard mode from a program, but + cannot get out of it in BASIC once you are in it. + + If you entered blackboard mode from BASIC, you can return to it + by pressing RESET. Any BASIC program will still be there. So + will any RS-232 or DOS handlers previously booted. Initialized to + 61987 ($F223). + + + 58484 E474 WARMSV + + Warmstart entry point (RESET button vector). Initializes the OS + RAM region. The RESET key produces an NMI interrupt and a + chip reset (see below). Jump to here on an NMI caused by + pressing the RESET key. Initialized to 61723 ($F11B). + + + 58487 E477 COLDSV + + Coldstart (powerup) entry point. Initializes the OS and user RAM + regions; wipes out any program in memory. Initialized to 61733 + ($F125). + + + 58490 E47A RBLOKV + + Cassette read block routine entry, OS use only. + + + 58493 E47D CSOPIV + + Cassette OPEN for input vector, OS use only. + + + 58496 E480 VCTABL + + RAM vector initial value table. + + --------------------------------------------------------------------------- + + The following are the addresses for the handler routines: + + + 58534-59092 E4A6-E6D4 CIOORG + + Addresses for the Central Input/Output routines (CIO): + + + 58534 ($E4A6) CIOINT + + is the CIO initialization routine called by the monitor on powerup. + + + 58577 ($E4D1); + + move the user IOCB to the ZIOCB. + + + 58596 ($E4E4); + + check for a valid command. + + + 58633 ($E509); + + OPEN command routines. + + + 58675 ($E533); + + CLOSE command routines. + + + 58702 ($E54E); + + STATUS and special command routines. + + + 58729 ($E569) CIREAD; + + process the CIO commands for read and + write, including buffer check for full or empty. + + + 58907 ($E61B); + + routine to return to the user from CIO. + + + 58941 ($E63D), + + routines to compute the device handler entry point, + jump to the handler, transfer control, and then return to CIO after the + operation. + + + 59093-59715 E6D5-E943 INTORG + + Addresses for the interrupt handler routines: + + + 59123 ($E6F3) PIRQ; + + IRQ interrupt service routines start here. + + + 59126 ($E6F6); + + the immediate IRQ vector to the IRQ handler. The + global NMI and IRQ RAM vectors in locations 512 to 527 ($200 to $20F) + are all initialized to this area (59142, $E706 for the new OS ROMs). + + + 59314 ($E7B2); + + the vector for the IRQ interrupts on powerup; it + points to a PLA and RTI instruction sequence (new OS ROMs; 59219; + $E78F). + + + 59316 ($E7B4) PNMI; + + the NMI handler, tests for the reason for the + NMI, then jumps through the appropriate RAM vector. Also called the + Interrupt Service Routine (ISR). + + + 59345 ($E7D1) SYSVBL; + + the VBLANK routines start here, + including frame counter, update timer, update hardware registers + from shadow registers, update the attract mode counter and the + realtime clock. The vertical blank immediate vector, VVBLKL1, + normally pointed to by locations 546, 547 ($222, $223), points to here. + The Updated OS ROMs point to 59310 ($E7AE). + + + 59666 ($E912) SETVBL; + + subroutines to set the VBLANK timers + and vectors. + + The vertical blank deferred interrupt, normally vectored from + locations 548, 549 ($224, $225), points to 59710 ($E93E). In the + Updated OS ROMs, it points to 59653 ($E905). In both cases they point + to the VBLANK exit routine. + + See page 104 of the OS User's Manual for a list of the vectors and + MICRO, January 1982, for an explanation of the VBLANK process. + + + 59716-60905 E944-EDE9 SIOORG + + Routines for the Serial Input/Output (SIO) routines: + + + 60011 ($EA6B) SEND; + + is the SIO send buffer routine entry. + + + 60048 ($EA90) ISRODN, + + is the serial output ready IRQ vector. + + + 60113 ($EAD1) ISRTD; + + is the serial output complete IRQ vector. + This is at 60111 ($EACF) in the new OS ROMs. + + + 60177 ($EB11) ISRSIR; + + is the serial input ready IRQ vector. This + is 60175 ($EB0F) in the new OS ROMs. + + + 60292 ($EB84) CASENT; + + is the start of the cassette handling code + SIO subroutine to set baud rate, tone values, inter-record gap, to load + the buffer from the cassette and to turn on the recorder motor. Write + routines are located in 61249 to 61666 ($EFF5 to $F0E2). + + + 60515 ($EC63) + + is the start of the disable POKEY interrupts routine + entry, which also disables the send and receive functions. + + + 60583 ($ECA7) COMPUT; + + is the subroutine to calculate baud + rate using the POKEY frequency registers and the VCOUNT timer. + The tables for the AUDF and VCOUNT values are between 60882 and + 60905 ($EDD2 and $EDE9). + + + 60906-61047 EDEA-EE77 DSKORG + + Routines for the disk handler. + Initialization is at DINIT, 60906 ($EDEA), entry is at DSKIF, 60912 + ($EDF0). + + + 61048-61248 EE78-EF40 PRNORG + + Routines for the printer handler. + + + 61249-61666 EF41-F0E2 CASORG + + Routines for the cassette handler. + + The buzz used in the cassette CLOAD command can be called up from + BASIC by: + + BUZZ = USR(61530). + + You can turn it off with the RESET key. While this isn't terribly + exciting, it points to the potential of using the console speaker for + sound instead of merely for beeps (the RAM location for the speaker is + at 53279; $D01F). See the speaker location and COMPUTE!, August + 1981, for a short routine to use the speaker for sound effects. + + + 61667-62435 F0E3-F3E3 MONORG + + Routines for the monitor handler. This is also the address area of + PWRUP, the powerup module (61733; $F125). Coldstart routines are + initialized to this location. The routine to check for cartridge + installation begins at 61845 ($F195). Hardware initialization begins at + 62081 ($F281). + + + 61723 ($F11B) RESET; + + the RESET button routine starts here. + + + 62081 ($F281) HARDI, + + the start of the hardware initialization + routines. + + + 62100 ($F294) OSRAM; + + the start of the OS RAM initialization + and setup routines. + + + 62159 ($F2CF) BOOT; + + the entry point for the disk boot routine. + + + 62189 ($F2ED) DOBOOT; + + the disk boot routine activation. + + + 62334 ($F37E) DOPEN; + + the entry point for the reinitialization + of disk software. + + + 62436-65535 F3E4-FFFF KBDORG + + Routines for the display and keyboard handler. The display + handler beqins at 62454 ($F3F6) and the keyboard handler + begins at 63197 ($F6DD), below. + + + 63038 F63E EGETCH + + Like the BASIC INPUT command, EGETCH gets a line from the + screen and keyboard, but only one character at a time. You must + do a JSR $F63E for each character input. This is also the address + of the beginning of the screen editor routines. + + + 63140 F6A4 EOUTCH + + This routine puts the character currently in the accumulator onto + the screen in the next print location. Similar to the BASIC PUT + command. + + + 63197 F6DD KGETC2 + + Beginning of the keyboard handler. + + + 63202 F6E2 KGETCH + + This routine waits for a key to be pressed and returns its value to + the accumulator (6502 register A). Similar to the BASIC GET + command. + + + 64428 FBAC SCROLL + + The screen scroll routine starts here. + + + 64764 FCFC DRAW + + Screen draw routines begin here, end at 65092 ($FE44). See + Creative Computing, March 1982, for an example of a + modification to the draw routines to avoid the "out-of-bounds" + error for use in GR.7+. + + + 65093-469 FE45-FFBD .... + + The ROM tables for display lists, ANTIC codes, control codes, + and ATASCII conversion codes. + + + 65470 FFBE PIRQQ + + Subroutines to test the acceptance of the last key pressed and to + process the debounce delay routines start here. + When a key is pressed, it initiates an IRQ through VKEYBD at + locations 520, 521 ($208, $209) to 65470 ($FFBE). This is the + keyboard service routine. It processes debounce, and SHIFT- + CTRL logic (see location 559; $22F); saves the internal keyboard + code in 754 ($2F2) and 764 ($2FC); sets the ATTRACT mode flag + at 77 ($4D) and sets location 555 ($22B -- SRTIMR) to 48 ($30). + + + 65528 FFF8 CHKSUN + + According to Softside Magazine, December 1981, if a PEEK here + returns 255, then you have the older OS ROM(s). There were + some troubles with cassette loads in the older ROMs that + sometimes require the following to cure: + + Do an LPRINT without a printer attached before CLOAD. This + clears the cassette buffer. + + Press RESET before CSAVEing or CLOADing will restore the + system to its initialization parameters and help with loading and + saving routines. + + There is a new OS available from Atari which fixes a bug that + would cause the I/O operations to "time out" for a few seconds. It + apparently does not alter any of the routines mentioned here. + + The chip reset interrupt (powerup) vectors through location + 65532 ($FFFC) to 58487 ($E477) where a JMP vector to the + powerup routine is located. A chip reset is not the same as + pressing the RESET key, which in itself does not generate a chip + reset. + + The NMI interrupts are vectored through 65530 ($FFFA) to the + NMI service routine (ISR) at 59316 ($E7B4), and all IRQ + interrupts are vectored through 65534 ($FFFE) to the IRQ service + routine at 59123 ($E6F3). In these service routine areas, the + cause of the interrupt is determined, and the appropriate action + is taken, either by the OS or through a JMP to a RAM vector + where a user routine exists. + + ---------------------------------------------------------------------- + + Return to Table of Contents | Previous Chapter | Next Chapter + + + + + + + + + + + + [IMG] + [IMG] diff --git a/mklevelinfo.pl b/mklevelinfo.pl new file mode 100644 index 0000000..56a8894 --- /dev/null +++ b/mklevelinfo.pl @@ -0,0 +1,91 @@ +#!/usr/bin/perl -w + +%struct = ( + 0 => [ 2, 'desc', "first 2 bytes are level number in screencodes" ], + 2 => [ 2, 'sub0', "a subroutine" ], + 4 => [ 2, 'sub1', "a subroutine" ], + 6 => [ 2, 'sub2', "a subroutine" ], + 8 => [ 2, 'sub3', "a subroutine" ], + 10 => [ 1, 'num_bombs', "number of bombs to pick up on this level" ], + 11 => [ 1, 'bullet_chance', '0 = no bullets' ], + 12 => [ 1, 'y_start', 'jumpman starting Y position' ], + 13 => [ 1, 'x_start', 'jumpman starting X position' ], + 14 => [ 2, 'offs', 'points to $0600' ], + 16 => [ 1, 'points_per_bomb', 'points awarded per bomb pickup (always $64 aka 100)' ], + 17 => [ 2, 'time_bonus', 'amount of time bonus at start of level' ], + 19 => [ 1, 'offs', 'always $00' ], + 20 => [ 2, 'unkn_table0', 'pointer to ROM table or $06xx' ], + 22 => [ 2, 'map0', 'map data' ], + 24 => [ 2, 'map1', 'map data' ], + 26 => [ 2, 'map2', 'map data' ], + 28 => [ 2, 'unkn_table1', 'unknown, pointer to a ROM table or $0000' ], + 30 => [ 2, 'offs', 'always $0000' ], + 32 => [ 2, 'sub4', '$06E6 for most levels, or else a ROM subroutine' ], + 34 => [ 2, 'sub5', '$06E6 for some levels, or else a ROM subroutine' ], + 36 => [ 2, 'sub6', 'always $9740 aka game_main_loop' ], + 38 => [ 2, 'sub_eol', 'called at end of level (all bombs picked up). $06E6 for all but level07' ], + 40 => [ 6, 'offs', 'all zeroes' ], + 46 => [ 9, 'offs', 'unknown' ], + 55 => [ 3, 'offs', 'unknown, always $00 $00 $00' ], + 58 => [ 2, 'offs', 'unknown, not a ROM address' ], + 60 => [ 4, 'offs', 'unknown, level05 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00' ], +); + +sub mkaddr { + return sprintf("\$%04x", $_[0]); +} + +sub mknum { + return sprintf("%02d", $_[0]); +} + +sub mkrange { + my ($level, $label, $start, $len, $type, $comment) = @_; + my $sa = mkaddr($start); + my $ea = mkaddr($start + $len - 1); + my $llab; + if($level >= 0) { + my $ll = sprintf("%02d", $level); + $llab = "level$ll"; + } else { + if($level == -609) { + $llab = "cur_level"; + } else { + $llab = "work_level"; + } + my $l = <<EOF; +label { name "${llab}_$label"; addr $sa; size $len; comment "$comment"; }; +EOF + return $l; + } + my $range = <<EOF; +range { name "${llab}_$label"; start $sa; end $ea; type $type; comment "$comment"; }; +EOF + return $range; +} + +for $level (-610,-609,0..11) { + $addr = 0xa000 + $level * 0x40; + for $offset (sort { $a <=> $b } keys %struct) { + my ($size, $label, $comment) = @{$struct{$offset}}; + if($level == 0 && $offset == 0) { + $comment = "64-byte level descriptors, 12 of them (1 per level). " . $comment; + } + + $type = 'bytetable'; + if(($label =~ /^sub/) or ($label =~ /^map/) or ($label =~ /^unkn_table/)) { + $type = 'addrtable'; + } + + if($label eq 'time_bonus') { + $type = 'wordtable'; + } + + if($label eq 'offs') { + $label .= "_" . mknum($offset); + } + + print mkrange($level, $label, $addr + $offset, $size, $type, $comment); + } + print "\n"; +} diff --git a/mkmusiclabels.pl b/mkmusiclabels.pl new file mode 100644 index 0000000..f47cbfe --- /dev/null +++ b/mkmusiclabels.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl -w + +$startaddr = 0; +$entry = 0; +do { + $startaddr = 0x8FC3 + $entry * 5; + printf 'range { name "mus%02d_addr1"; start $%04x; end $%04x; type addrtable; };%s', + $entry, $startaddr, $startaddr+1, "\n"; + printf 'range { name "mus%02d_addr2"; start $%04x; end $%04x; type addrtable; };%s', + $entry, $startaddr+2, $startaddr+3, "\n"; + printf 'range { name "mus%02d_len_or_tempo"; start $%04x; end $%04x; type bytetable; };%s', + $entry, $startaddr+4, $startaddr+4, "\n"; + print "\n"; + $entry++; +} while($startaddr < 0x8fff); diff --git a/porting_ideas.txt b/porting_ideas.txt new file mode 100644 index 0000000..ecad971 --- /dev/null +++ b/porting_ideas.txt @@ -0,0 +1,50 @@ + +can't really do a pure game engine that just uses the binary for data, +because parts of the game mechanics are implemented purely as 6502 +code. also the sound effects would need the engine to execute 6502 code +*and* emulate POKEY. however, it can at least use this much of the binary: + +- sprite and font bitmaps +- level layout data +- level names +- possibly color data (using an atari palette) + +this stuff can either be read out of the binary at runtime, or be coverted +into source and/or config files when building the engine. either way, +the original game binary will be required, but doing it at build time +means you don't need the binary at runtime (engine will be a standalone +port of the game). + +the various specials (hail, hatchlings, invisible level, etc) will have +to be rewritten in C (or whatever the engine ends up being written in). +probably just hardcode which specials appear on which levels. + +the basic game rules that don't change from level to level will of course +be part of the engine. running, jumping, climbing/descending ropes, +picking up bombs, collision detection, most levels have generic bullets. + +the sound effects and music can just be .wav files captured from the +original game running on the emulator. + +I'm thinking C with SDL2. render the game in an atari-sized window +(320x192 or whatever it really is) and let SDL2 scale it, which seems a +lot nicer than SDL1's basically nonexistent scaling. other possibility +would be perl-SDL, provided it's got full SDL2 support (not sure, seems +cpan doesn't have it) + +might add high-score saving a la original Jumpman (the one thing I really +missed, for the cart-based Junior). also maybe a randomizer mode. + +later on down the road, the engine should support original Jumpman too. +the https://playermissile.com/jumpman/ project has a lot of good info, +much of which will also apply to Junior. also there's x86 asm source +for the PC version. + +much later, there should be a level editor for the engine. not one that +can export levels for the original game like omnivore does for original +Jumpman, though. unless that turns out to be easier than I think, +of course. + +also inevitably someone will want updated graphics/sound, a "high res +apack" dd-on or such. I'm not opposed to such a thing existing but I +really only care about the original game. |