; ; Berzerk (C) 1980 Stern Electronics. ; ; Reverse engineering work by Scott Tunstall, Paisley, Scotland. ; Tools used: MAME debugger & Visual Studio Code text editor. ; Date: 26 Feb 2022 - sorry about the delay - Coronavirus and work got in the way. ; Keep checking for updates. ; ; Please send any questions, corrections and updates to scott.tunstall@ntlworld.com ; ; Be sure to check out my reverse engineering work for Robotron 2084, Galaxian and Scramble too, ; at http://seanriddle.com/robomame.asm, http://seanriddle.com/galaxian.asm and http://seanriddle.com/scramble.asm respectively. ; ; You might be interested to know that I converted Frenzy's (Berzerk's sequel) source code from 8085 to Z80 so that I could ; identify shared logic and use Frenzy's comments to determine what each routine does. ; ; It appears there's a lot of shared code! ; You can find my conversion here: https://github.com/ScottTunstall/FrenzyZ80Conv ; ; ; Finally: ; If you'd like to show appreciation for this work by buying me a coffee, feel free: https://ko-fi.com/scotttunstall ; I'd be equally happy if you donated to Parkinsons UK or Chest Heart And Stroke (CHAS) Scotland. ; Thanks. /* Conventions: NUMBERS ======= The term "@ $" means "at memory address in hexadecimal". e.g. @ $1234 means "refer to memory address 1234" or "program code @ memory location 1234" The term "#$" means "immediate value in hexadecimal". It's a convention I have kept from 6502 days. e.g. #$60 means "immediate value of 60 hex" (96 decimal) If I don't prefix a number with $ or #$ in my comments, treat the value as a decimal number. ARRAYS, LISTS, TABLES ===================== The terms "entry", "slot", "item", "record" when used in an array, list or table context all mean the same thing. I try to be consistent with my terminology but I might not always succeed. "Length" when used in terms of an array refers to how many elements it contains. SizeOf refers to the size in bytes of a structure (as it does in C). Unless I specify otherwise, I all indexes into arrays/lists/tables are zero-based, meaning element [0] is the first element, [1] the second, [2] the third and so on. FLAGS ===== The terms "Clear", "Reset", "Unset" in a flag context all mean the flag is set to zero. A non-zero value in a flag means the flag is "set" - unless I specify otherwise. COORDINATES =========== X,Y refer to the X and Y axis in a Cartesian 2D coordinate system, where X is horizontal and Y is vertical. TODOs: ====== TODOs are for me to look at later, when a piece of code isn't immediately obvious. Anyone who knows me, knows I like leaving TODOs in code :) UNCOMMENTED CODE: I never really bother with reverse engineering code specifically for cocktail cabinets. I just don't see any useful return on the time invested. */ /* MEMORY MAP Taken from https://github.com/mamedev/mame/blob/master/src/mame/drivers/berzerk.cpp 0000 - 07ff 2k 0-7 Program PROM (1C) 0800 - 09ff 1/2 k 4-7 CMOS RAM BBKUP 0800 - 0bff 1k 0-3 scratch pad RAM 0a00 - 0bff 1/2 k 4-7 Optional CMOS RAM 1000 - 17ff 2k 0-7 Program PROM (1D) 1800 - 1fff 2k 0-7 Program PROM (3D) 2000 - 27ff 2k 0-7 Program PROM (4D) 2800 - 2fff 2k 0-7 Program PROM (6D) 3000 - 37ff 2k 0-7 Program PROM (4C) 3800 - 3fff 2k 0-7 Program PROM (3C) 4000 - 43ff 1k 0-7 scratch pad RAM Video RAM - 32 bytes per scan line. 1 bit per pixel. 4400 - 5fff 7k 0-7 screen image RAM (256 * 223) 6000 - 63ff 1k 0-7 Magic scratchpad RAM 6400 - 7fff 7k 0-7 Magic image RAM 8000 - 87ff 2k 0-7 Color look-up (RGBI,RGBI) 0-3ff top half of screen (first 128 lines) 400-fff bottom half of screen Maps 4x4 color boxes into one of 16 colors void berzerk_state::berzerk_io_map(address_map &map) { map.global_mask(0xff); map(0x00, 0x3f).noprw(); map(0x40, 0x47).rw(FUNC(berzerk_state::audio_r), FUNC(berzerk_state::audio_w)); map(0x48, 0x48).portr("P1").nopw(); map(0x49, 0x49).portr("SYSTEM").nopw(); map(0x4a, 0x4a).portr("P2").nopw(); map(0x4b, 0x4b).nopr().w(FUNC(berzerk_state::magicram_control_w)); map(0x4c, 0x4c).rw(FUNC(berzerk_state::nmi_enable_r), FUNC(berzerk_state::nmi_enable_w)); map(0x4d, 0x4d).rw(FUNC(berzerk_state::nmi_disable_r), FUNC(berzerk_state::nmi_disable_w)); map(0x4e, 0x4e).r(FUNC(berzerk_state::intercept_v256_r)).nopw(); // note reading from here should clear pending frame interrupts, see zfb-1.tiff 74ls74 at 3D pin 13 /CLR map(0x4f, 0x4f).nopr().w(FUNC(berzerk_state::irq_enable_w)); map(0x50, 0x57).noprw(); /* second sound board, initialized but not used */ map(0x58, 0x5f).noprw(); map(0x60, 0x60).mirror(0x18).portr("F3").nopw(); map(0x61, 0x61).mirror(0x18).portr("F2").nopw(); map(0x62, 0x62).mirror(0x18).portr("F6").nopw(); map(0x63, 0x63).mirror(0x18).portr("F5").nopw(); map(0x64, 0x64).mirror(0x18).portr("F4").nopw(); map(0x65, 0x65).mirror(0x18).portr("SW2").nopw(); map(0x66, 0x66).mirror(0x18).rw(FUNC(berzerk_state::led_off_r), FUNC(berzerk_state::led_off_w)); map(0x67, 0x67).mirror(0x18).rw(FUNC(berzerk_state::led_on_r), FUNC(berzerk_state::led_on_w)); map(0x80, 0xff).noprw(); } // MAGIC RAM control register: // -- These are early investigation results and subject to change -- //Bit 3 set: Flip horizontal //Bit 4 and Bit 7 set: XOR mode /************************************* * * Port definitions * *************************************/ #define BERZERK_COINAGE(CHUTE, DIPBANK) \ PORT_DIPNAME( 0x0f, 0x00, "Coin "#CHUTE ) PORT_DIPLOCATION(#DIPBANK":1,2,3,4") \ PORT_DIPSETTING( 0x09, DEF_STR( 2C_1C ) ) \ PORT_DIPSETTING( 0x0d, DEF_STR( 4C_3C ) ) \ PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) \ PORT_DIPSETTING( 0x0e, DEF_STR( 4C_5C ) ) \ PORT_DIPSETTING( 0x0a, DEF_STR( 2C_3C ) ) \ PORT_DIPSETTING( 0x0f, DEF_STR( 4C_7C ) ) \ PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) ) \ PORT_DIPSETTING( 0x0b, DEF_STR( 2C_5C ) ) \ PORT_DIPSETTING( 0x02, DEF_STR( 1C_3C ) ) \ PORT_DIPSETTING( 0x0c, DEF_STR( 2C_7C ) ) \ PORT_DIPSETTING( 0x03, DEF_STR( 1C_4C ) ) \ PORT_DIPSETTING( 0x04, DEF_STR( 1C_5C ) ) \ PORT_DIPSETTING( 0x05, DEF_STR( 1C_6C ) ) \ PORT_DIPSETTING( 0x06, DEF_STR( 1C_7C ) ) \ PORT_DIPSETTING( 0x07, "1 Coin/10 Credits" ) \ PORT_DIPSETTING( 0x08, "1 Coin/14 Credits" ) static INPUT_PORTS_START( joystick ) // used on all games except moonwarp PORT_START("P1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P2") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0x80, 0x80, DEF_STR( Cabinet ) ) PORT_DIPSETTING( 0x80, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) INPUT_PORTS_END static INPUT_PORTS_START( common ) // used on all games PORT_START("SYSTEM") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x1c, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) /* fake port for monitor type */ PORT_START("MONITOR_TYPE") PORT_CONFNAME( 0x01, 0x00, "Monitor Type" ) PORT_CONFSETTING( 0x00, "Wells-Gardner" ) PORT_CONFSETTING( 0x01, "Electrohome" ) PORT_BIT( 0xfe, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_START("SW2") /* port for the 'bookkeeping reset' and 'bookkeeping' buttons; * The 'bookkeeping reset' button is an actual button on the zpu-1000 and * zpu-1001 pcbs, labeled 'S2' or 'SW2'. It is wired to bit 0. * * pressing it while high scores are displayed will give a free game * without adding any coin info to the bookkeeping info in nvram. * The 'bookkeeping' button is wired to the control panel, usually hidden * underneath or only accessible through the coin door. Wired to bit 7. * * It displays various bookkeeping statistics when pressed sequentially. * Pressing P1 fire (according to the manual) when stats are displayed * will clear the stat shown on screen. */ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Free Game (not logged in bookkeeping)") PORT_BIT( 0x7e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SERVICE2 ) PORT_NAME("Bookkeeping") PORT_CODE(KEYCODE_F1) INPUT_PORTS_END static INPUT_PORTS_START( berzerk ) PORT_INCLUDE( joystick ) PORT_INCLUDE( common ) PORT_START("F2") PORT_DIPNAME( 0x03, 0x00, "Color Test" ) PORT_CODE(KEYCODE_F5) PORT_TOGGLE PORT_DIPLOCATION("F2:1,2") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x03, DEF_STR( On ) ) PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("F2:7,8") PORT_DIPSETTING( 0xc0, "5000 and 10000" ) PORT_DIPSETTING( 0x40, "5000" ) PORT_DIPSETTING( 0x80, "10000" ) PORT_DIPSETTING( 0x00, DEF_STR( None ) ) PORT_START("F3") PORT_DIPNAME( 0x01, 0x00, "Input Test Mode" ) PORT_CODE(KEYCODE_F2) PORT_TOGGLE PORT_DIPLOCATION("F3:1") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, "Crosshair Pattern" ) PORT_CODE(KEYCODE_F4) PORT_TOGGLE PORT_DIPLOCATION("F3:2") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("F3:7,8") PORT_DIPSETTING( 0x00, DEF_STR( English ) ) PORT_DIPSETTING( 0x40, DEF_STR( German ) ) PORT_DIPSETTING( 0x80, DEF_STR( French ) ) PORT_DIPSETTING( 0xc0, DEF_STR( Spanish ) ) PORT_START("F4") BERZERK_COINAGE(1, F4) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("F5") BERZERK_COINAGE(2, F5) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("F6") BERZERK_COINAGE(3, F6) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) INPUT_PORTS_END */ /* Direction bit EQUs, - referred to as DURL bits in this document and the Frenzy source code. DURL = Down Up Right Left :) */ LEFT EQU $01 RIGHT EQU $02 UP EQU $04 DOWN EQU $08 /* Speech synthesis EQUs Berzerk has a vocabulary of 30 words. They are listed below. See also: - NMI handler @ $1748 which instructs the voice hardware to emit speech; - talk.asm within Frenzy's source code. */ KILL EQU $01 ATTACK EQU $02 CHARGE EQU $03 GOT EQU $04 SHOOT EQU $05 GET EQU $06 IS EQU $07 ALERT EQU $08 DETECTED EQU $09 THE EQU $0A IN EQU $0B IT EQU $0C THERE EQU $0D WHERE EQU $0E HUMANOID EQU $0F COINS EQU $10 POCKET EQU $11 INTRUDER EQU $12 NO EQU $13 ESCAPE EQU $14 DESTROY EQU $15 MUST EQU $16 NOT EQU $17 CHICKEN EQU $18 FIGHT EQU $19 LIKE EQU $1A A EQU $1B ROBOT EQU $1C ??? EQU $1D // Memory addresses // Audio ports CR1_PORT EQU $40 CR2_PORT EQU $41 VOICE_PORT EQU $44 ; Voice port number UNKNOWN_0800 EQU $0800 NMI_STACK_PTR EQU $085E ; used by NMI handler to store SP register while it does its thing V.PTR EQU $0870 ; pointer to next VECTOR struct struct LINKED_LIST_ITEM { BYTE Flags BYTE Delay BYTE NextItemLo BYTE NextItemHi } LINKED_LIST_PTR EQU $0872 ; pointer to head of job linked list STACK_PTR EQU $0874 ; used to preserve value of SP register in interrupt handler. See $26AC. MAN_PTR EQU $0876 ; pointer to current player's VECTOR structure ; Sound chip phantom registers (see also: EQUS.ASM within Frenzy's source code) TCR1 EQU $0878 TCR2 EQU $0879 TCR3 EQU $087A TMR1 EQU $087B TMR2 EQU $087D TMR3 EQU $087F NOISE EQU $0881 VOL1 EQU $0882 VOL2 EQU $0883 VOL3 EQU $0884 PC0 EQU $0885 PC1 EQU $0889 IS_CHICKEN EQU $089A ; A flag that determines if the robots call you a chicken or not. 0 = Player not a chicken. $FF = Player is a chicken. See $2BC6 and $2C18. TALK_TIMER EQU $089B ; Countdown before a robot speaks. When this hits 0, a robot will say something. See $2B9D. SPEECH_BUFFER EQU $0918 ; holds dynamically generated sequence of bytes to output to voice. See $2b6B. PLAYER_COLOUR_ADDR EQU $0940 ; pointer to attribute RAM where player's man is. Maps to CAddr within equs.asm in Frenzy's source code. PLAYER_COLOUR_SAVE EQU $0942 ; buffer 10 bytes in size, used to hold attributes to be restored. ; Bookkeeping totals held in CMOS ; Upper nibble (bits 4-7) hold 1 digit of value CMOS_CREDITS EQU $08A4 CMOS_CHUTE1 EQU $08A6 CMOS_CHUTE2 EQU $08AE CMOS_CHUTE3 EQU $08B6 CMOS_NUM_PLAYS EQU $08BE CMOS_TOTAL_SCORE EQU $08C4 CMOS_TOTAL_SECS_OF_PLAY EQU $08D0 CMOS_HIGH_SCORES EQU $08DC // Scratch pad RAM EQUs ??? EQU $4066 ; Status bits used in VECTOR structure STATUS_BIT_ERASE EQU 0 STATUS_BIT_WRITE EQU 1 STATUS_BIT_MOVE EQU 2 STATUS_BIT_BLANK EQU 3 STATUS_BIT_COLOR EQU 4 STATUS_BIT_HIT EQU 7 ; ; Structure that encapsulates state required for an animated sprite, such as the player and robots. ; Or, in Plain English, a data structure that holds information about a sprite on screen. ; ; Note: ; [Laser] Bolts do not use VECTORS, they use the BOLT structure instead. ; struct VECTOR { 0 BYTE Status ; status bits that determine how this object is rendered. See "status bits" above for info. 1 BYTE Magic ; last magic RAM value used for this object 2 BYTE O.A.L ; old screen address low byte 3 BYTE O.A.H ; old screen address high byte 4 BYTE O.P.L ; old pattern (sprite pixel data) address low byte 5 BYTE O.P.H ; old pattern address high byte 6 BYTE V.X ; X velocity. A signed delta to add to P.X 7 BYTE P.X ; Current X position on screen 8 BYTE V.Y ; Y velocity. A signed delta to add to P.Y 9 BYTE P.Y ; Current Y position on screen 10 BYTE D.P.L ; low byte of a pointer to an entry in a pattern table 11 BYTE D.P.H ; high byte of a pointer to an entry in a pattern table 12 BYTE TIME ; Counter used to limit how fast this object moves. Lower = faster 13 BYTE TPRIME ; Used to reload TIME when TIME counts to 0. } sizeof (VECTOR) = 14 bytes EQU $415E EQU $4300 ; High score table. ; ; A high score requires exactly 6 bytes per entry. There is a maximum of 10 high score entries. ; ; Format of each high score entry: ; First 3 bytes: score as BCD. e.g. a score of 123,456 would be stored like so: 12 34 56 ; Last 3 bytes: name entered as (mostly) ASCII. HI_SCORES EQU $4302 ; Start of high score table HI_SCORE_1 EQU $4302 ; Top score HI_SCORE_2 EQU $4308 HI_SCORE_3 EQU $430E HI_SCORE_4 EQU $4314 HI_SCORE_5 EQU $431A HI_SCORE_6 EQU $4320 HI_SCORE_7 EQU $4326 HI_SCORE_8 EQU $432C HI_SCORE_9 EQU $4332 HI_SCORE_10 EQU $4338 ; lowest Hi Score P1_SCORE EQU $433E ; Player 1's score. Stored as BCD. ; $433E = First two digits of score (hundred thousands & ten thousands) ; $433F = Third and fourth digits of score (thousands & hundreds) ; $4340 = Last two digits of score (tens) ; e.g. a score of 101120 would be stored as 10 11 20 P2_SCORE EQU $4341 ; Player 2's score. Stored in same format as player 1's. ; Player state. ; ; Remarks: ; The corresponding fields for Frenzy are stored in EQUS.ASM if you want to take a look. ; CURRENT_PLAYER EQU $4344 ; 1 = player 1 playing , 2 = player 2 playing. ROOM_X EQU $4345 ; X coordinate of room within *maze* - decrements when player exits room left, increments when player exits right ROOM_Y EQU $4346 ; Y coordinate of room within *maze* - decrements when player exits room top, increments when player exits bottom MAN_X EQU $4347 ; Player's X coordinate on screen. MAN_Y EQU $4348 ; Player's Y coordinate on screen DEATHS EQU $4349 ; Lives left. EQU $434A RBOLTS EQU $434B ; Maximum number of Robot laser bolts allowed on screen at once. 0 = Robots never shoot. See $288E. ROBOT_SPEED EQU $434C ; Value from 1..255. 1= Fastest, 255 = Slowest RWAIT EQU $434D ; Initial robot firing holdoff timer. OTTO_TIME EQU $434E ; Countdown timer before Evil Otto appears. XTRAMEN EQU $434F ; Flag. Set to 1 when a bonus life has been awarded to player. Prevents more bonus lives. RNG_SEED EQU $435C ; Seed for the random number generator @ $2678 UPDATE EQU $436D ; Flag. Set to $FF when score needs to be updated on screen. See $218D IS_DEMO_MODE EQU $436E ; Flag. When set to a nonzero value, the game is showing "demo mode". DEMO_PTR EQU $436F RCOUNT EQU $4371 ; Number of robots still alive in room, not counting Evil Otto. Is decremented when a robot is killed. RSAVED EQU $4372 ; Number of robots in room *when room starts*. Used to calculate bonus for clearing room. See $2491. NUMBER_OF_PLAYERS EQU $4376 ; 1 = One player game, 2 = 2 player game PLAYER_COLOUR EQU $4378 ; Colour of player. Used to set screen attributes. FLIP EQU $4379 ; 0 = Playing upright, 8 = playing on cocktail cabinet. ; ; structure that encapsulates the state for a [laser] bolt fired by player or robot. ; Or, in Plain English, a data structure that holds information about a laser bolt on screen, such as its position. ; ; Remarks: ; Bolts are programatically plotted pixel-by-pixel on screen. They do not have pattern data in ROM. ; ; See also: bolts.asm in Frenzy's source code. struct BOLT { 0 BYTE Direction ; DURL (Direction) bits. bit 0 set: left, bit 1 set: right, bit 2 set: up, bit 3 set: down 1 BYTE Length ; current length of bolt. 2 BYTE X ; X coordinate of the head of the bolt 3 BYTE Y ; Y coordinate of the head of the bolt 4 BYTE LastDirection 5 BYTE MaxLength ; max length of bolt (pixels) - see $1f7C 6 BYTE TailX ; X coordinate of the tail of the bolt 7 BYTE LastY ; Y coordinate of the tail of the bolt } sizeof(BOLT) is 8 bytes PLAYER_BOLTS EQU $437B PLAYER_BOLT_1 EQU $437B PLAYER_BOLT_2 EQU $4383 ROBOT_BOLTS EQU $438F 0000: 00 nop 0001: F3 di 0002: AF xor a 0003: D3 4D out ($4D),a ; write to nmi_disable_r 0005: ED 47 ld i,a 0007: DB 61 in a,($61) ; read from F2 0009: CB 47 bit 0,a ; check if "Colour Test Mode" bit is set 000B: C2 00 02 jp nz,$0200 ; if bit is set, goto COLOUR_TEST_MODE 000E: DB 60 in a,($60) ; read F3 0010: CB 47 bit 0,a ; check if "Input Test Mode" bit is set 0012: C2 31 05 jp nz,$0531 ; if bit is set, goto INPUT_TEST_MODE 0015: DD 21 41 01 ld ix,$0141 0019: 18 68 jr $0083 001B: CD 7B 29 call $297B ; call PRINT_STRING_297B 001E: 90 20 08 ; X/Y coordinates 0021: 43 6F 6E 67 72 61 74 75 6C 61 74 69 6F 6E 73 20 Congratulations 0031: 50 6C 61 79 65 72 20 00 Player . 0039: C9 ret 003A: CD 7B 29 call $297B ; call PRINT_STRING_297B 003D: 90 10 08 ; X/Y coordinates 0040: 46 65 6C 69 63 69 74 61 74 69 6F 6E 73 20 61 75 Felicitations au 0050: 20 6A 6F 75 65 75 72 20 00 joueur . 0059: C9 ret 005A: FF rst $38 005B: FF rst $38 005C: FF rst $38 005D: FF rst $38 005E: FF rst $38 005F: FF rst $38 0060: FF rst $38 0061: FF rst $38 0062: FF rst $38 0063: FF rst $38 0064: FF rst $38 0065: FF rst $38 // NMI handler 0066: D3 4D out ($4D),a ; write to nmi_disable_r 0068: F5 push af 0069: 3A 00 40 ld a,($4000) 006C: B7 or a 006D: C2 1D 05 jp nz,$051D 0070: F1 pop af 0071: C3 21 17 jp $1721 ; jump to main NMI handler code 0074: 05 dec b ; Referenced by $0199 0075: 00 08 ; Referenced by $019C 0077: A3 00 0079: 01 00 00 ld bc,$0000 007C: 0D dec c 007D: 20 FD jr nz,$007C 007F: 10 FB djnz $007C 0081: DB 66 in a,($66) ; read led_off_r 0083: 3E 01 ld a,$01 0085: 01 41 01 ld bc,$0141 0088: 11 47 82 ld de,$8247 008B: ED 41 out (c),b 008D: 0D dec c 008E: ED 51 out (c),d 0090: 0C inc c 0091: 0C inc c 0092: ED 41 out (c),b 0094: 0C inc c 0095: ED 41 out (c),b 0097: 0C inc c 0098: 0C inc c 0099: 0C inc c 009A: ED 59 out (c),e 009C: 0E 51 ld c,$51 009E: 3D dec a 009F: 28 EA jr z,$008B 00A1: 01 00 00 ld bc,$0000 00A4: 0D dec c 00A5: 20 FD jr nz,$00A4 00A7: 10 FB djnz $00A4 00A9: DB 67 in a,($67) ; read led_on_r 00AB: AF xor a 00AC: D3 40 out ($40),a ; write to audio_w 00AE: D3 50 out ($50),a ; second sound board, unused 00B0: DD E9 jp (ix) 00B2: FF rst $38 00B3: FF rst $38 00B4: FF rst $38 00B5: FF rst $38 00B6: FF rst $38 00B7: FF rst $38 00B8: FF rst $38 00B9: FF rst $38 00BA: FF rst $38 00BB: FF rst $38 00BC: FF rst $38 00BD: FF rst $38 00BE: FF rst $38 00BF: FF rst $38 00C0: FF rst $38 00C1: FF rst $38 00C2: FF rst $38 00C3: FF rst $38 00C4: FF rst $38 00C5: FF rst $38 00C6: FF rst $38 00C7: FF rst $38 00C8: FF rst $38 00C9: FF rst $38 00CA: FF rst $38 00CB: FF rst $38 00CC: FF rst $38 00CD: FF rst $38 00CE: FF rst $38 00CF: FF rst $38 00D0: FF rst $38 00D1: FF rst $38 00D2: FF rst $38 00D3: FF rst $38 00D4: FF rst $38 00D5: FF rst $38 00D6: FF rst $38 00D7: FF rst $38 00D8: FF rst $38 00D9: FF rst $38 00DA: FF rst $38 00DB: FF rst $38 00DC: FF rst $38 00DD: FF rst $38 00DE: FF rst $38 00DF: FF rst $38 00E0: FF rst $38 00E1: FF rst $38 00E2: FF rst $38 00E3: FF rst $38 00E4: FF rst $38 00E5: FF rst $38 00E6: FF rst $38 00E7: FF rst $38 00E8: FF rst $38 00E9: FF rst $38 00EA: FF rst $38 00EB: FF rst $38 00EC: FF rst $38 00ED: FF rst $38 00EE: FF rst $38 00EF: FF rst $38 00F0: FF rst $38 00F1: FF rst $38 00F2: FF rst $38 00F3: FF rst $38 00F4: FF rst $38 00F5: FF rst $38 00F6: FF rst $38 00F7: FF rst $38 00F8: FF rst $38 00F9: FF rst $38 00FA: FF rst $38 00FB: FF rst $38 00FC: FF rst $38 00FD: FF rst $38 00FE: FF rst $38 00FF: FF rst $38 0100: 18 3B jr $013D 0102: 01 C0 08 ld bc,$08C0 0105: 21 00 00 ld hl,$0000 0108: 16 08 ld d,$08 010A: 7E ld a,(hl) 010B: 09 add hl,bc 010C: AF xor a 010D: ED 4F ld r,a 010F: 32 00 10 ld ($1000),a 0112: 15 dec d 0113: 20 F5 jr nz,$010A 0115: 0E 7F ld c,$7F 0117: 16 20 ld d,$20 0119: 7B ld a,e 011A: E6 20 and $20 011C: 47 ld b,a 011D: ED 78 in a,(c) 011F: CB 0B rrc e 0121: 0D dec c 0122: 15 dec d 0123: 20 F4 jr nz,$0119 0125: 3E 80 ld a,$80 0127: 01 57 80 ld bc,$8057 012A: ED 79 out (c),a 012C: 05 dec b 012D: 0D dec c 012E: CB 0F rrc a 0130: 30 F8 jr nc,$012A 0132: 0E 47 ld c,$47 0134: ED 79 out (c),a 0136: 0D dec c 0137: CB 0F rrc a 0139: 30 F9 jr nc,$0134 013B: 18 C5 jr $0102 013D: 3E 01 ld a,$01 013F: ED 47 ld i,a 0141: 1E 06 ld e,$06 0143: DD 21 00 10 ld ix,$1000 0147: 01 00 08 ld bc,$0800 014A: 26 00 ld h,$00 014C: 2E FF ld l,$FF 014E: DD 7E 00 ld a,(ix+$00) 0151: 57 ld d,a 0152: A5 and l 0153: 6F ld l,a 0154: 7A ld a,d 0155: 84 add a,h 0156: 67 ld h,a 0157: DD 23 inc ix 0159: 0D dec c 015A: 20 F2 jr nz,$014E 015C: 10 F0 djnz $014E 015E: 3A 74 00 ld a,($0074) 0161: FE FF cp $FF 0163: 28 25 jr z,$018A 0165: 83 add a,e 0166: D6 07 sub $07 0168: F2 6F 01 jp p,$016F 016B: 7D ld a,l 016C: 3C inc a 016D: 28 05 jr z,$0174 016F: 3E FF ld a,$FF 0171: BC cp h 0172: 20 16 jr nz,$018A 0174: 7B ld a,e 0175: CB 07 rlc a 0177: DA 92 01 jp c,$0192 017A: 1D dec e 017B: 20 CA jr nz,$0147 017D: ED 57 ld a,i 017F: A7 and a 0180: 20 17 jr nz,$0199 0182: DD 21 00 00 ld ix,$0000 0186: 1E 80 ld e,$80 0188: 18 BD jr $0147 018A: ED 57 ld a,i 018C: A7 and a 018D: C2 02 01 jp nz,$0102 0190: 18 FE jr $0190 0192: DD 21 99 01 ld ix,$0199 0196: C3 79 00 jp $0079 0199: 2A 75 00 ld hl,($0075) ; load HL with 40800 019C: ED 4B 77 00 ld bc,($0077) ; load BC with #$00A3 (163 decimal) 01A0: 36 55 ld (hl),$55 ; write to UNKNOWN_0800 01A2: 2B dec hl 01A3: ED A1 cpi 01A5: E2 AB 01 jp po,$01AB 01A8: 23 inc hl 01A9: 18 F5 jr $01A0 01AB: 16 AA ld d,$AA 01AD: 31 FF FF ld sp,$FFFF 01B0: ED 4B 77 00 ld bc,($0077) 01B4: 7A ld a,d 01B5: 2F cpl 01B6: AE xor (hl) 01B7: 20 16 jr nz,$01CF 01B9: 72 ld (hl),d 01BA: 2B dec hl 01BB: ED A1 cpi 01BD: EA CC 01 jp pe,$01CC 01C0: 7A ld a,d 01C1: FE 55 cp $55 01C3: 28 25 jr z,$01EA 01C5: 31 01 00 ld sp,$0001 01C8: 16 55 ld d,$55 01CA: 18 E4 jr $01B0 01CC: 39 add hl,sp 01CD: 18 E5 jr $01B4 01CF: 57 ld d,a 01D0: ED 57 ld a,i 01D2: CB 0F rrc a 01D4: 38 01 jr c,$01D7 01D6: 76 halt 01D7: 1E 12 ld e,$12 01D9: 7A ld a,d 01DA: E6 0F and $0F 01DC: CA 02 01 jp z,$0102 01DF: 1D dec e 01E0: 7A ld a,d 01E1: E6 F0 and $F0 01E3: CA 02 01 jp z,$0102 01E6: 1D dec e 01E7: C3 02 01 jp $0102 01EA: ED 57 ld a,i 01EC: CB 0F rrc a 01EE: 1E 20 ld e,$20 01F0: D2 B1 02 jp nc,$02B1 01F3: C3 02 01 jp $0102 01F6: FF rst $38 01F7: FF rst $38 01F8: FF rst $38 01F9: FF rst $38 01FA: FF rst $38 01FB: FF rst $38 01FC: FF rst $38 01FD: FF rst $38 01FE: FF rst $38 01FF: FF rst $38 ; ; Called from $000B ; COLOUR_TEST_MODE: 0200: 01 48 10 ld bc,$1048 0203: ED 78 in a,(c) 0205: 0C inc c 0206: ED 78 in a,(c) 0208: 0C inc c 0209: ED 78 in a,(c) 020B: 0C inc c 020C: 0C inc c 020D: ED 78 in a,(c) 020F: 0C inc c 0210: ED 78 in a,(c) 0212: 0C inc c 0213: ED 78 in a,(c) 0215: 0C inc c 0216: 3E 01 ld a,$01 0218: ED 79 out (c),a 021A: 01 48 00 ld bc,$0048 021D: ED 78 in a,(c) 021F: 0C inc c 0220: ED 78 in a,(c) 0222: 0C inc c 0223: ED 78 in a,(c) 0225: 21 00 50 ld hl,$5000 0228: 11 00 70 ld de,$7000 022B: 06 10 ld b,$10 022D: 78 ld a,b 022E: 3D dec a 022F: D3 4B out ($4B),a ; write to magicram_control_w 0231: 3E 80 ld a,$80 0233: 77 ld (hl),a 0234: 12 ld (de),a 0235: 4E ld c,(hl) 0236: CB 0F rrc a 0238: 30 F9 jr nc,$0233 023A: AF xor a 023B: DB 4E in a,($4E) ; read middle/bottom screen status 023D: 3E 08 ld a,$08 023F: 32 00 50 ld ($5000),a 0242: 32 00 70 ld ($7000),a 0245: AF xor a 0246: DB 4E in a,($4E) ; read middle/bottom screen status 0248: 23 inc hl 0249: 13 inc de 024A: 10 E1 djnz $022D 024C: 06 0D ld b,$0D 024E: 11 00 A0 ld de,$A000 0251: 21 FE 5F ld hl,$5FFE 0254: 3E 80 ld a,$80 0256: 25 dec h 0257: 77 ld (hl),a 0258: 4E ld c,(hl) 0259: 24 inc h 025A: 37 scf 025B: CB 15 rl l 025D: CB 14 rl h 025F: 19 add hl,de 0260: CB 0F rrc a 0262: 10 F2 djnz $0256 0264: 21 11 11 ld hl,$1111 0267: 11 11 11 ld de,$1111 026A: 31 00 88 ld sp,$8800 026D: 0E 10 ld c,$10 026F: 06 10 ld b,$10 0271: E5 push hl 0272: E5 push hl 0273: E5 push hl 0274: E5 push hl 0275: 10 FA djnz $0271 0277: 19 add hl,de 0278: F1 pop af 0279: 3B dec sp 027A: 3B dec sp 027B: 0D dec c 027C: 20 F1 jr nz,$026F 027E: DB 4C in a,($4C) 0280: AF xor a 0281: DB 4E in a,($4E) ; read middle/bottom screen status 0283: AF xor a 0284: DB 61 in a,($61) ; read from F2 0286: E6 02 and $02 0288: 28 FE jr z,$0288 028A: 21 00 50 ld hl,$5000 028D: 11 00 70 ld de,$7000 0290: 3E F0 ld a,$F0 0292: ED 47 ld i,a 0294: 01 4B 00 ld bc,$004B 0297: ED 57 ld a,i 0299: ED 79 out (c),a 029B: 0E 00 ld c,$00 029D: 79 ld a,c 029E: 70 ld (hl),b 029F: 12 ld (de),a 02A0: 48 ld c,b 02A1: 2F cpl 02A2: 46 ld b,(hl) 02A3: 47 ld b,a 02A4: B1 or c 02A5: 20 F6 jr nz,$029D 02A7: ED 57 ld a,i 02A9: D6 10 sub $10 02AB: ED 47 ld i,a 02AD: 20 E5 jr nz,$0294 02AF: 18 FE jr $02AF ; enter infinite loop! 02B1: DD 21 B8 02 ld ix,$02B8 02B5: C3 79 00 jp $0079 02B8: 21 FF 5F ld hl,$5FFF 02BB: 11 00 00 ld de,$0000 02BE: DD 21 C5 02 ld ix,$02C5 02C2: C3 95 03 jp $0395 02C5: 01 00 00 ld bc,$0000 02C8: 21 00 40 ld hl,$4000 02CB: DD 21 D2 02 ld ix,$02D2 02CF: C3 76 03 jp $0376 02D2: 21 00 40 ld hl,$4000 02D5: 11 55 00 ld de,$0055 02D8: DD 21 DF 02 ld ix,$02DF 02DC: C3 95 03 jp $0395 02DF: 21 FF 5F ld hl,$5FFF 02E2: 11 AA 55 ld de,$55AA 02E5: DD 21 EC 02 ld ix,$02EC 02E9: C3 95 03 jp $0395 02EC: 21 00 40 ld hl,$4000 02EF: 11 FF AA ld de,$AAFF 02F2: DD 21 F9 02 ld ix,$02F9 02F6: C3 95 03 jp $0395 02F9: 21 FF 5F ld hl,$5FFF 02FC: 11 00 FF ld de,$FF00 02FF: DD 21 06 03 ld ix,$0306 0303: C3 95 03 jp $0395 0306: 79 ld a,c 0307: B0 or b 0308: C2 C1 03 jp nz,$03C1 030B: DD 21 12 03 ld ix,$0312 030F: C3 79 00 jp $0079 0312: 21 FF 87 ld hl,$87FF 0315: 11 00 00 ld de,$0000 0318: DD 21 1F 03 ld ix,$031F 031C: C3 95 03 jp $0395 031F: 01 00 00 ld bc,$0000 0322: 21 00 80 ld hl,$8000 0325: DD 21 2C 03 ld ix,$032C 0329: C3 76 03 jp $0376 032C: 21 00 84 ld hl,$8400 032F: DD 21 36 03 ld ix,$0336 0333: C3 76 03 jp $0376 0336: 21 00 80 ld hl,$8000 0339: 11 55 00 ld de,$0055 033C: DD 21 43 03 ld ix,$0343 0340: C3 8F 03 jp $038F 0343: 21 FF 87 ld hl,$87FF 0346: 11 AA 55 ld de,$55AA 0349: DD 21 50 03 ld ix,$0350 034D: C3 8F 03 jp $038F 0350: 21 00 80 ld hl,$8000 0353: 11 FF AA ld de,$AAFF 0356: DD 21 5D 03 ld ix,$035D 035A: C3 8F 03 jp $038F 035D: 21 FF 87 ld hl,$87FF 0360: 11 00 FF ld de,$FF00 0363: DD 21 6A 03 ld ix,$036A 0367: C3 8F 03 jp $038F 036A: 79 ld a,c 036B: B0 or b 036C: C2 6C 03 jp nz,$036C 036F: DD 21 42 04 ld ix,$0442 0373: C3 79 00 jp $0079 0376: 16 00 ld d,$00 0378: 72 ld (hl),d 0379: 7E ld a,(hl) 037A: AA xor d 037B: B0 or b 037C: 47 ld b,a 037D: 23 inc hl 037E: 72 ld (hl),d 037F: 7E ld a,(hl) 0380: AA xor d 0381: B1 or c 0382: 4F ld c,a 0383: 2B dec hl 0384: 15 dec d 0385: C2 78 03 jp nz,$0378 0388: 36 00 ld (hl),$00 038A: 23 inc hl 038B: 36 00 ld (hl),$00 038D: DD E9 jp (ix) 038F: D9 exx 0390: 01 00 08 ld bc,$0800 0393: 18 04 jr $0399 0395: D9 exx 0396: 01 00 20 ld bc,$2000 0399: D9 exx 039A: 7E ld a,(hl) 039B: AA xor d 039C: B0 or b 039D: 47 ld b,a 039E: 73 ld (hl),e 039F: 7E ld a,(hl) 03A0: AB xor e 03A1: B0 or b 03A2: 47 ld b,a 03A3: CB 43 bit 0,e 03A5: C2 AA 03 jp nz,$03AA 03A8: 2B dec hl 03A9: 3E 23 ld a,$23 03AB: 78 ld a,b 03AC: 41 ld b,c 03AD: 4F ld c,a 03AE: D9 exx 03AF: 0D dec c 03B0: C2 B7 03 jp nz,$03B7 03B3: 05 dec b 03B4: CA BB 03 jp z,$03BB 03B7: D9 exx 03B8: C3 9A 03 jp $039A 03BB: D9 exx 03BC: 78 ld a,b 03BD: 41 ld b,c 03BE: 4F ld c,a 03BF: DD E9 jp (ix) 03C1: 21 22 04 ld hl,$0422 03C4: 11 01 00 ld de,$0001 03C7: 78 ld a,b 03C8: A2 and d 03C9: C2 E8 03 jp nz,$03E8 03CC: 79 ld a,c 03CD: A3 and e 03CE: C3 E8 03 jp $03E8 03D1: EB ex de,hl 03D2: 29 add hl,hl 03D3: EB ex de,hl 03D4: D2 C7 03 jp nc,$03C7 03D7: 11 00 40 ld de,$4000 03DA: 1D dec e 03DB: FD 7E 00 ld a,(iy+$00) 03DE: C2 DA 03 jp nz,$03DA 03E1: 15 dec d 03E2: C2 DA 03 jp nz,$03DA 03E5: C3 B8 02 jp $02B8 03E8: 08 ex af,af' 03E9: 7E ld a,(hl) 03EA: 23 inc hl 03EB: D9 exx 03EC: 6F ld l,a 03ED: D9 exx 03EE: 7E ld a,(hl) 03EF: 23 inc hl 03F0: D9 exx 03F1: 67 ld h,a 03F2: 11 1F 00 ld de,$001F 03F5: 06 03 ld b,$03 03F7: 08 ex af,af' 03F8: B7 or a 03F9: 28 07 jr z,$0402 03FB: 36 FC ld (hl),$FC 03FD: 23 inc hl 03FE: 36 3F ld (hl),$3F 0400: 18 05 jr $0407 0402: 36 84 ld (hl),$84 0404: 23 inc hl 0405: 36 21 ld (hl),$21 0407: 19 add hl,de 0408: 10 EE djnz $03F8 040A: 06 24 ld b,$24 040C: B7 or a 040D: 28 07 jr z,$0416 040F: 36 FF ld (hl),$FF 0411: 23 inc hl 0412: 36 FF ld (hl),$FF 0414: 18 05 jr $041B 0416: 36 80 ld (hl),$80 0418: 23 inc hl 0419: 36 01 ld (hl),$01 041B: 19 add hl,de 041C: 10 EE djnz $040C 041E: D9 exx 041F: C3 D1 03 jp $03D1 0422: 8D adc a,l 0423: 50 ld d,b 0424: 4D ld c,l 0425: 4A ld c,d 0426: 0D dec c 0427: 44 ld b,h 0428: CD 56 15 call $1556 042B: 44 ld b,h 042C: 55 ld d,l 042D: 4A ld c,d 042E: 95 sub l 042F: 50 ld d,b 0430: D5 push de 0431: 56 ld d,(hl) 0432: 89 adc a,c 0433: 50 ld d,b 0434: 49 ld c,c 0435: 4A ld c,d 0436: 09 add hl,bc 0437: 44 ld b,h 0438: C9 ret 0439: 56 ld d,(hl) 043A: 11 44 51 ld de,$5144 043D: 4A ld c,d 043E: 91 sub c 043F: 50 ld d,b 0440: D1 pop de 0441: 56 ld d,(hl) 0442: 21 00 60 ld hl,$6000 0445: 16 01 ld d,$01 0447: 42 ld b,d 0448: AF xor a 0449: 4F ld c,a 044A: 5F ld e,a 044B: ED 47 ld i,a 044D: ED 57 ld a,i 044F: D3 4B out ($4B),a ; write to magicram_control_w 0451: 36 FF ld (hl),$FF 0453: 72 ld (hl),d 0454: 36 00 ld (hl),$00 0456: 7E ld a,(hl) 0457: BB cp e 0458: 20 FE jr nz,$0458 045A: ED 57 ld a,i 045C: 3C inc a 045D: ED 47 ld i,a 045F: FE 10 cp $10 0461: 20 0B jr nz,$046E 0463: CB 12 rl d 0465: 30 E0 jr nc,$0447 0467: DD 21 87 04 ld ix,$0487 046B: C3 79 00 jp $0079 046E: 79 ld a,c 046F: CB 1F rr a 0471: CB 18 rr b 0473: CB 19 rr c 0475: 59 ld e,c 0476: ED 57 ld a,i 0478: FE 08 cp $08 047A: 38 D1 jr c,$044D 047C: 3E 08 ld a,$08 047E: CB 08 rrc b 0480: CB 13 rl e 0482: 3D dec a 0483: 20 F9 jr nz,$047E 0485: 18 C6 jr $044D 0487: 1E 00 ld e,$00 0489: DD 21 CA 04 ld ix,$04CA 048D: 21 00 60 ld hl,$6000 0490: 01 01 01 ld bc,$0101 0493: 7B ld a,e 0494: D3 4B out ($4B),a ; write to magicram_control_w 0496: 78 ld a,b 0497: 32 00 40 ld ($4000),a 049A: 71 ld (hl),c 049B: 79 ld a,c 049C: DD E9 jp (ix) 049E: AE xor (hl) 049F: 20 FE jr nz,$049F 04A1: 77 ld (hl),a 04A2: 78 ld a,b 04A3: A1 and c 04A4: 28 02 jr z,$04A8 04A6: 3E 80 ld a,$80 04A8: 57 ld d,a 04A9: DB 4E in a,($4E) ; read middle/bottom screen status 04AB: AA xor d 04AC: 17 rla 04AD: 38 FE jr c,$04AD 04AF: CB 00 rlc b 04B1: 30 E0 jr nc,$0493 04B3: CB 01 rlc c 04B5: 30 DC jr nc,$0493 04B7: DD 23 inc ix 04B9: DD 23 inc ix 04BB: DD 23 inc ix 04BD: 3E 10 ld a,$10 04BF: 83 add a,e 04C0: 5F ld e,a 04C1: 30 D0 jr nc,$0493 04C3: DD 21 FA 04 ld ix,$04FA 04C7: C3 79 00 jp $0079 04CA: 00 nop 04CB: 18 D1 jr $049E 04CD: B0 or b 04CE: 18 CE jr $049E 04D0: 2F cpl 04D1: 18 18 jr $04EB 04D3: AF xor a 04D4: 18 21 jr $04F7 04D6: A0 and b 04D7: 18 C5 jr $049E 04D9: 78 ld a,b 04DA: 18 C2 jr $049E 04DC: A8 xor b 04DD: 18 18 jr $04F7 04DF: 2F cpl 04E0: 18 EB jr $04CD 04E2: 2F cpl 04E3: 18 0F jr $04F4 04E5: A8 xor b 04E6: 18 B6 jr $049E 04E8: 78 ld a,b 04E9: 18 0C jr $04F7 04EB: A0 and b 04EC: 18 09 jr $04F7 04EE: AF xor a 04EF: 18 AD jr $049E 04F1: 2F cpl 04F2: 18 E2 jr $04D6 04F4: B0 or b 04F5: 18 00 jr $04F7 04F7: 2F cpl 04F8: 18 A4 jr $049E 04FA: ED 5E im 2 04FC: 3E 07 ld a,$07 04FE: ED 47 ld i,a 0500: DD 21 02 16 ld ix,$1602 0504: 3E FF ld a,$FF 0506: D3 4F out ($4F),a 0508: 47 ld b,a 0509: 31 FF 43 ld sp,$43FF 050C: DB 4E in a,($4E) ; read middle/bottom screen status 050E: 1F rra 050F: CB 10 rl b 0511: 78 ld a,b 0512: EE 55 xor $55 0514: 28 03 jr z,$0519 0516: FB ei 0517: 18 FE jr $0517 0519: D3 4F out ($4F),a ; enable interrupts? 051B: 06 FF ld b,$FF ; ; Called from NMI handler ; 051D: 31 FF 43 ld sp,$43FF 0520: DB 4D in a,($4D) ; disable NMI (according to MAME driver source) 0522: DB 4E in a,($4E) ; read middle/bottom screen status 0524: 1F rra 0525: CB 10 rl b 0527: 78 ld a,b 0528: EE 20 xor $20 052A: CA 79 00 jp z,$0079 052D: DB 4C in a,($4C) ; enable NMI (according to MAME driver source) 052F: 18 FE jr $052F ; enter infinite loop ; Called from $0012 INPUT_TEST_MODE: 0531: 31 00 44 ld sp,$4400 0534: CD 4E 1A call $1A4E ; call CLEAR_SCREEN 0537: CD F8 35 call $35F8 ; call COLOUR_FILL_WHITE ; print titles 053A: 21 B9 05 ld hl,$05B9 ; address of "ZPU DIP SWITCHES" text 053D: 11 20 00 ld de,$0020 ; D = Y coordinate, E = X coordinate 0540: CD 91 05 call $0591 ; print "ZPU DIP SWITCHES" 0543: 11 20 80 ld de,$8020 ; D = Y coordinate, E = X coordinate 0546: CD 91 05 call $0591 ; print "VFB SWITCHES" 0549: 11 08 10 ld de,$1008 ; D = Y coordinate, E = X coordinate 054C: CD 91 05 call $0591 ; print "1 2 3 4 5 6 7 8" 054F: 11 10 D0 ld de,$D010 ; D = Y coordinate, E = X coordinate 0552: CD 91 05 call $0591 ; print "0=OFF =ON" ; create 2 horizontal rules (like
tag in HTML) 0555: 21 A0 47 ld hl,$47A0 0558: CD 45 1A call $1A45 ; call WRITE_FF_64_TIMES_HL 055B: 21 A0 55 ld hl,$55A0 055E: CD 45 1A call $1A45 ; call WRITE_FF_64_TIMES_HL ; read ZPU DIP switches 0561: 11 08 20 ld de,$2008 ; D = Y coordinate, E = X coordinate 0564: DB 61 in a,($61) ; read from F2 DIP switch 0566: CD 97 05 call $0597 ; call PRINT_SET_BITS 0569: DB 60 in a,($60) ; read from F3 DIP switch 056B: CD 97 05 call $0597 ; call PRINT_SET_BITS 056E: DB 62 in a,($62) ; read from F6 DIP switch 0570: CD 97 05 call $0597 ; call PRINT_SET_BITS 0573: DB 63 in a,($63) ; read from F5 DIP switch 0575: CD 97 05 call $0597 ; call PRINT_SET_BITS 0578: DB 64 in a,($64) ; read from F4 DIP switch 057A: CD 97 05 call $0597 ; call PRINT_SET_BITS ; now print VFB switches 057D: 11 08 90 ld de,$9008 ; D = Y coordinate, E = X coordinate 0580: DB 48 in a,($48) ; read P1 controls 0582: CD 96 05 call $0596 ; call FLIP_THEN_PRINT_SET_BITS 0585: DB 49 in a,($49) ; read SYSTEM 0587: CD 96 05 call $0596 ; call FLIP_THEN_PRINT_SET_BITS 058A: DB 4A in a,($4A) ; read player 2 controls 058C: CD 96 05 call $0596 ; call FLIP_THEN_PRINT_SET_BITS 058F: 18 D0 jr $0561 ; go back and read DIP switches until machine switched off! ; TODO: Tentative function name ; D = Y coordinate ; E = X coordinate JP_PRINT_STRING_06B8: 0591: 06 00 ld b,$00 ; Magic RAM control bits 0593: C3 B8 06 jp $06B8 ; jump to PRINT_STRING_06B8 FLIP_THEN_PRINT_SET_BITS: 0596: 2F cpl ; flip bits ; ; Used by INPUT TEST MODE screen. ; ; Displays a graphic representation of bits set/Unset in a byte ; Set bit will be rendered as a crosshatch pattern ; Unset bit will be rendered as "0" (no quotes) ; ; A = bits ; D = Y coordinate ; E = X coordinate PRINT_SET_BITS: 0597: 0E 08 ld c,$08 ; testing 8 bits (the full byte) 0599: 21 01 06 ld hl,$0601 ; address of hatch pattern string ; test bit 059C: 1F rra ; move bit into carry flag 059D: 38 03 jr c,$05A2 ; if bit is set, goto 05A2 to print hatch pattern ; bit is unset, print 0 059F: 21 03 06 ld hl,$0603 ; address of "0" string ; print hatch character or "0" 05A2: F5 push af 05A3: D5 push de 05A4: C5 push bc 05A5: CD 91 05 call $0591 ; call JP_PRINT_STRING_06B8 05A8: C1 pop bc 05A9: D1 pop de 05AA: F1 pop af 05AB: 21 20 00 ld hl,$0020 ; horizontal pixel spacing between characters 05AE: 19 add hl,de ; increment X coordinate by #$20 (32 decimal) pixels 05AF: EB ex de,hl ; now make DE = X/Y coordinates 05B0: 0D dec c ; decrement count of bits left to test 05B1: 20 E6 jr nz,$0599 ; repeat until all bits done ; All bits done 05B3: 21 00 0F ld hl,$0F00 ; increment Y coordinate by #$0F (15 decimal) pixels 05B6: 19 add hl,de 05B7: EB ex de,hl 05B8: C9 ret ; Text used in the ZPU DIP SWITCHES test screen 05B9: 5A 50 55 20 44 49 50 20 53 57 49 54 43 48 45 53 ZPU DIP SWITCHES 05C9: 00 05CA: 56 46 42 20 53 57 49 54 43 48 45 53 00 VFB SWITCHES. 05D7: 31 20 20 20 32 20 20 20 33 20 20 20 34 20 20 20 1 2 3 4 05E7: 35 20 20 20 36 20 20 20 37 20 20 20 38 00 5 6 7 8. 05F5: 30 3D 4F 46 46 20 20 7F 3D 4F 4E 00 0=OFF .=ON. 0601: 7F 00 (Hatch pattern) 0603: 30 00 0. ; ; ; Display bookkeeping totals ; ; BOOKKEEPING: 0605: AF xor a 0606: D3 4F out ($4F),a ; disable interrupts 0608: DB 4E in a,($4E) ; clear pending frame interrupts 060A: 31 00 43 ld sp,$4300 060D: DB 65 in a,($65) ; read SW2 060F: CB 7F bit 7,a ; test BOOKKEEPING bit 0611: 20 FA jr nz,$060D ; wait until user takes finger off BOOKKEEPING button 0613: CD 4E 1A call $1A4E ; call CLEAR_SCREEN 0616: CD 3D 36 call $363D ; set colour attributes such that any pixels on all but last 2 lines of screen will be blue 0619: F3 di 061A: 21 CC 06 ld hl,$06CC ; pointer to the first text string, "Credits" ; main loop 061D: 7E ld a,(hl) ; read byte 061E: B7 or a ; is it 0? - which is the list terminator 061F: CA 02 16 jp z,$1602 ; yes, goto $1602 0622: CD 9A 06 call $069A ; call BK_SCROLL_UP 0625: 06 00 ld b,$00 0627: 11 00 CF ld de,$CF00 ; D = Y coordinate, E = X coordinate ; print title of bookkeeping item then scroll screen up to make room for associated value 062A: CD B8 06 call $06B8 ; print title of bookkeeping item 062D: CD 9A 06 call $069A ; call BK_SCROLL_UP 0630: E5 push hl ; After printing text string, HL is now a pointer to 3 parameter bytes. ; Bytes 0 & 1: pointer to CMOS RAM entry ; Byte 2: max length, in digits, of entry 0631: 5E ld e,(hl) ; read LSB of CMOS RAM address 0632: 23 inc hl 0633: 56 ld d,(hl) ; read MSB of CMOS RAM address 0634: 23 inc hl 0635: 46 ld b,(hl) ; read size in bytes 0636: 23 inc hl 0637: E5 push hl ; DE = pointer to CMOS RAM entry to print ; B = size of CMOS RAM entry in bytes (or, put another way, number of digits to print) 0638: 21 00 00 ld hl,$0000 063B: E5 push hl ; allocate 6 bytes of temp storage.. 063C: E5 push hl 063D: E5 push hl ; ..on the stack 063E: 39 add hl,sp ; HL = SP 063F: CD 73 06 call $0673 ; call UNPACK_BYTES_TO_HL ; print digits 0642: 11 CF 00 ld de,$00CF ; Set Y coordinate to print digits 0645: CD 8D 06 call $068D ; call PRINT_DIGITS_068D 0648: E1 pop hl ; discard temp data on stack 0649: E1 pop hl 064A: E1 pop hl 064B: E1 pop hl 064C: E3 ex (sp),hl 064D: DB 65 in a,($65) ; read SW2 064F: CB 7F bit 7,a ; test BOOKKEEPING bit 0651: 20 16 jr nz,$0669 ; if bit is set, goto $0669 ; Test if fire has been pressed - if so, then clear (zero) the bookkeeping item. 0653: DB 48 in a,($48) ; read P1 controls 0655: CB 67 bit 4,a ; test FIRE bit 0657: 20 F4 jr nz,$064D ; if FIRE is NOT pressed (remember, its active LOW) goto $064D ; P1 fire has been pressed - clear the bookkeeping item 0659: E5 push hl 065A: 5E ld e,(hl) ; read LSB of CMOS RAM address 065B: 23 inc hl 065C: 56 ld d,(hl) ; read MSB of CMOS RAM address 065D: 23 inc hl 065E: 46 ld b,(hl) ; read size in bytes 065F: AF xor a ; write B zero bytes to CMOS RAM @ DE 0660: 12 ld (de),a ; write 0 byte 0661: 13 inc de ; bump DE to next byte to be zeroes 0662: 10 FC djnz $0660 ; repeat until all bytes written 0664: E1 pop hl 0665: D1 pop de 0666: C3 30 06 jp $0630 ; update screen to show value zeroed ; wait for user to take finger off BOOKKEEPING button 0669: E1 pop hl 066A: DB 65 in a,($65) ; read SW2 066C: CB 7F bit 7,a ; test BOOKKEEPING bit 066E: 20 FA jr nz,$066A ; repeat until BOOKKEEPING button not pressed 0670: C3 1D 06 jp $061D ; print next bookkeeping item ; ; This routine is used to read values from CMOS. ; ; Expects: ; B = sizeof() in bytes ; DE = pointer to byte pairs where only upper nibble of each byte is relevant ; e.g. a value of 96 decimal would be stored as 90 60 in CMOS ; HL = pointer to RAM where result can be stored ; ; Returns: A = value read from CMOS ; UNPACK_BYTES_TO_HL: 0673: E5 push hl 0674: D5 push de 0675: C5 push bc ; read first byte in pair 0676: 1A ld a,(de) 0677: 13 inc de 0678: E6 F0 and $F0 ; mask in upper nibble 067A: 4F ld c,a ; store upper nibble in C ; read second byte in pair 067B: 1A ld a,(de) 067C: 13 inc de 067D: 07 rlca ; move bits 4..7 067E: 07 rlca 067F: 07 rlca 0680: 07 rlca ; into bits 0..3 0681: E6 0F and $0F ; preserve lower nibble ; C= upper nibble (source: byte 0). A = lower nibble (source: byte 1). ; Combine nibbles to form 2 digit BCD number then write result to (HL) 0683: B1 or c ; combine A with C 0684: 77 ld (hl),a ; write result 0685: 23 inc hl ; bump HL to point to first byte in next byte pair 0686: 05 dec b 0687: 10 ED djnz $0676 ; repeat until all byte pairs done 0689: C1 pop bc 068A: D1 pop de 068B: E1 pop hl 068C: C9 ret ; ; Used by Bookkeeping screen to display totals ; ; Expects: E = Y coordinate ; PRINT_DIGITS_068D: 068D: C5 push bc 068E: D5 push de 068F: E5 push hl 0690: 53 ld d,e ; set Y coordinate 0691: 1E 00 ld e,$00 ; set X coordinate to 0 0693: CD 40 2A call $2A40 ; call PRINT_DIGITS 0696: E1 pop hl 0697: D1 pop de 0698: C1 pop bc 0699: C9 ret ; ; Scroll screen up for bookkeeping ; ; BK_SCROLL_UP: 069A: C5 push bc 069B: D5 push de 069C: E5 push hl ; scroll up 069D: 01 C0 19 ld bc,$19C0 06A0: 11 00 44 ld de,$4400 06A3: 21 00 46 ld hl,$4600 06A6: ED B0 ldir ; clear remainder of screen 06A8: 01 00 02 ld bc,$0200 06AB: AF xor a 06AC: 12 ld (de),a ; 06AD: 13 inc de 06AE: 0D dec c 06AF: C2 AC 06 jp nz,$06AC 06B2: 10 F8 djnz $06AC 06B4: E1 pop hl 06B5: D1 pop de 06B6: C1 pop bc 06B7: C9 ret ; ; HL = pointer to null(zero byte)-terminated text string ; B = Magic image RAM control bits ; D = Y coordinate ; E = X coordinate ; PRINT_STRING_06B8: 06B8: EB ex de,hl 06B9: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 06BC: EB ex de,hl 06BD: 4E ld c,(hl) ; read char from string 06BE: CD DB 29 call $29DB ; call PRINT_CHAR 06C1: 13 inc de 06C2: 23 inc hl 06C3: 47 ld b,a 06C4: 7E ld a,(hl) 06C5: B7 or a 06C6: 78 ld a,b 06C7: C2 BD 06 jp nz,$06BD 06CA: 23 inc hl 06CB: C9 ret ; ; BOOKKEEPING CMOS RAM descriptor table ; ; Each entry in the table is a null (zero) terminated text string followed by 3 bytes: ; Bytes 0 & 1: pointer to CMOS RAM entry ; Byte 2: max length, in digits, of entry ; ; For example, after "Credits" is printed below, the system will print 2 digits read from CMOS RAM location $08A4 ; ; See $061A for the code that reads and prints these entries 06CC: 43 72 65 64 69 74 73 00 Credits. 06D4: A4 08 ; pointer to CMOS RAM where credits is held 02 ; max number of digits /* 08A4: 06D7: 43 68 75 74 65 20 31 00 Chute 1. A6 08 ; pointer to CMOS RAM where chute 1 is held 08 ; max number of digits 06E2: 43 68 75 74 65 20 32 00 Chute 2. AE 08 ; pointer to CMOS RAM where chute 2 is held 08 ; max number of digits 06ED: 43 68 75 74 65 20 33 00 Chute 3. B6 08 ; pointer to CMOS RAM where chute 3 is held 08 ; max number of digits 06F8: 50 6C 61 79 73 00 Plays. BE 08 ; pointer to CMOS RAM where plays is held 06 ; max number of digits 0701: 54 6F 74 61 6C 20 53 63 6F 72 65 00 Total Score. C4 08 ; pointer to CMOS RAM where total score is held 0C ; max number of digits 0710: 54 6F 74 61 6C 20 53 65 63 6F 6E 64 73 Total Seconds 071D: 20 6F 66 20 50 6C 61 79 00 of Play. D0 08 ; pointer to CMOS RAM where total seconds of play is held 0C ; max number of digits 0729: 48 69 67 68 20 53 63 6F 72 65 73 00 High Scores. DC 08 ; pointer to CMOS RAM where high scores is held 06 ; max number of digits ; This terminates the list of entries (see $061E) 00 0739: F3 di CROSSHAIR_PATTERN_TEST_MODE: 073A: 21 00 44 ld hl,$4400 ; load HL with address of screen image RAM ; HL = start of screen image RAM 073D: 54 ld d,h 073E: 5D ld e,l ; DE = HL ; create vertical bar 073F: 36 01 ld (hl),$01 ; write 1 pixel 0741: 23 inc hl 0742: 73 ld (hl),e 0743: 23 inc hl 0744: 01 FD 1B ld bc,$1BFD 0747: EB ex de,hl 0748: ED B0 ldir ; create horizontal bars 074A: 21 00 45 ld hl,$4500 074D: 54 ld d,h 074E: 5D ld e,l 074F: 06 20 ld b,$20 0751: 36 FF ld (hl),$FF ; write 8 pixels 0753: 23 inc hl 0754: 10 FB djnz $0751 ; We now have a template of sorts to use to create a grid. Copy this template to fill screen. 0756: 01 80 02 ld bc,$0280 0759: 09 add hl,bc 075A: EB ex de,hl 075B: 01 7F 18 ld bc,$187F 075E: ED B0 ldir ; create grid pattern ; grid is drawn, now colour it 0760: CD F8 35 call $35F8 ; call COLOUR_FILL_WHITE ; wait for FIRE to be pressed 0763: CD 86 07 call $0786 ; call WAIT_FOR_1P_FIRE_BUTTON ; Fill entire screen with pixels 0766: 21 00 44 ld hl,$4400 ; load HL with address of screen image RAM 0769: 11 01 44 ld de,$4401 076C: 01 FF 1B ld bc,$1BFF 076F: 36 FF ld (hl),$FF 0771: ED B0 ldir ; fill screen with pixels ; Set pixel colour attributes to RED - now entire screen will be red colour 0773: 21 00 81 ld hl,$8100 0776: 11 01 81 ld de,$8101 0779: 01 FF 06 ld bc,$06FF 077C: 36 11 ld (hl),$11 077E: ED B0 ldir ; fill attribute RAM with $11 (Red) ; wait for fire to be pressed 0780: CD 86 07 call $0786 ; call WAIT_FOR_1P_FIRE_BUTTON ; it appears once you enter the crosshair test you can't exit it without switching machine off, ; changing DIP switches to disable test, then restarting machine 0783: C3 3A 07 jp $073A ; go and draw the crosshair again WAIT_FOR_1P_FIRE_BUTTON: ; wait for fire button to be pressed 0786: DB 48 in a,($48) ; read P1 controls 0788: CB 67 bit 4,a ; test if FIRE pressed 078A: 20 FA jr nz,$0786 ; jump if FIRE not pressed (remember, button is ACTIVE_LOW so is deemed pressed when bit NOT set) ; Wait for user to take finger off fire button 078C: DB 48 in a,($48) ; read player 1 controls 078E: CB 67 bit 4,a ; test if FIRE pressed 0790: 28 FA jr z,$078C l jump if FIRE pressed to $078C 0792: C9 ret 0793: CD 7B 29 call $297B ; call PRINT_STRING_297B 0796: 90 08 20 ; X/Y coordinates 0799: 59 6F 75 20 68 61 76 65 20 6A 6F 69 6E 65 64 20 You have joined 07A9: 74 68 65 20 69 6D 6D 6F 72 74 61 6C 73 00 the immortals.. 07B7: CD 7B 29 call $297B ; call PRINT_STRING_297B 07BA: 90 0C 30 ; X/Y coordinates 07BD: 69 6E 20 74 68 65 20 42 45 52 5A 45 52 4B 20 68 in the BERZERK h 07CD: 61 6C 6C 20 6F 66 20 66 61 6D 65 00 all of fame. 07D9: CD 7B 29 call $297B ; call PRINT_STRING_297B 07DC: 90 18 50 ; X/Y coordinates 07DF: 45 6E 74 65 72 20 79 6F 75 72 20 69 6E 69 74 69 Enter your initi 07EF: 61 6C 73 3A 00 als:. 07F4: C9 ret 07F5: FF rst $38 07F6: FF rst $38 07F7: FF rst $38 07F8: FF rst $38 07F9: FF rst $38 07FA: FF rst $38 07FB: FF rst $38 07FC: 09 add hl,bc 07FD: 05 dec b 07FE: 17 rla 07FF: 05 dec b ; ; 0800 - 0FFF is RAM, not ROM and contains no code. ; ; pattern table for robot standing still 1000: 10 D1 10 DE 10 EB 10 F8 10 F8 10 F8 11 05 11 12 00 00 10 ; pattern table for robot moving right/up right/down right 1013: 11 2C 11 1F 11 1F 00 13 10 ; pattern table for robot moving down 101C: 10 D1 11 39 10 D1 11 47 00 1C 10 ; pattern table for robot moving left/up left/down left 1027: 11 55 11 62 11 62 00 27 10 ; pattern table for robot moving up 1030: 11 6F 11 7C 11 6F 11 8A 00 30 10 ; pattern table for robot exploding. 103B: 11 98 11 BC 11 E0 12 08 00 41 10 ; pattern table for player standing still. (1 frame) 1046: 10 BF 00 46 10 104B: 10 AD 10 9B 10 89 10 9B 00 4B 10 1056: 13 B5 13 A3 13 91 13 A3 00 56 10 ; Player shooting up, right pattern table (1 frame) 1061: 13 09 00 61 10 ; Player shooting right pattern table (1 frame) 1066: 13 1A 00 66 10 ; Player shooting down, right pattern table (1 frame) 106B: 13 2B 00 6B 10 ; Player shooting down pattern table (1 frame) 1070: 13 3C 00 70 10 ; Player shooting down, left pattern table (1 frame) 1075: 13 4D 00 75 10 ; Player shooting left pattern table (1 frame) 107A: 13 5E 00 7A 10 ; Player shooting up, left pattern table (1 frame) 107F: 13 6F 00 7F 10 ; Player shooting up pattern table (1 frame) 1084: 13 80 00 84 10 ; ; Player sprite patterns (pixel data) ; 1089: 01 ; width in bytes 10 ; height in bytes 18 18 00 3C 5A 99 58 18 18 24 22 41 41 81 81 00 109B: 01 ; width in bytes 10 ; height in bytes 00 18 18 00 3C 5C 5C 3E 18 18 14 12 F2 82 02 03 10AD: 01 ; width in bytes 10 ; height in bytes 18 18 00 3C 5C 5C 5A 18 18 18 18 18 18 18 1C 10 10BF: 01 ; width in bytes 10 ; height in bytes 18 18 00 3C 5A 5A 5A 18 18 18 18 18 18 18 1C 10 10D1: 01 ; width in bytes 0B ; height in bytes 3C 66 FF BD BD BD 3C 24 24 24 66 10DE: 01 ; width in bytes 0B ; height in bytes 3C 4E FF BD BD BD 3C 24 24 24 66 10EB: 01 ; width in bytes 0B ; height in bytes 3C 1E FF BD BD BD 3C 24 24 24 66 10F8: 01 ; width in bytes 0B ; height in bytes 3C 7E FF BD BD BD 3C 24 24 24 66 1105: 01 ; width in bytes 0B ; height in bytes 3C 78 FF BD BD BD 3C 24 24 24 66 1112: 01 ; width in bytes 0B ; height in bytes 3C 71 FF BD BD BD 3C 24 24 24 66 111F: 01 ; width in bytes 0B ; height in bytes 3C 78 FF BD BD BD 3C 18 18 18 1C 112C: 01 ; width in bytes 0B ; height in bytes 3C 78 FF BD BD BD 3C 24 24 24 36 1139: 01 ; width in bytes 0C ; height in bytes 3C 66 FF BD BD BD 3C 24 24 26 20 60 1147: 01 ; width in bytes 0C ; height in bytes 3C 66 FF BD BD BD 3C 24 24 64 04 06 1155: 01 ; width in bytes 0B ; height in bytes 3C 1E FF BD BD BD 3C 24 24 24 6C 1162: 01 ; width in bytes 0B ; height in bytes 3C 1E FF BD BD BD 3C 18 18 18 38 116F: 01 ; width in bytes 0B ; height in bytes 3C 7E FF BD BD BD 3C 24 24 24 66 117C: 01 ; width in bytes 0C ; height in bytes 3C 7E FF BD BD BD 3C 24 24 26 20 60 118A: 01 ; width in bytes 0C ; height in bytes 3C 7E FF BD BD BD 3C 24 24 64 04 06 ; Explosion sprite patterns 1198: 02 ; width in bytes 11 ; height in bytes 00 00 119C: 00 nop 119D: 00 nop 119E: 00 nop 119F: 00 nop 11A0: 00 nop 11A1: 00 nop 11A2: 00 nop 11A3: 00 nop 11A4: 00 nop 11A5: 00 nop 11A6: 03 inc bc 11A7: C0 ret nz 11A8: 07 rlca 11A9: E0 ret po 11AA: 0F rrca 11AB: F0 ret p 11AC: 13 inc de 11AD: C8 ret z 11AE: 22 C4 03 ld ($03C4),hl 11B1: 40 ld b,b 11B2: 03 inc bc 11B3: C0 ret nz 11B4: 02 ld (bc),a 11B5: 40 ld b,b 11B6: 02 ld (bc),a 11B7: 40 ld b,b 11B8: 02 ld (bc),a 11B9: 40 ld b,b 11BA: 06 60 ld b,$60 11BC: 02 ld (bc),a ; ; Sprite ; 11BD: 11 00 00 ld de,$0000 11C0: 00 nop 11C1: 00 nop 11C2: 00 nop 11C3: 00 nop 11C4: 00 nop 11C5: 00 nop 11C6: 03 inc bc 11C7: C0 ret nz 11C8: 06 60 ld b,$60 11CA: 12 ld (de),a 11CB: 48 ld c,b 11CC: 08 ex af,af' 11CD: 10 10 djnz $11DF 11CF: 08 ex af,af' 11D0: 22 44 44 ld ($4444),hl 11D3: 42 ld b,d 11D4: 02 ld (bc),a 11D5: 10 03 djnz $11DA 11D7: C0 ret nz 11D8: 02 ld (bc),a 11D9: 40 ld b,b 11DA: 04 inc b 11DB: 20 02 jr nz,$11DF 11DD: 40 ld b,b 11DE: 06 60 ld b,$60 11E0: 02 ld (bc),a ; ; Sprite ; 11E1: 13 inc de 11E2: 00 nop 11E3: 00 nop 11E4: 02 ld (bc),a 11E5: 00 nop 11E6: 00 nop 11E7: 40 ld b,b 11E8: 00 nop 11E9: 08 ex af,af' 11EA: 10 00 djnz $11EC 11EC: 03 inc bc 11ED: 00 nop 11EE: 00 nop 11EF: 12 ld (de),a 11F0: 08 ex af,af' 11F1: 01 80 00 ld bc,$0080 11F4: 08 ex af,af' 11F5: 02 ld (bc),a 11F6: 40 ld b,b 11F7: 02 ld (bc),a 11F8: 04 inc b 11F9: 10 23 djnz $121E 11FB: C0 ret nz 11FC: 40 ld b,b 11FD: 04 inc b 11FE: 20 02 jr nz,$1202 1200: 00 nop 1201: 00 nop 1202: 80 add a,b 1203: 00 nop 1204: 10 08 djnz $120E 1206: 18 0C jr $1214 1208: 01 01 00 ld bc,$0001 120B: 12 ld (de),a 120C: 2E 12 ld l,$12 120E: 34 inc (hl) 120F: 12 ld (de),a 1210: 3B dec sp 1211: 12 ld (de),a 1212: 43 ld b,e 1213: 12 ld (de),a 1214: 4C ld c,h 1215: 12 ld (de),a 1216: 56 ld d,(hl) 1217: 12 ld (de),a 1218: A7 and a 1219: 12 ld (de),a 121A: 6D ld l,l 121B: 12 ld (de),a 121C: 79 ld a,c 121D: 12 ld (de),a 121E: 85 add a,l 121F: 12 ld (de),a 1220: 91 sub c 1221: 12 ld (de),a 1222: 9D sbc a,l 1223: 12 ld (de),a 1224: 91 sub c 1225: 12 ld (de),a 1226: 85 add a,l 1227: 12 ld (de),a 1228: 79 ld a,c 1229: 12 ld (de),a 122A: 6D ld l,l 122B: 00 nop 122C: 17 rla 122D: 12 ld (de),a 122E: 84 add a,h 122F: 00 nop 1230: 01 02 18 ld bc,$1802 1233: 18 84 jr $11B9 1235: 00 nop 1236: 01 03 10 ld bc,$1003 1239: 38 10 jr c,$124B 123B: 84 add a,h 123C: 00 nop 123D: 01 04 18 ld bc,$1804 1240: 3C inc a 1241: 3C inc a 1242: 18 84 jr $11C8 1244: 00 nop 1245: 01 05 38 ld bc,$3805 1248: 7C ld a,h 1249: 7C ld a,h 124A: 7C ld a,h 124B: 38 84 jr c,$11D1 124D: 00 nop 124E: 01 06 3C ld bc,$3C06 1251: 7E ld a,(hl) 1252: 7E ld a,(hl) 1253: 7E ld a,(hl) 1254: 7E ld a,(hl) 1255: 3C inc a 1256: 84 add a,h 1257: 00 nop 1258: 01 07 38 ld bc,$3807 125B: 7C ld a,h 125C: FE FE cp $FE 125E: FE 7C cp $7C 1260: 38 84 jr c,$11E6 1262: 00 nop 1263: 01 08 3C ld bc,$3C08 1266: 7E ld a,(hl) 1267: FF rst $38 1268: FF rst $38 1269: FF rst $38 126A: FF rst $38 126B: 7E ld a,(hl) 126C: 3C inc a 126D: 82 add a,d 126E: 00 nop 126F: 01 08 3C ld bc,$3C08 1272: 7E ld a,(hl) 1273: DB FF in a,($FF) 1275: FF rst $38 1276: BD cp l 1277: 42 ld b,d 1278: 3C inc a 1279: 81 add a,c 127A: 00 nop 127B: 01 08 3C ld bc,$3C08 127E: 7E ld a,(hl) 127F: DB FF in a,($FF) 1281: FF rst $38 1282: BD cp l 1283: 42 ld b,d 1284: 3C inc a 1285: 80 add a,b 1286: 80 add a,b 1287: 01 08 3C ld bc,$3C08 128A: 7E ld a,(hl) 128B: DB FF in a,($FF) 128D: FF rst $38 128E: BD cp l 128F: 42 ld b,d 1290: 3C inc a 1291: 80 add a,b 1292: 40 ld b,b 1293: 01 08 3C ld bc,$3C08 1296: 7E ld a,(hl) 1297: DB FF in a,($FF) 1299: FF rst $38 129A: BD cp l 129B: 42 ld b,d 129C: 3C inc a 129D: 01 08 3C ld bc,$3C08 12A0: 7E ld a,(hl) 12A1: DB FF in a,($FF) 12A3: FF rst $38 12A4: BD cp l 12A5: 42 ld b,d 12A6: 3C inc a 12A7: 84 add a,h 12A8: 00 nop 12A9: 01 08 00 ld bc,$0008 12AC: 00 nop 12AD: 00 nop 12AE: 3C inc a 12AF: 7E ld a,(hl) 12B0: DB FF in a,($FF) 12B2: 7E ld a,(hl) 12B3: 12 ld (de),a 12B4: D0 12 12B6: BE 12 12B8: E3 12 12BA: F6 00 or $00 12BC: B3 12 12BE: 01 ; width in bytes 10 ; height in bytes 00 18 18 00 3C 5A 5A 5A 18 18 18 18 18 18 18 3C ; ; Player sprite patterns ; 12D0: 01 ; width in bytes 11 ; height in bytes 18 24 24 42 81 81 81 81 81 42 24 24 24 24 24 42 3C 12E3: 01 ; width in bytes 11 ; height in bytes 3C 24 24 7E C3 A5 A5 A5 E7 66 24 24 24 24 66 42 7E 12F6: 01 ; width in bytes 11 ; height in bytes 3C 3C 3C 7E FF FF FF FF FF 7E 3C 3C 3C 3C 7E 7E 7E 1309: 01 ; width in bytes 0F ; height in bytes 18 19 04 1C 18 18 18 18 18 18 18 18 18 18 1C 131A: 01 ; width in bytes 0F ; height in bytes 18 18 00 1F 18 18 18 18 18 18 18 18 18 18 1C 132B: 01 ; width in bytes 0F ; height in bytes 18 18 00 18 18 1C 1A 18 18 18 18 18 18 18 1C 133C: 01 ; width in bytes 0F ; height in bytes 18 18 00 3C 3C 3A 3A 3A 18 18 18 18 18 18 1C 134D: 01 ; width in bytes 0F ; height in bytes 18 18 00 3C 3C 5C 9C 1C 18 18 18 18 18 18 38 135E: 01 ; width in bytes 0F ; height in bytes 18 18 00 F8 18 18 18 18 18 18 18 18 18 18 38 136F: 01 ; width in bytes 0F ; height in bytes 98 58 20 18 18 18 18 18 18 18 18 18 18 18 38 1380: 01 ; width in bytes 0F ; height in bytes 18 18 00 1D 1B 19 18 18 18 18 18 18 18 18 38 01 jr c,$1393 1392: 10 18 djnz $13AC 1394: 18 00 jr $1396 1396: 3C inc a 1397: 5A ld e,d 1398: 99 sbc a,c 1399: 9A sbc a,d 139A: 18 18 jr $13B4 139C: 24 inc h 139D: 44 ld b,h 139E: 42 ld b,d 139F: 42 ld b,d 13A0: 41 ld b,c 13A1: 41 ld b,c 13A2: 80 add a,b 13A3: 01 10 00 ld bc,$0010 13A6: 18 18 jr $13C0 13A8: 00 nop 13A9: 3C inc a 13AA: 3A 3A 7C ld a,($7C3A) 13AD: 18 18 jr $13C7 13AF: 28 48 jr z,$13F9 13B1: 4F ld c,a 13B2: 41 ld b,c 13B3: 40 ld b,b 13B4: 80 add a,b 13B5: 01 10 18 ld bc,$1810 13B8: 18 00 jr $13BA 13BA: 3C inc a 13BB: 3A 3A 7A ld a,($7A3A) 13BE: 18 18 jr $13D8 13C0: 18 18 jr $13DA 13C2: 18 18 jr $13DC 13C4: 18 18 jr $13DE 13C6: 38 72 jr c,$143A 13C8: 20 62 jr nz,$142C 13CA: 6F ld l,a 13CB: 75 ld (hl),l 13CC: 74 ld (hl),h 13CD: 6F ld l,a 13CE: 6E ld l,(hl) 13CF: 20 73 jr nz,$1444 13D1: 74 ld (hl),h 13D2: 61 ld h,c 13D3: 72 ld (hl),d 13D4: 74 ld (hl),h 13D5: 20 31 jr nz,$1408 13D7: 20 6F jr nz,$1448 13D9: 75 ld (hl),l 13DA: 20 32 jr nz,$140E 13DC: 00 nop 13DD: C9 ret 13DE: CD 7B 29 call $297B ; call PRINT_STRING_297B 13E1: 90 20 BE ; X/Y coordinates 13E4: 53 74 61 72 74 6B 6E 6F 65 70 66 65 20 64 72 75 Startknoepfe dru 13F4: 65 63 6B 65 6E 00 ecken. 13FA: C9 ret 13FB: CD 7B 29 call $297B ; call PRINT_STRING_297B 13FE: 90 44 BE ; X/Y coordinates 1401: 50 75 6C 73 61 72 20 53 74 61 72 74 00 Pulsar Start. 140E: C9 ret 140F: CD 7B 29 call $297B ; call PRINT_STRING_297B 1412: 90 58 BE ; X/Y coordinates 1415: 49 6E 73 65 72 74 20 43 6F 69 6E 00 Insert Coin. 1421: C9 ret 1422: CD 7B 29 call $297B ; call PRINT_STRING_297B 1425: 90 30 BE ; X/Y coordinates 1428: 49 6E 74 72 6F 64 75 69 72 65 20 6C 61 20 6D 6F Introduire la mo 1438: 6E 6E 61 69 65 00 nnaie. 143E: C9 ret 143F: CD 7B 29 call $297B ; call PRINT_STRING_297B 1442: 90 48 BE ; X/Y coordinates 1445: 4D 75 6E 7A 65 20 65 69 6E 77 65 72 66 65 6E 00 Munze einwerfen. 1455: C9 ret 1456: CD 7B 29 call $297B ; call PRINT_STRING_297B 1459: 90 48 BE ; X/Y coordinates 145C: 50 6F 6E 67 61 20 6C 61 20 6D 6F 6E 65 64 61 00 Ponga la moneda. 146C: C9 ret 146D: 00 nop 146E: C5 push bc 146F: F5 push af 1470: FD 2A 76 08 ld iy,($0876) ; load IY with contents of MAN_PTR 1474: FD 66 07 ld h,(iy+$07) ; read VECTOR.P.X (X pos) 1477: FD 6E 09 ld l,(iy+$09) ; read VECTOR.P.Y (Y pos) 147A: CD E7 1C call $1CE7 147D: D5 push de 147E: DD 66 07 ld h,(ix+$07) 1481: DD 6E 09 ld l,(ix+$09) 1484: 2D dec l 1485: 2D dec l 1486: 2D dec l 1487: 2D dec l 1488: 25 dec h 1489: 25 dec h 148A: 25 dec h 148B: 25 dec h 148C: CD E7 1C call $1CE7 148F: D9 exx 1490: 47 ld b,a 1491: D9 exx 1492: C1 pop bc 1493: 79 ld a,c 1494: BB cp e 1495: 20 03 jr nz,$149A 1497: F1 pop af 1498: C1 pop bc 1499: C9 ret 149A: 7C ld a,h 149B: E5 push hl 149C: C6 10 add a,$10 149E: 67 ld h,a 149F: CD E7 1C call $1CE7 14A2: D9 exx 14A3: 4F ld c,a 14A4: D9 exx 14A5: 7D ld a,l 14A6: C6 13 add a,$13 14A8: 6F ld l,a 14A9: CD E7 1C call $1CE7 14AC: D9 exx 14AD: 57 ld d,a 14AE: D9 exx 14AF: 7D ld a,l 14B0: E1 pop hl 14B1: 6F ld l,a 14B2: CD E7 1C call $1CE7 14B5: D9 exx 14B6: 5F ld e,a 14B7: F1 pop af 14B8: 67 ld h,a 14B9: 2E 00 ld l,$00 14BB: CB 5C bit 3,h 14BD: 28 06 jr z,$14C5 14BF: 78 ld a,b 14C0: B1 or c 14C1: E6 08 and $08 14C3: B5 or l 14C4: 6F ld l,a 14C5: CB 54 bit 2,h 14C7: 28 06 jr z,$14CF 14C9: 7A ld a,d 14CA: B3 or e 14CB: E6 04 and $04 14CD: B5 or l 14CE: 6F ld l,a 14CF: CB 4C bit 1,h 14D1: 28 06 jr z,$14D9 14D3: 78 ld a,b 14D4: B3 or e 14D5: E6 02 and $02 14D7: B5 or l 14D8: 6F ld l,a 14D9: CB 44 bit 0,h 14DB: 28 06 jr z,$14E3 14DD: 79 ld a,c 14DE: B2 or d 14DF: E6 01 and $01 14E1: B5 or l 14E2: 6F ld l,a 14E3: 2F cpl 14E4: A4 and h 14E5: C1 pop bc 14E6: C9 ret 14E7: 7D ld a,l 14E8: 1E 00 ld e,$00 14EA: FE 46 cp $46 14EC: 38 08 jr c,$14F6 14EE: 1E 05 ld e,$05 14F0: FE 8A cp $8A 14F2: EA ; ; TODO: Player bolt related ; ; HANDLE_PLAYER_BOLTS: 14F3: 06 02 ld b,$02 14F5: CD 05 15 call $1505 14F8: 3A 7A 43 ld a,($437A) 14FB: C6 02 add a,$02 14FD: E6 07 and $07 14FF: 47 ld b,a 1500: CD 05 15 call $1505 1503: 06 07 ld b,$07 1505: FD 21 7B 43 ld iy,$437B ; load IY with address of PLAYER_BOLTS 1509: C5 push bc 150A: FD E5 push iy 150C: CD 1A 15 call $151A 150F: FD E1 pop iy 1511: C1 pop bc 1512: 11 08 00 ld de,$0008 ; sizeof (BOLT) 1515: FD 19 add iy,de 1517: 10 F0 djnz $1509 1519: C9 ret ; ; ; Expects: ; IY = pointer to BOLT structure ; ; Remarks: ; See also: 151A: FD 7E 00 ld a,(iy+$00) ; read BOLT.Direction flags (DURL bits) 151D: B7 or a ; test if bolt is moving in any direction (0 = No) 151E: 28 0C jr z,$152C ; if bolt has no direction, then its inactive, goto $152C ; bolt is active 1520: FD 34 01 inc (iy+$01) ; increment BOLT.Length to count how big the laser bolt is 1523: CD 53 15 call $1553 ; call MOVE_AND_DRAW_BOLT 1526: DC A0 15 call c,$15A0 ; if bolt has collided with something, call HANDLE_BOLT_COLLISION 1529: CD 7E 15 call $157E ; call CHECK_IF_BOLT_OFFSCREEN 152C: 01 04 00 ld bc,$0004 152F: FD 09 add iy,bc 1531: FD 35 01 dec (iy+$01) 1534: C0 ret nz 1535: FD 34 01 inc (iy+$01) 1538: AF xor a 1539: FD B6 FD or (iy-$03) ; test if BOLT.Length is zero 153C: C8 ret z ; exit if so 153D: AF xor a 153E: FD B6 00 or (iy+$00) 1541: CA 4A 15 jp z,$154A ; erase the bolt 1544: CD 53 15 call $1553 ; call MOVE_AND_DRAW_BOLT 1547: CD 7E 15 call $157E ; call CHECK_IF_BOLT_OFFSCREEN 154A: FD 35 FD dec (iy-$03) ; decrement BOLT.Length 154D: C0 ret nz 154E: FD 36 00 00 ld (iy+$00),$00 1552: C9 ret ; ; Test the DURL (direction) bits to determine the direction of this BOLT. ; Adjust the X,Y coordinates of the BOLT as required. ; ; Expects: ; A = DURL bits ; IY = pointer to BOLT structure ; ; Returns: ; Carry set if the bolt has hit something such as a wall or enemy robot MOVE_AND_DRAW_BOLT: 1553: 0F rrca ; move DURL bit for LEFT into carry 1554: D2 5A 15 jp nc,$155A ; if this bit isn't set, the bolt isn't moving left, goto $155A ; player bolt is moving left 1557: FD 35 02 dec (iy+$02) ; decrement BOLT.PX 155A: 0F rrca ; move DURL bit for RIGHT into carry 155B: D2 61 15 jp nc,$1561 ; if this bit isn't set, the bolt isn't moving right, goto $1561 ; player bolt is moving right 155E: FD 34 02 inc (iy+$02) ; increment BOLT.PX 1561: 0F rrca ; move DURL bit for UP into carry 1562: D2 68 15 jp nc,$1568 ; if this bit isn't set, the bolt isn't moving right, goto $1568 ; player bolt is moving up 1565: FD 35 03 dec (iy+$03) ; decrement BOLT.Y 1568: 0F rrca ; move DURL bit for DOWN into carry 1569: D2 6F 15 jp nc,$156F ; if this bit isn't set, the bolt isn't moving down, goto $156F ; player bolt is moving down 156C: FD 34 03 inc (iy+$03) ; increment BOLT.Y 156F: FD 66 03 ld h,(iy+$03) ; load H with BOLT.Y 1572: FD 6E 02 ld l,(iy+$02) ; load L with BOLT.PX 1575: CD A1 29 call $29A1 ; call RTOAX to get Magic RAM address and set XOR pixel mode 1578: 36 80 ld (hl),$80 ; write a single pixel for the bolt 157A: DB 4E in a,($4E) ; test if the pixel plotted tripped the collision detection hardware 157C: 07 rlca ; if carry is set, pixel was plotted onto another pixel (a collision) 157D: C9 ret ; Check if a bolt has left the screen. ; ; Expects: ; IY = pointer to BOLT structure ; CHECK_IF_BOLT_OFFSCREEN: 157E: FD 7E 02 ld a,(iy+$02) ; A = BOLT.PX 1581: FD 46 00 ld b,(iy+$00) ; B = BOLT.Direction 1584: 11 FF 03 ld de,$03FF 1587: CD 97 15 call $1597 ; call CHECK_IF_ZERO_OR_E 158A: FD 7E 03 ld a,(iy+$03) ; A = BOLT.Y 158D: 11 D0 0C ld de,$0CD0 1590: CD 97 15 call $1597 ; call CHECK_IF_ZERO_OR_E 1593: FD 70 00 ld (iy+$00),b ; set BOLT.Direction 1596: C9 ret ; Check if a supplied value in A is equal to 0 or the value in E. ; ; Expects: ; A = value ; E = value to compare against ; B = DURL Direction bits ; ; Returns: ; if A is 0 or A == E, then B is set to 0 (all Direction bits clear) ; Otherwise, B is same as on entry to routine (ie: left untouched). ; CHECK_IF_ZERO_OR_E: 1597: FE 00 cp $00 ; is value == 0? 1599: 28 02 jr z,$159D ; yes, set B to 0 159B: BB cp e ; is value == E? 159C: C0 ret nz ; exit if not 159D: 06 00 ld b,$00 ; set B to 0 159F: C9 ret ; and we're out ; ; Check if a bolt has hit the player or a robot. ; ; Expects: ; IY = pointer to BOLT structure HANDLE_BOLT_COLLISION: ; Deactivate the bolt. It's hit something - maybe just a wall. 15A0: FD 36 00 00 ld (iy+$00),$00 ; Set BOLT.Direction to 0, meaning "Inactive" ; check if the bolt has hit the player 15A4: DD 2A 76 08 ld ix,($0876) ; load IX with contents of MAN_PTR 15A8: CD CB 15 call $15CB ; call COLLISION_DETECTION ; Now check if the bolt has hit any robots 15AB: ED 4B 70 08 ld bc,($0870) ; load HL with contents of V.PTR 15AF: 78 ld a,b 15B0: B1 or c ; check if pointer is NULL 15B1: 28 17 jr z,$15CA ; if NULL, goto $15CA ; BC = pointer to VECTOR structure for robot 15B3: C5 push bc ; We want to make IX = BC. There's no ld ix,bc instruction so... 15B4: DD E1 pop ix ; IX = pointer to vector structure for robot 15B6: CD CB 15 call $15CB ; call COLLISION_DETECTION 15B9: DD 66 FF ld h,(ix-$01) 15BC: DD 6E FE ld l,(ix-$02) 15BF: E5 push hl 15C0: DD E1 pop ix 15C2: 7D ld a,l 15C3: B9 cp c 15C4: 20 F0 jr nz,$15B6 15C6: 7C ld a,h 15C7: B8 cp b 15C8: 20 EC jr nz,$15B6 15CA: C9 ret ; ; Check if a VECTOR has collided with [the head of] a BOLT. ; ; Expects: ; IX = pointer to VECTOR structure ; IY = pointer to BOLT structure ; ; Remarks: ; See also: HITCHK in bolts.asm within Frenzy's source code. COLLISION_DETECTION: 15CB: DD CB 00 56 bit 2,(ix+$00) ; test MOVE bit of VECTOR.Status 15CF: C8 ret z ; exit if not moving 15D0: DD 66 0B ld h,(ix+$0b) 15D3: DD 6E 0A ld l,(ix+$0a) ; HL = pointer to sprite pattern table 15D6: 56 ld d,(hl) ; 15D7: 23 inc hl 15D8: 5E ld e,(hl) ; DE = pointer to sprite pattern 15D9: EB ex de,hl 15DA: 56 ld d,(hl) ; read width of pattern (in bytes. 1 byte = 8 pixels) 15DB: 23 inc hl 15DC: 5E ld e,(hl) ; read height of pattern in pixels 15DD: 1C inc e ; Determine how far away the BOLT is from the VECTOR. ; This is a "is a single pixel [the head of the bolt] within the [VECTOR's] rectangle" routine. ; D = width of VECTOR pattern, bytes ; E = height of VECTOR pattern, pixels ; 15DE: FD 7E 03 ld a,(iy+$03) ; read BOLT.Y 15E1: DD 96 09 sub (ix+$09) ; subtract VECTOR.Y 15E4: 3C inc a 15E5: F8 ret m ; if BOLT.Y < VECTOR.Y then subtraction result will be negative, and M flag set 15E6: BB cp e ; 15E7: D0 ret nc ; if ((BOLT.Y - VECTOR.Y)+1 > e then exit 15E8: FD 7E 02 ld a,(iy+$02) ; read BOLT.X 15EB: DD 96 07 sub (ix+$07) ; subtract VECTOR.X 15EE: F8 ret m ; if BOLT.X < VECTOR.X then subtraction result will be negative, and M flag set 15EF: CB 22 sla d ; multiply width in bytes... 15F1: CB 22 sla d 15F3: CB 22 sla d ; ... by 8 to give pattern width in pixels 15F5: 14 inc d ; and add 1 15F6: BA cp d ; 15F7: D0 ret nc ; if (BOLT.X - VECTOR.X)+1 > d then exit 15F8: DD CB 00 FE set 7,(ix+$00) ; set HIT bit in VECTOR.STATUS 15FC: DD CB FA C6 set 0,(ix-$06) ; TODO: ???? 1600: E1 pop hl 1601: C9 ret ; ; ; 1602: F3 di 1603: 31 00 43 ld sp,$4300 1606: DB 60 in a,($60) ; read F3 1608: CB 4F bit 1,a ; CROSSHAIR PATTERN switch set? 160A: C2 3A 07 jp nz,$073A ; yes, jump to CROSSHAIR_PATTERN_TEST_MODE ; clear from $0870 - $08A3 160D: 21 70 08 ld hl,$0870 1610: 06 34 ld b,$34 1612: 36 00 ld (hl),$00 1614: 23 inc hl 1615: 10 FB djnz $1612 ; clear scratch pad RAM from $4000 - $43ff 1617: 21 00 40 ld hl,$4000 161A: 01 00 04 ld bc,$0400 161D: AF xor a 161E: 77 ld (hl),a 161F: 23 inc hl 1620: 0D dec c 1621: 20 FB jr nz,$161E 1623: 10 F9 djnz $161E 1625: CD 21 17 call $1721 ; Copy high score entries from CMOS RAM to RAM. 1628: 21 DC 08 ld hl,$08DC ; load HL with address of CMOS_HIGH_SCORES 162B: 11 02 43 ld de,$4302 ; load DE with address of HI_SCORES 162E: 06 1E ld b,$1E ; the high score table requires $1E (30 decimal) *pairs* of bytes in CMOS ; as there are 10 high score entries requiring 6 bytes each. 1630: 7E ld a,(hl) ; read BCD digit of score from CMOS 1631: 23 inc hl ; bump HL to point to next BCD digit 1632: E6 F0 and $F0 ; mask in upper nibble (plain English: retain the tens part of the BCD number) 1634: 4F ld c,a ; preserve in C 1635: 7E ld a,(hl) ; read BCD digit of score from CMOS 1636: 23 inc hl ; bump HL to point to next BCD digit 1637: 0F rrca ; shift number held in upper nibble.. 1638: 0F rrca 1639: 0F rrca 163A: 0F rrca ; .. to lower nibble 163B: E6 0F and $0F ; mask in lower nibble (discard any rubbish brought in by rrca) 163D: B1 or c ; combine result with value preserved @ $1634 163E: 12 ld (de),a ; write to HI_SCORES in memory 163F: 13 inc de 1640: 10 EE djnz $1630 1642: DB 49 in a,($49) ; read SYSTEM 1644: 2F cpl 1645: 21 9F 08 ld hl,$089F 1648: 77 ld (hl),a 1649: 23 inc hl 164A: 77 ld (hl),a 164B: CD 66 16 call $1666 164E: CD AC 19 call $19AC 1651: CD 8B 18 call $188B 1654: CD 98 1A call $1A98 1657: CD 8B 18 call $188B 165A: CD 85 16 call $1685 165D: CA 4B 16 jp z,$164B 1660: CD 66 16 call $1666 1663: CD B2 18 call $18B2 1666: F3 di 1667: E1 pop hl 1668: 22 00 44 ld ($4400),hl 166B: 32 02 44 ld ($4402),a 166E: 31 00 43 ld sp,$4300 1671: CD 22 1E call $1E22 ; call CREATE_JOB 1674: FD 2A 72 08 ld iy,($0872) 1678: CD F1 22 call $22F1 167B: CD AB 26 call $26AB 167E: 2A 00 44 ld hl,($4400) 1681: 3A 02 44 ld a,($4402) 1684: E9 jp (hl) 1685: 2A 3E 43 ld hl,($433E) 1688: 22 73 43 ld ($4373),hl 168B: 3A 40 43 ld a,($4340) 168E: 32 75 43 ld ($4375),a 1691: 21 00 00 ld hl,$0000 1694: 22 3E 43 ld ($433E),hl 1697: 22 3F 43 ld ($433F),hl 169A: 2A 5C 43 ld hl,($435C) 169D: E5 push hl 169E: 21 D9 16 ld hl,$16D9 16A1: 22 6F 43 ld ($436F),hl 16A4: 3E FF ld a,$FF 16A6: 32 6E 43 ld ($436E),a ; set IS_DEMO_MODE 16A9: 01 0C 00 ld bc,$000C 16AC: 11 44 43 ld de,$4344 16AF: 21 CD 16 ld hl,$16CD 16B2: ED B0 ldir 16B4: CD 9D 20 call $209D 16B7: E1 pop hl 16B8: F5 push af 16B9: 22 5C 43 ld ($435C),hl 16BC: CD 78 26 call $2678 ; call RANDOM 16BF: 2A 73 43 ld hl,($4373) 16C2: 22 3E 43 ld ($433E),hl 16C5: 2A 74 43 ld hl,($4374) 16C8: 22 3F 43 ld ($433F),hl 16CB: F1 pop af 16CC: C9 ret 16CD: 01 02 02 ld bc,$0202 16D0: 1E 64 ld e,$64 16D2: 01 70 00 ld bc,$0070 16D5: 01 1E 02 ld bc,$021E 16D8: 00 nop 16D9: 0A ld a,(bc) 16DA: 8F adc a,a 16DB: 12 ld (de),a 16DC: 8F adc a,a 16DD: 14 inc d 16DE: 8F adc a,a 16DF: 19 add hl,de 16E0: 8F adc a,a 16E1: 02 ld (bc),a 16E2: 9F sbc a,a 16E3: 19 add hl,de 16E4: 8F adc a,a 16E5: 06 8F ld b,$8F 16E7: 18 8F jr $1678 16E9: 02 ld (bc),a 16EA: FF rst $38 16EB: 00 nop 16EC: FF rst $38 16ED: 02 ld (bc),a 16EE: FF rst $38 16EF: BF cp a 16F0: 08 ex af,af' 16F1: AF xor a 16F2: 09 add hl,bc 16F3: BF cp a 16F4: 01 BF 09 ld bc,$09BF 16F7: FF rst $38 16F8: 09 add hl,bc 16F9: C1 pop bc 16FA: 12 ld (de),a 16FB: 8F adc a,a 16FC: 00 nop 16FD: FF rst $38 16FE: 01 D4 08 ld bc,$08D4 1701: BF cp a 1702: 18 BF jr $16C3 1704: 18 8F jr $1695 1706: 08 ex af,af' 1707: FF rst $38 1708: 08 ex af,af' 1709: B6 or (hl) 170A: 02 ld (bc),a 170B: C0 ret nz 170C: 06 9C ld b,$9C 170E: 12 ld (de),a 170F: 8F adc a,a 1710: 08 ex af,af' 1711: BF cp a 1712: 00 nop 1713: FF rst $38 1714: 14 inc d 1715: 8F adc a,a 1716: 14 inc d 1717: 8F adc a,a 1718: 14 inc d 1719: 8F adc a,a 171A: 14 inc d 171B: 8F adc a,a 171C: 14 inc d 171D: 8F adc a,a 171E: 00 nop 171F: FF rst $38 1720: FF rst $38 ; ; NMI handler ; ; See also: NMI.ASM in Frenzy's source code NMI_HANDLER: 1721: ED 73 5E 08 ld ($085E),sp ; preserve stack pointer in NMI_STACK_PTR 1725: 31 5E 08 ld sp,$085E 1728: F5 push af 1729: C5 push bc 172A: D5 push de 172B: E5 push hl 172C: DD E5 push ix 172E: DB 65 in a,($65) ; read SW2 1730: CB 7F bit 7,a ; test BOOKKEEPING button 1732: C2 05 06 jp nz,$0605 ; if bit is set, goto BOOKKEEPING 1735: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 1738: B7 or a 1739: CC 12 1D call z,$1D12 173C: CD 76 17 call $1776 ; call C.LOAD ; Do voice if not demo - This section of code is replicated in Frenzy. 173F: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 1742: B7 or a ; test flag 1743: 20 1D jr nz,$1762 ; if flag is non zero then in demo mode, goto STOP_TALKING. 1745: 2A 98 08 ld hl,($0898) ; Get VOICE_PC ; speech loop 1748: 7C ld a,h 1749: B5 or l 174A: 28 19 jr z,$1765 ; if HL = 0, exit routine 174C: DB 44 in a,($44) ; read VOICE_PORT 174E: E6 C0 and $C0 1750: FE 40 cp $40 1752: 20 11 jr nz,$1765 ; if busy, exit routine ; speak 1754: 7E ld a,(hl) ; read byte to send to voice hardware 1755: CB 7F bit 7,a ; test if byte is a terminator byte 1757: 20 09 jr nz,$1762 ; if bit 7 is set, it is a terminator byte, goto STOP_TALKINGto shut up! 1759: 23 inc hl 175A: D3 44 out ($44),a ; output to VOICE_PORT 175C: CB 77 bit 6,a ; test if a word 175E: 28 05 jr z,$1765 ; exit if not a word 1760: 18 E6 jr $1748 ; do another byte for speech ; stop talking STOP_TALKING: 1762: 21 00 00 ld hl,$0000 ; NULL pointer 1765: 22 98 08 ld ($0898),hl ; update VOICE_PC ; Clean up 1768: DD E1 pop ix 176A: E1 pop hl 176B: D1 pop de 176C: C1 pop bc 176D: F1 pop af 176E: ED 7B 5E 08 ld sp,($085E) ; restore stack pointer 1772: D3 4C out ($4C),a ; write to nmi_enable_r 1774: ED 45 retn ; ; Frenzy's source code states the following about this routine: ; ; OUTPUT DATA TO ALL REGISTERS FROM RAM ; DO CONTROL REGISTERS ; ; All I know about this routine is that it writes to the audio control registers. ; If anyone has any more information, please email me. Credit will be given, of course. ; ; See also: ; C.LOAD within NMI.ASM in Frenzy's source code. C.LOAD: 1776: 21 78 08 ld hl,$0878 ; load HL with address of TCR1 1779: 46 ld b,(hl) 177A: 23 inc hl ; bump HL to point to TCR2 177B: 56 ld d,(hl) 177C: 23 inc hl ; bump HL to point to TCR3 177D: 5E ld e,(hl) 177E: 23 inc hl 177F: 0E 41 ld c,$41 ; load C with CR2_PORT 1781: CB 80 res 0,b 1783: CB C2 set 0,d 1785: ED 51 out (c),d 1787: 0D dec c 1788: ED 41 out (c),b 178A: 0C inc c 178B: CB 82 res 0,d 178D: ED 51 out (c),d 178F: 0D dec c 1790: ED 59 out (c),e ; DO TIMERS T.LOAD: 1792: 0C inc c 1793: 0C inc c 1794: 06 03 ld b,$03 1796: 79 ld a,c 1797: 0C inc c 1798: 51 ld d,c T.LOOP: 1799: 5E ld e,(hl) 179A: 23 inc hl 179B: 4F ld c,a 179C: 7E ld a,(hl) 179D: 23 inc hl 179E: ED 79 out (c),a 17A0: 79 ld a,c 17A1: 4A ld c,d 17A2: ED 59 out (c),e 17A4: 14 inc d 17A5: 14 inc d 17A6: 10 F1 djnz $1799 ; DO NOISE AND VOLUMES 17A8: 0D dec c 17A9: 3E 00 ld a,$00 17AB: 06 04 ld b,$04 V.LOOP: 17AD: B6 or (hl) 17AE: 23 inc hl 17AF: ED 79 out (c),a 17B1: E6 C0 and $C0 17B3: C6 40 add a,$40 17B5: 10 F6 djnz $17AD 17B7: C9 ret ; ; ; ; ; 17B8: 06 06 ld b,$06 17BA: 21 BE 08 ld hl,$08BE ; load HL with address of CMOS_NUM_PLAYS 17BD: CD B3 2D call $2DB3 ; call INCREMENT_BY_1 17C0: 3A 76 43 ld a,($4376) ; read NUMBER_OF_PLAYERS 17C3: FE 02 cp $02 17C5: CC B3 2D call z,$2DB3 ; call INCREMENT_BY_1 17C8: CD 51 18 call $1851 17CB: 01 0C 00 ld bc,$000C 17CE: 11 44 43 ld de,$4344 17D1: 21 7F 18 ld hl,$187F ; load HL with address of DEFAULT_PLAYER_STATE 17D4: ED B0 ldir 17D6: CD 78 26 call $2678 ; call RANDOM 17D9: 2A 5C 43 ld hl,($435C) 17DC: 22 45 43 ld ($4345),hl 17DF: AF xor a 17E0: 32 6E 43 ld ($436E),a ; clear IS_DEMO_MODE flag 17E3: 32 9A 08 ld ($089A),a ; clear IS_CHICKEN flag 17E6: 3C inc a 17E7: 32 9B 08 ld ($089B),a ; set TALK_TIMER 17EA: CD A7 33 call $33A7 17ED: 21 44 43 ld hl,$4344 17F0: 11 50 43 ld de,$4350 17F3: 01 0C 00 ld bc,$000C 17F6: ED B0 ldir 17F8: 3E 02 ld a,$02 17FA: 77 ld (hl),a 17FB: 3A 76 43 ld a,($4376) ; read NUMBER_OF_PLAYERS 17FE: FE 02 cp $02 1800: 28 04 jr z,$1806 1802: AF xor a 1803: 32 55 43 ld ($4355),a 1806: FB ei 1807: 21 1E 64 ld hl,$641E 180A: 22 47 43 ld ($4347),hl ; set MAN_X and MAN_Y 180D: 3A 44 43 ld a,($4344) ; read CURRENT_PLAYER 1810: 3D dec a 1811: 28 0B jr z,$181E 1813: DB 4A in a,($4A) ; read player 2 controls 1815: CB 7F bit 7,a 1817: 28 05 jr z,$181E 1819: 3E E0 ld a,$E0 181B: 32 47 43 ld ($4347),a ; set MAN_X 181E: CD 9D 20 call $209D 1821: CD 78 26 call $2678 ; call RANDOM 1824: 2A 5C 43 ld hl,($435C) 1827: 22 45 43 ld ($4345),hl 182A: 3E 5A ld a,$5A 182C: CD 6D 1E call $1E6D 182F: CD F1 22 call $22F1 1832: 21 49 43 ld hl,$4349 ; load HL with address of DEATHS 1835: 35 dec (hl) ; reduce number of lives 1836: 08 ex af,af' 1837: CD 6A 18 call $186A 183A: 7E ld a,(hl) 183B: B7 or a 183C: C2 06 18 jp nz,$1806 183F: 08 ex af,af' 1840: 20 F5 jr nz,$1837 1842: CD 6A 18 call $186A 1845: CD 51 2C call $2C51 1848: CD 6A 18 call $186A 184B: CD 51 2C call $2C51 184E: C3 4B 16 jp $164B 1851: 21 00 00 ld hl,$0000 1854: 22 3E 43 ld ($433E),hl 1857: 22 40 43 ld ($4340),hl 185A: 22 42 43 ld ($4342),hl 185D: 22 A1 08 ld ($08A1),hl 1860: 22 A2 08 ld ($08A2),hl 1863: 21 DB 1A ld hl,$1ADB 1866: 22 98 08 ld ($0898),hl ; set VOICE_PC 1869: C9 ret 186A: E5 push hl 186B: 21 44 43 ld hl,$4344 186E: 11 50 43 ld de,$4350 1871: 06 0C ld b,$0C 1873: 1A ld a,(de) 1874: 4E ld c,(hl) 1875: EB ex de,hl 1876: 12 ld (de),a 1877: 71 ld (hl),c 1878: EB ex de,hl 1879: 23 inc hl 187A: 13 inc de 187B: 10 F6 djnz $1873 187D: E1 pop hl 187E: C9 ret ; ; Default player state ; DEFAULT_PLAYER_STATE: 187F: 01 00 00 ld bc,$0000 1882: 1E 64 ld e,$64 1884: 03 inc bc 1885: 60 ld h,b 1886: 00 nop 1887: 05 dec b 1888: 5A ld e,d 1889: 00 nop 188A: 00 nop 188B: 06 03 ld b,$03 188D: 2A 72 08 ld hl,($0872) 1890: 23 inc hl 1891: 36 3C ld (hl),$3C 1893: 2B dec hl 1894: CB CE set 1,(hl) 1896: DB 65 in a,($65) ; read SW2 1898: CB 47 bit 0,a 189A: 28 04 jr z,$18A0 189C: 3E 01 ld a,$01 189E: 18 21 jr $18C1 18A0: CD 7B 19 call $197B 18A3: CD 97 19 call $1997 18A6: 20 0A jr nz,$18B2 18A8: 2A 72 08 ld hl,($0872) 18AB: CB 4E bit 1,(hl) 18AD: 20 E7 jr nz,$1896 18AF: 10 DC djnz $188D 18B1: C9 ret 18B2: 6F ld l,a 18B3: CD F1 18 call $18F1 ; call DECREMENT_CREDITS 18B6: CB 4D bit 1,l 18B8: 3E 01 ld a,$01 18BA: 28 05 jr z,$18C1 18BC: CD F1 18 call $18F1 ; call DECREMENT_CREDITS 18BF: 3E 02 ld a,$02 18C1: 32 76 43 ld ($4376),a 18C4: 2A 72 08 ld hl,($0872) 18C7: 36 01 ld (hl),$01 18C9: E1 pop hl 18CA: C3 B8 17 jp $17B8 ; Display credits ; ; See also: CREDS in coins.asm within Frenzy's source code. ; PRINT_CREDITS: 18CD: E5 push hl ; create space for a word on the stack 18CE: 21 00 00 ld hl,$0000 18D1: 39 add hl,sp ; HL = SP 18D2: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 18D5: 77 ld (hl),a ; write number of credits to our temp space on stack 18D6: 06 02 ld b,$02 ; You can have up to 99 credits, so 2 digits long. 18D8: 11 78 D5 ld de,$D578 ; D = Y coordinate, E = X coordinate 18DB: CD 40 2A call $2A40 ; call PRINT_DIGITS 18DE: E1 pop hl ; discard temp space on stack 18DF: C9 ret ; ; Read number of credits from CMOS ; ; Returns: ; A = Number of credits, BCD encoded ; ; See also: Getc in coins.asm within Frenzy's source code. GET_CREDITS_AS_BCD: 18E0: 3A A5 08 ld a,($08A5) ; load HL with address of CMOS_CREDITS+1 18E3: 0F rrca ; move upper nibble.. 18E4: 0F rrca 18E5: 0F rrca 18E6: 0F rrca ; to lower nibble. 18E7: E6 0F and $0F ; Now A is a value from 0..9. 18E9: 4F ld c,a ; preserve A in C 18EA: 3A A4 08 ld a,($08A4) ; load HL with address of CMOS_CREDITS 18ED: E6 F0 and $F0 ; mask in upper nibble and discard lower 18EF: B1 or c ; combine with value we preserved in C 18F0: C9 ret ; ; Decrement credits by 1 ; ; See also: DECCRD in coins.asm within Frenzy's source code. ; DECREMENT_CREDITS: 18F1: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 18F4: C6 99 add a,$99 ; add -1 in 9's complement arithmetic 18F6: 27 daa 18F7: 4F ld c,a ; Preserve A in C 18F8: E6 F0 and $F0 ; mask in upper nibble. We can store that "as-is" into CMOS 18FA: 32 A4 08 ld ($08A4),a ; set first digit of CMOS_CREDITS 18FD: 79 ld a,c ; restore A from C 18FE: 07 rlca ; move lower nibble.. 18FF: 07 rlca 1900: 07 rlca 1901: 07 rlca ; .. to upper nibble. 1902: E6 F0 and $F0 ; Discard lower nibble - it'll be garbage 1904: 32 A5 08 ld ($08A5),a ; set second digit of CMOS_CREDITS 1907: C9 ret 1908: 7E ld a,(hl) 1909: B7 or a 190A: C8 ret z 190B: C5 push bc 190C: E5 push hl 190D: 35 dec (hl) 190E: 78 ld a,b 190F: 3D dec a 1910: 87 add a,a 1911: 87 add a,a 1912: 87 add a,a 1913: 5F ld e,a 1914: 16 00 ld d,$00 1916: 21 A6 08 ld hl,$08A6 1919: 19 add hl,de 191A: 06 08 ld b,$08 191C: CD B3 2D call $2DB3 ; call INCREMENT_BY_1 191F: E1 pop hl 1920: E5 push hl 1921: 11 05 00 ld de,$0005 1924: 19 add hl,de 1925: 7E ld a,(hl) 1926: 57 ld d,a 1927: 3C inc a 1928: E6 03 and $03 192A: 77 ld (hl),a 192B: ED 78 in a,(c) 192D: E6 0F and $0F 192F: CB 1A rr d 1931: 17 rla 1932: 4F ld c,a 1933: 06 00 ld b,$00 1935: 21 5B 19 ld hl,$195B 1938: 09 add hl,bc 1939: 7E ld a,(hl) 193A: CB 42 bit 0,d 193C: 28 04 jr z,$1942 193E: 07 rlca 193F: 07 rlca 1940: 07 rlca 1941: 07 rlca 1942: E6 0F and $0F 1944: C6 00 add a,$00 1946: 27 daa 1947: 57 ld d,a 1948: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 194B: FE 99 cp $99 194D: 28 09 jr z,$1958 194F: 82 add a,d 1950: 27 daa 1951: 30 02 jr nc,$1955 1953: 3E 99 ld a,$99 1955: CD F7 18 call $18F7 1958: E1 pop hl 1959: C1 pop bc 195A: C9 ret 195B: 11 11 22 ld de,$2211 195E: 22 33 33 ld ($3333),hl 1961: 44 ld b,h 1962: 44 ld b,h 1963: 55 ld d,l 1964: 55 ld d,l 1965: 66 ld h,(hl) 1966: 66 ld h,(hl) 1967: 77 ld (hl),a 1968: 77 ld (hl),a 1969: AA xor d 196A: AA xor d 196B: EE EE xor $EE 196D: 00 nop 196E: 11 11 22 ld de,$2211 1971: 00 nop 1972: 55 ld d,l 1973: 00 nop 1974: 77 ld (hl),a 1975: 00 nop 1976: 21 11 21 ld hl,$2111 1979: 11 32 C5 ld de,$C532 197C: 21 9C 08 ld hl,$089C 197F: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 1982: F5 push af 1983: 01 62 03 ld bc,$0362 1986: CD 08 19 call $1908 1989: 23 inc hl 198A: 0C inc c 198B: 10 F9 djnz $1986 198D: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 1990: C1 pop bc 1991: B8 cp b 1992: C4 CD 18 call nz,$18CD 1995: C1 pop bc 1996: C9 ret 1997: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 199A: 2E 00 ld l,$00 199C: B7 or a 199D: 28 08 jr z,$19A7 199F: FE 01 cp $01 19A1: 2E 01 ld l,$01 19A3: 28 02 jr z,$19A7 19A5: 2E 03 ld l,$03 19A7: DB 49 in a,($49) ; read SYSTEM 19A9: 2F cpl 19AA: A5 and l 19AB: C9 ret ; Definitely called 19AC: CD 4E 1A call $1A4E ; call CLEAR_SCREEN 19AF: CD AF 35 call $35AF ; call SET_COLOUR_ATTRS_35AF 19B2: CD 7B 29 call $297B ; call PRINT_STRING_297B 19B5: 90 0C BE ; X/Y coordinates 19B8: 1F 31 39 38 30 20 53 54 45 52 4E 20 45 6C 65 63 .1980 STERN Elec 19C8: 74 72 6F 6E 69 63 73 2C 20 49 6E 63 2E 00 tronics, Inc. 19D6: CD CD 18 call $18CD 19D9: CD 14 23 call $2314 ; call SHOW_SCORE 19DC: CD ED 1A call $1AED ; call LTABLE 19DF: 04 inc b 19E0: 1B dec de 19E1: 2D dec l 19E2: 1B dec de 19E3: 17 rla 19E4: 1B dec de 19E5: 45 ld b,l 19E6: 1B dec de 19E7: 21 02 43 ld hl,$4302 19EA: 3E 01 ld a,$01 19EC: 32 00 43 ld ($4300),a 19EF: 11 38 18 ld de,$1838 19F2: D5 push de 19F3: E5 push hl 19F4: 7E ld a,(hl) 19F5: 23 inc hl 19F6: B6 or (hl) 19F7: 23 inc hl 19F8: B6 or (hl) 19F9: E1 pop hl 19FA: E5 push hl 19FB: 20 04 jr nz,$1A01 19FD: E1 pop hl 19FE: D1 pop de 19FF: 18 35 jr $1A36 1A01: 21 00 43 ld hl,$4300 1A04: 06 02 ld b,$02 1A06: CD 40 2A call $2A40 ; call PRINT_DIGITS 1A09: 13 inc de 1A0A: E1 pop hl 1A0B: 06 06 ld b,$06 1A0D: CD 4A 2A call $2A4A 1A10: 13 inc de 1A11: AF xor a 1A12: 4E ld c,(hl) 1A13: CD DB 29 call $29DB ; call PRINT_CHAR 1A16: 13 inc de 1A17: 23 inc hl 1A18: 4E ld c,(hl) 1A19: CD DB 29 call $29DB ; call PRINT_CHAR 1A1C: 13 inc de 1A1D: 23 inc hl 1A1E: 4E ld c,(hl) 1A1F: CD DB 29 call $29DB ; call PRINT_CHAR 1A22: 23 inc hl 1A23: D1 pop de 1A24: 7A ld a,d 1A25: C6 10 add a,$10 1A27: 57 ld d,a 1A28: 3A 00 43 ld a,($4300) 1A2B: C6 01 add a,$01 1A2D: 27 daa 1A2E: 32 00 43 ld ($4300),a 1A31: FE 11 cp $11 1A33: C2 F2 19 jp nz,$19F2 1A36: 21 00 46 ld hl,$4600 1A39: CD 45 1A call $1A45 ; call WRITE_FF_64_TIMES_HL 1A3C: 21 00 5B ld hl,$5B00 1A3F: CD 45 1A call $1A45 ; call WRITE_FF_64_TIMES_HL 1A42: 21 80 5D ld hl,$5D80 ; ; Fill 64 memory addresses with #$FF (255 decimal) ; Expects: ; HL = start memory address WRITE_FF_64_TIMES_HL: 1A45: 3E FF ld a,$FF 1A47: 06 40 ld b,$40 1A49: 77 ld (hl),a 1A4A: 23 inc hl 1A4B: 10 FC djnz $1A49 1A4D: C9 ret ; ; ; CLEAR_SCREEN: ; fill colour RAM with 0 1A4E: 21 00 81 ld hl,$8100 1A51: 01 00 07 ld bc,$0700 1A54: AF xor a 1A55: 77 ld (hl),a 1A56: 23 inc hl 1A57: 0D dec c 1A58: 20 FB jr nz,$1A55 1A5A: 10 F9 djnz $1A55 1A5C: F3 di 1A5D: ED 73 00 43 ld ($4300),sp ; clear screen image RAM by using stack commands ; Set stack pointer to top of screen image RAM 1A61: 31 00 60 ld sp,$6000 1A64: 06 E0 ld b,$E0 1A66: 11 00 00 ld de,$0000 1A69: D5 push de ; write 0... 1A6A: D5 push de 1A6B: D5 push de 1A6C: D5 push de 1A6D: D5 push de 1A6E: D5 push de 1A6F: D5 push de 1A70: D5 push de 1A71: D5 push de 1A72: D5 push de 1A73: D5 push de 1A74: D5 push de 1A75: D5 push de 1A76: D5 push de 1A77: D5 push de 1A78: D5 push de ; .. to screen image RAM 1A79: 10 EE djnz $1A69 1A7B: ED 7B 00 43 ld sp,($4300) 1A7F: FB ei 1A80: DB 4A in a,($4A) ; read player 2 controls 1A82: CB 7F bit 7,a ; test DIP switch to check if upright 1A84: 20 0D jr nz,$1A93 1A86: 3A 44 43 ld a,($4344) ; read CURRENT_PLAYER 1A89: FE 02 cp $02 ; player 2 playing? 1A8B: 20 06 jr nz,$1A93 ; cocktail cabinet 1A8D: 3E 08 ld a,$08 1A8F: 32 79 43 ld ($4379),a ; set FLIP flag 1A92: C9 ret ; upright cabinet 1A93: AF xor a 1A94: 32 79 43 ld ($4379),a ; set FLIP flag 1A97: C9 ret 1A98: CD DD 1A call $1ADD ; call CLEAR_CHYRON 1A9B: CD E0 18 call $18E0 ; call GET_CREDITS_AS_BCD 1A9E: 28 21 jr z,$1AC1 1AA0: 3D dec a 1AA1: 28 0F jr z,$1AB2 1AA3: CD 13 36 call $3613 1AA6: CD ED 1A call $1AED ; call LTABLE 1AA9: 94 1B ; $1B94: Push 1 or 2 player start button DE 1B ; $1BDE: Startknoepfe druecken. BB 1B ; $1BBB: Pousser bouton start 1 ou 2. FB 1B ; $1BFB: Pulsar Start. 1AB1: C9 ret 1AB2: CD 0A 36 call $360A 1AB5: CD ED 1A call $1AED ; call LTABLE 1AB8: 54 1B ; $1B54: Push 1 Player Start Button. DE 1B ; $1BDE: Startknoepfe druecken. 76 1B ; $1B76: Pousser bouton start 1. FB 1B ; $1BFB: Pulsar Start. 1AC0: C9 ret 1AC1: CD 01 36 call $3601 1AC4: CD ED 1A call $1AED ; call LTABLE 1AC7: 0F 1C ; $1C0F: Insert Coin. 3F 1C ; $1C3F: Munze einwerfen. 22 1C ; $1C22: Introduire la monnaie. 56 1C ; $1C56: Ponga la moneda. ; Say "coins detected in pocket" 1ACF: 21 D6 1A ld hl,$1AD6 ; load HL with address of COINS_DETECTED_IN_POCKET speech 1AD2: 22 98 08 ld ($0898),hl ; set VOICE_PC 1AD5: C9 ret COINS_DETECTED_IN_POCKET: 1AD6: 65 10 ; COINS 09 ; DETECTED 0B ; IN 11 ; POCKET 45 FF ; ; Clears the message area which holds the copyright message and instructions to players ; such as Push 1 or 2 player start ; ; Remarks: ; named LERASE (erase line for messages) in gameover.asm within Frenzy's source code. ; CLEAR_CHYRON: 1ADD: 21 C0 5B ld hl,$5BC0 1AE0: 01 C0 02 ld bc,$02C0 1AE3: AF xor a 1AE4: 77 ld (hl),a 1AE5: 23 inc hl 1AE6: 0D dec c 1AE7: C2 E4 1A jp nz,$1AE4 1AEA: 10 F8 djnz $1AE4 1AEC: C9 ret ; ; ; ; Remarks: ; Named LTABLE in gameover.asm within Frenzy's source code. ; LTABLE: 1AED: E1 pop hl ; get table address 1AEE: 54 ld d,h 1AEF: 5D ld e,l ; save table address in DE 1AF0: 01 08 00 ld bc,$0008 ; offset to end of table 1AF3: 09 add hl,bc 1AF4: E5 push hl 1AF5: EB ex de,hl 1AF6: DB 60 in a,($60) ; read F3 1AF8: E6 C0 and $C0 ; mask in bits set when German, French, Spanish 1AFA: 07 rlca 1AFB: 07 rlca 1AFC: 07 rlca 1AFD: 4F ld c,a 1AFE: 09 add hl,bc 1AFF: 7E ld a,(hl) 1B00: 23 inc hl 1B01: 66 ld h,(hl) 1B02: 6F ld l,a 1B03: E9 jp (hl) 1B04: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B07: 90 58 00 ; X/Y coordinates 1B0A: 48 69 67 68 20 53 63 6F 72 65 73 00 High Scores. 1B16: C9 ret 1B17: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B1A: 90 48 00 ; X/Y coordinates 1B1D: 4D 65 69 6C 6C 65 75 72 20 53 63 6F 72 65 00 Meilleur Score.. 1B2C: C9 ret 1B2D: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B30: 90 40 00 ; X/Y coordinates 1B33: 48 6F 65 63 68 73 74 65 72 20 47 65 62 6E 69 73 Hoechster Gebnis 1B43: 00 1B44: C9 ret 1B45: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B48: 90 5C 00 ; X/Y coordinates 1B4B: 52 65 63 6F 72 64 73 00 Records. 1B53: C9 ret 1B54: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B57: 90 14 BE ; X/Y coordinates 1B5A: 50 75 73 68 20 31 20 50 6C 61 79 65 72 20 53 74 Push 1 Player St 1B6A: 61 72 74 20 42 75 74 74 6F 6E 00 art Button. 1B75: C9 ret 1B76: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B79: 90 24 BE ; X/Y coordinates 1B7C: 50 6F 75 73 73 65 72 20 62 6F 75 74 6F 6E 20 73 Pousser bouton s 1B8C: 74 61 72 74 20 31 00 tart 1. 1B93: C9 ret 1B94: CD 7B 29 call $297B ; call PRINT_STRING_297B 1B97: 90 04 BE ; X/Y coordinates 1B9A: 50 75 73 68 20 31 20 6F 72 20 32 20 50 6C 61 79 Push 1 or 2 Play 1BAA: 65 72 20 53 74 61 72 74 20 42 75 74 74 6F 6E 00 er Start Button. 1BBA: C9 ret 1BBB: CD 7B 29 call $297B ; call PRINT_STRING_297B 1BBE: 90 10 BE ; X/Y coordinates 1BC1: 50 6F 75 73 73 65 72 20 62 6F 75 74 6F 6E 20 73 Pousser bouton s 1BD1: 74 61 72 74 20 31 20 6F 75 20 32 00 tart 1 ou 2. 1BDD: C9 ret 1BDE: CD 7B 29 call $297B ; call PRINT_STRING_297B 1BE1: 90 20 BE ; X/Y coordinates 1BE4: 53 74 61 72 74 6B 6E 6F 65 70 66 65 20 64 72 75 Startknoepfe dru 1BF4: 65 63 6B 65 6E 00 C9 CD 7B 29 90 44 BE 50 75 6C ecken. 1BFA: C9 ret 1BFB: CD 7B 29 call $297B ; call PRINT_STRING_297B 1BFE: 90 44 BE ; X/Y coordinates 1C01: 50 75 6C 73 61 72 20 53 74 61 72 74 00 Pulsar Start. 1C0E: C9 ret 1C0F: CD 7B 29 call $297B ; call PRINT_STRING_297B 1C12: 90 58 BE ; X/Y coordinates 1C15: 49 6E 73 65 72 74 20 43 6F 69 6E 00 Insert Coin. 1C21: C9 ret 1C22: CD 7B 29 call $297B ; call PRINT_STRING_297B 1C25: 90 30 BE ; X/Y coordinates 1C28: 49 6E 74 72 6F 64 75 69 72 65 20 6C 61 20 6D 6F Introduire la mo 1C38: 6E 6E 61 69 65 00 nnaie. 1C3E: C9 ret 1C3F: CD 7B 29 call $297B ; call PRINT_STRING_297B 1C42: 90 48 BE ; X/Y coordinates 1C45: 4D 75 6E 7A 65 20 65 69 6E 77 65 72 66 65 6E 00 Munze einwerfen. 1C55: C9 ret 1C56: CD 7B 29 call $297B ; call PRINT_STRING_297B 1C59: 90 48 BE ; X/Y coordinates 1C5C: 50 6F 6E 67 61 20 6C 61 20 6D 6F 6E 65 64 61 00 Ponga la moneda. 1C6C: C9 ret 1C6D: A3 and e 1C6E: C5 push bc 1C6F: F5 push af 1C70: FD 2A 76 08 ld iy,($0876) ; load IY with contents of MAN_PTR 1C74: FD 66 07 ld h,(iy+$07) 1C77: FD 6E 09 ld l,(iy+$09) 1C7A: CD E7 1C call $1CE7 1C7D: D5 push de 1C7E: DD 66 07 ld h,(ix+$07) 1C81: DD 6E 09 ld l,(ix+$09) 1C84: 2D dec l 1C85: 2D dec l 1C86: 2D dec l 1C87: 2D dec l 1C88: 25 dec h 1C89: 25 dec h 1C8A: 25 dec h 1C8B: 25 dec h 1C8C: CD E7 1C call $1CE7 1C8F: D9 exx 1C90: 47 ld b,a 1C91: D9 exx 1C92: C1 pop bc 1C93: 79 ld a,c 1C94: BB cp e 1C95: 20 03 jr nz,$1C9A 1C97: F1 pop af 1C98: C1 pop bc 1C99: C9 ret 1C9A: 7C ld a,h 1C9B: E5 push hl 1C9C: C6 10 add a,$10 1C9E: 67 ld h,a 1C9F: CD E7 1C call $1CE7 1CA2: D9 exx 1CA3: 4F ld c,a 1CA4: D9 exx 1CA5: 7D ld a,l 1CA6: C6 13 add a,$13 1CA8: 6F ld l,a 1CA9: CD E7 1C call $1CE7 1CAC: D9 exx 1CAD: 57 ld d,a 1CAE: D9 exx 1CAF: 7D ld a,l 1CB0: E1 pop hl 1CB1: 6F ld l,a 1CB2: CD E7 1C call $1CE7 1CB5: D9 exx 1CB6: 5F ld e,a 1CB7: F1 pop af 1CB8: 67 ld h,a 1CB9: 2E 00 ld l,$00 1CBB: CB 5C bit 3,h 1CBD: 28 06 jr z,$1CC5 1CBF: 78 ld a,b 1CC0: B1 or c 1CC1: E6 08 and $08 1CC3: B5 or l 1CC4: 6F ld l,a 1CC5: CB 54 bit 2,h 1CC7: 28 06 jr z,$1CCF 1CC9: 7A ld a,d 1CCA: B3 or e 1CCB: E6 04 and $04 1CCD: B5 or l 1CCE: 6F ld l,a 1CCF: CB 4C bit 1,h 1CD1: 28 06 jr z,$1CD9 1CD3: 78 ld a,b 1CD4: B3 or e 1CD5: E6 02 and $02 1CD7: B5 or l 1CD8: 6F ld l,a 1CD9: CB 44 bit 0,h 1CDB: 28 06 jr z,$1CE3 1CDD: 79 ld a,c 1CDE: B2 or d 1CDF: E6 01 and $01 1CE1: B5 or l 1CE2: 6F ld l,a 1CE3: 2F cpl 1CE4: A4 and h 1CE5: C1 pop bc 1CE6: C9 ret 1CE7: 7D ld a,l 1CE8: 1E 00 ld e,$00 1CEA: FE 46 cp $46 1CEC: 38 08 jr c,$1CF6 1CEE: 1E 05 ld e,$05 1CF0: FE 8A cp $8A 1CF2: 38 02 jr c,$1CF6 1CF4: 1E 0A ld e,$0A 1CF6: 7C ld a,h 1CF7: 06 05 ld b,$05 1CF9: 0E 3A ld c,$3A 1CFB: 16 30 ld d,$30 1CFD: B9 cp c 1CFE: 38 08 jr c,$1D08 1D00: 1C inc e 1D01: 08 ex af,af' 1D02: 79 ld a,c 1D03: 82 add a,d 1D04: 4F ld c,a 1D05: 08 ex af,af' 1D06: 10 F5 djnz $1CFD 1D08: EB ex de,hl 1D09: 01 5E 43 ld bc,$435E 1D0C: 26 00 ld h,$00 1D0E: 09 add hl,bc 1D0F: 7E ld a,(hl) 1D10: EB ex de,hl 1D11: C9 ret 1D12: DD 21 22 1D ld ix,$1D22 1D16: ED 4B 85 08 ld bc,($0885) 1D1A: CD 22 1D call $1D22 1D1D: ED 43 85 08 ld ($0885),bc 1D21: C9 ret 1D22: 0A ld a,(bc) 1D23: 03 inc bc 1D24: 26 00 ld h,$00 1D26: 87 add a,a 1D27: 6F ld l,a 1D28: 11 31 1D ld de,$1D31 1D2B: 19 add hl,de 1D2C: 7E ld a,(hl) 1D2D: 23 inc hl 1D2E: 66 ld h,(hl) 1D2F: 6F ld l,a 1D30: E9 jp (hl) 1D31: 51 ld d,c 1D32: 1D dec e 1D33: 5C ld e,h 1D34: 1D dec e 1D35: 5D ld e,l 1D36: 1D dec e 1D37: 68 ld l,b 1D38: 1D dec e 1D39: 74 ld (hl),h 1D3A: 1D dec e 1D3B: 7E ld a,(hl) 1D3C: 1D dec e 1D3D: 8A adc a,d 1D3E: 1D dec e 1D3F: 96 sub (hl) 1D40: 1D dec e 1D41: A7 and a 1D42: 1D dec e 1D43: B1 or c 1D44: 1D dec e 1D45: BD cp l 1D46: 1D dec e 1D47: CB 1D rr l 1D49: E4 1D F4 call po,$F41D 1D4C: 1D dec e 1D4D: 09 add hl,bc 1D4E: 1E 1C ld e,$1C 1D50: 1E 0B ld e,$0B 1D52: 21 00 00 ld hl,$0000 1D55: 22 87 08 ld ($0887),hl 1D58: 22 89 08 ld ($0889),hl 1D5B: C9 ret 1D5C: C9 ret 1D5D: 0A ld a,(bc) 1D5E: 03 inc bc 1D5F: 6F ld l,a 1D60: 87 add a,a 1D61: 9F sbc a,a 1D62: 67 ld h,a 1D63: 09 add hl,bc 1D64: 44 ld b,h 1D65: 4D ld c,l 1D66: DD E9 jp (ix) 1D68: 0A ld a,(bc) 1D69: 03 inc bc 1D6A: 6F ld l,a 1D6B: 0A ld a,(bc) 1D6C: 03 inc bc 1D6D: 67 ld h,a 1D6E: 35 dec (hl) 1D6F: 20 EC jr nz,$1D5D 1D71: 03 inc bc 1D72: DD E9 jp (ix) 1D74: 0A ld a,(bc) 1D75: 03 inc bc 1D76: 6F ld l,a 1D77: 0A ld a,(bc) 1D78: 03 inc bc 1D79: 67 ld h,a 1D7A: 5E ld e,(hl) 1D7B: C3 8D 1D jp $1D8D 1D7E: 0A ld a,(bc) 1D7F: 03 inc bc 1D80: 6F ld l,a 1D81: 0A ld a,(bc) 1D82: 03 inc bc 1D83: 67 ld h,a 1D84: 5E ld e,(hl) 1D85: 23 inc hl 1D86: 56 ld d,(hl) 1D87: C3 9C 1D jp $1D9C 1D8A: 0A ld a,(bc) 1D8B: 03 inc bc 1D8C: 5F ld e,a 1D8D: 0A ld a,(bc) 1D8E: 03 inc bc 1D8F: 6F ld l,a 1D90: 0A ld a,(bc) 1D91: 03 inc bc 1D92: 67 ld h,a 1D93: 73 ld (hl),e 1D94: DD E9 jp (ix) 1D96: 0A ld a,(bc) 1D97: 03 inc bc 1D98: 5F ld e,a 1D99: 0A ld a,(bc) 1D9A: 03 inc bc 1D9B: 57 ld d,a 1D9C: 0A ld a,(bc) 1D9D: 03 inc bc 1D9E: 6F ld l,a 1D9F: 0A ld a,(bc) 1DA0: 03 inc bc 1DA1: 67 ld h,a 1DA2: 73 ld (hl),e 1DA3: 23 inc hl 1DA4: 72 ld (hl),d 1DA5: DD E9 jp (ix) 1DA7: 0A ld a,(bc) 1DA8: 03 inc bc 1DA9: 6F ld l,a 1DAA: 0A ld a,(bc) 1DAB: 03 inc bc 1DAC: 67 ld h,a 1DAD: 5E ld e,(hl) 1DAE: C3 C0 1D jp $1DC0 1DB1: 0A ld a,(bc) 1DB2: 03 inc bc 1DB3: 6F ld l,a 1DB4: 0A ld a,(bc) 1DB5: 03 inc bc 1DB6: 67 ld h,a 1DB7: 5E ld e,(hl) 1DB8: 23 inc hl 1DB9: 56 ld d,(hl) 1DBA: C3 D1 1D jp $1DD1 1DBD: 0A ld a,(bc) 1DBE: 03 inc bc 1DBF: 5F ld e,a 1DC0: 0A ld a,(bc) 1DC1: 03 inc bc 1DC2: 6F ld l,a 1DC3: 0A ld a,(bc) 1DC4: 03 inc bc 1DC5: 67 ld h,a 1DC6: 7E ld a,(hl) 1DC7: 83 add a,e 1DC8: 77 ld (hl),a 1DC9: DD E9 jp (ix) 1DCB: 0A ld a,(bc) 1DCC: 03 inc bc 1DCD: 5F ld e,a 1DCE: 0A ld a,(bc) 1DCF: 03 inc bc 1DD0: 57 ld d,a 1DD1: 0A ld a,(bc) 1DD2: 03 inc bc 1DD3: 6F ld l,a 1DD4: 0A ld a,(bc) 1DD5: 03 inc bc 1DD6: 67 ld h,a 1DD7: E5 push hl 1DD8: 7E ld a,(hl) 1DD9: 23 inc hl 1DDA: 66 ld h,(hl) 1DDB: 6F ld l,a 1DDC: 19 add hl,de 1DDD: EB ex de,hl 1DDE: E1 pop hl 1DDF: 73 ld (hl),e 1DE0: 23 inc hl 1DE1: 72 ld (hl),d 1DE2: DD E9 jp (ix) 1DE4: 0A ld a,(bc) 1DE5: 03 inc bc 1DE6: 5F ld e,a 1DE7: 0A ld a,(bc) 1DE8: 03 inc bc 1DE9: 6F ld l,a 1DEA: 0A ld a,(bc) 1DEB: 03 inc bc 1DEC: 67 ld h,a 1DED: CB 2E sra (hl) 1DEF: 1D dec e 1DF0: 20 FB jr nz,$1DED 1DF2: DD E9 jp (ix) 1DF4: 0A ld a,(bc) 1DF5: 03 inc bc 1DF6: 5F ld e,a 1DF7: 0A ld a,(bc) 1DF8: 03 inc bc 1DF9: 6F ld l,a 1DFA: 0A ld a,(bc) 1DFB: 03 inc bc 1DFC: 67 ld h,a 1DFD: 23 inc hl 1DFE: CB 2E sra (hl) 1E00: 2B dec hl 1E01: CB 1E rr (hl) 1E03: 23 inc hl 1E04: 1D dec e 1E05: 20 F7 jr nz,$1DFE 1E07: DD E9 jp (ix) 1E09: 0A ld a,(bc) 1E0A: 03 inc bc 1E0B: 5F ld e,a 1E0C: 0A ld a,(bc) 1E0D: 03 inc bc 1E0E: 6F ld l,a 1E0F: 0A ld a,(bc) 1E10: 03 inc bc 1E11: 67 ld h,a 1E12: 0A ld a,(bc) 1E13: 77 ld (hl),a 1E14: 23 inc hl 1E15: 03 inc bc 1E16: 1D dec e 1E17: C2 12 1E jp nz,$1E12 1E1A: DD E9 jp (ix) 1E1C: 0A ld a,(bc) 1E1D: 03 inc bc 1E1E: 87 add a,a 1E1F: C3 0B 1E jp $1E0B ; ; This adds an item to the linked list. ; ; Note: the CREATE_JOB label I have assigned is tentative and could change. ; Am fairly sure this is a job scheduling algorithm. ; Frenzy uses a different job system entirely. CREATE_JOB: 1E22: E1 pop hl ; pull return address from stack 1E23: D9 exx ; swap to alternate register set 1E24: 21 01 00 ld hl,$0001 1E27: E5 push hl ; reserve 4 bytes.. 1E28: E5 push hl ; ..on stack 1E29: 21 00 00 ld hl,$0000 1E2C: 39 add hl,sp ; HL = SP ; Check if this linked list already has a head. 1E2D: 3A 73 08 ld a,($0873) ; read MSB of contents of LINKED_LIST_PTR 1E30: B7 or a ; test if zero 1E31: 20 06 jr nz,$1E39 ; if non-zero then our linked list already has a head, goto $1E39 1E33: E5 push hl ; Linked list doesn't have a head, so make one. 1E34: 22 72 08 ld ($0872),hl ; set head of linked list 1E37: 18 1E jr $1E57 ; and exit ; If we get here, then the linked list already has a head. We want to make the item in HL the new head, ; and make the "old" head the next link of the new. 1E39: FD E5 push iy 1E3B: C1 pop bc ; Preserve IY in BC 1E3C: FD 2A 72 08 ld iy,($0872) ; get head of list by reading contents of LINKED_LIST_PTR 1E40: EB ex de,hl ; DE = new head 1E41: FD 66 FF ld h,(iy-$01) 1E44: FD 6E FE ld l,(iy-$02) 1E47: E5 push hl 1E48: F3 di 1E49: FD 72 FF ld (iy-$01),d 1E4C: FD 73 FE ld (iy-$02),e 1E4F: FB ei 1E50: ED 53 72 08 ld ($0872),de ; set new head of linked list 1E54: C5 push bc 1E55: FD E1 pop iy ; Restore IY from BC (see $1E3B) 1E57: D9 exx ; swap to normal register set 1E58: E9 jp (hl) ; jump to return address popped @ $1E22 ; ; Allocate 24 bytes on the stack and save the address of the reserved bytes in the head of the LINKED_LIST. ; ; IY = address of routine to jump to ; 1E59: 21 00 00 ld hl,$0000 1E5C: 39 add hl,sp ; HL = SP 1E5D: EB ex de,hl ; now DE = SP. 1E5E: 21 E8 FF ld hl, -24 1E61: 39 add hl,sp 1E62: F9 ld sp,hl ; allocate 24 bytes on stack 1E63: 2A 72 08 ld hl,($0872) ; get head of list by reading contents of LINKED_LIST_PTR 1E66: 23 inc hl 1E67: 23 inc hl 1E68: 73 ld (hl),e ; write DE into head 1E69: 23 inc hl 1E6A: 72 ld (hl),d 1E6B: FD E9 jp (iy) ; ; A = delay ; ACTIVATE_HEAD_JOB: 1E6D: FD 2A 72 08 ld iy,($0872) ; load IY with pointer to head of linked list 1E71: FD 77 01 ld (iy+$01),a ; update LINKED_LIST_ITEM.Delay 1E74: FD 36 00 82 ld (iy+$00),$82 ; update LINKED_LIST_ITEM.Flags STOP_JOB: 1E78: FD 2A 72 08 ld iy,($0872) 1E7C: 21 00 00 ld hl,$0000 1E7F: 39 add hl,sp ; HL = SP 1E80: 31 70 08 ld sp,$0870 1E83: FD 75 02 ld (iy+$02),l 1E86: FD 74 03 ld (iy+$03),h 1E89: 18 04 jr $1E8F ; ; ; 1E8B: FD 2A 72 08 ld iy,($0872) 1E8F: FD 66 FF ld h,(iy-$01) 1E92: FD 6E FE ld l,(iy-$02) 1E95: E5 push hl 1E96: FD E1 pop iy ; IY = HL 1E98: CB 46 bit 0,(hl) 1E9A: CA 8F 1E jp z,$1E8F 1E9D: FD 6E 02 ld l,(iy+$02) 1EA0: FD 66 03 ld h,(iy+$03) 1EA3: FD 22 72 08 ld ($0872),iy 1EA7: F9 ld sp,hl 1EA8: C9 ret ; ; ; See also: MAN in man.asm within Frenzy's source code. MAN: 1EA9: CD D4 1F call $1FD4 ; call MAN_INIT 1EAC: DD 36 00 16 ld (ix+$00),$16 ; set STATUS_BIT_COLOR + STATUS_BIT_WRITE + STATUS_BIT_WRITE 1EB0: CD 22 1E call $1E22 ; call CREATE_JOB 1EB3: C5 push bc 1EB4: FD 21 8B 1E ld iy,$1E8B 1EB8: CD 59 1E call $1E59 1EBB: C1 pop bc 1EBC: DD 2A 76 08 ld ix,($0876) ; Now IX = MAN_PTR, a pointer to the player's VECTOR structure. 1EC0: DD CB 00 7E bit 7,(ix+$00) ; test STATUS_BIT_HIT bit is set. If it is, player has been killed! 1EC4: C2 A7 1F jp nz,$1FA7 ; player's dead, goto PLAYER_DEAD 1EC7: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 1ECA: B7 or a ; check if zero. if zero, its a real game 1ECB: 28 14 jr z,$1EE1 ; its a real game, goto MOVE_PLAYER ; automatic demo mode ; The player's movements during the demo are encoded as an array of DURL Direction bits in ROM. 1ECD: 2A 6F 43 ld hl,($436F) ; Load HL with contents of DEMO_PTR 1ED0: 7E ld a,(hl) ; Read DURL Direction bits from HL 1ED1: 23 inc hl 1ED2: 22 6F 43 ld ($436F),hl ; Update DEMO_PTR 1ED5: CB 7F bit 7,a ; test bit 7. 1ED7: 28 16 jr z,$1EEF ; if bit 7 not set, A is a DURL bit, move player sprite accordingly 1ED9: CB BF res 7,a 1EDB: C5 push bc 1EDC: CD 6D 1E call $1E6D ; call ACTIVATE_HEAD_JOB 1EDF: 18 DA jr $1EBB ; ; Expects: ; C = Last direction player moved ; ; Remarks: ; See also S.STICK in control.asm within Frenzy's source code. MOVE_PLAYER: 1EE1: 3A 79 43 ld a,($4379) ; read FLIP 1EE4: B7 or a ; is upright cabinet? 1EE5: 28 04 jr z,$1EEB ; yes, goto $1EEB 1EE7: DB 4A in a,($4A) ; read player 2 controls 1EE9: 18 02 jr $1EED 1EEB: DB 48 in a,($48) ; read player 1 controls ; A = bits read from player control port. ; C = bits previously read from player control port. Used to determine if player changing direction. 1EED: EE 1F xor $1F 1EEF: CB 67 bit 4,a ; test fire button 1EF1: 57 ld d,a ; save direction bits in D 1EF2: 20 0D jr nz,$1F01 ; fire button pressed, goto TRY_FIRE 1EF4: E6 0F and $0F ; mask in left,right,up,down bits and discard rest 1EF6: B9 cp c ; compare to last direction player moved. 1EF7: C4 91 1F call nz,$1F91 ; if the player has changed direction, call CHANGE_PLAYER_DIRECTION 1EFA: C5 push bc 1EFB: CD 78 1E call $1E78 1EFE: C3 BB 1E jp $1EBB ; ; Fire button has been pressed. Can the player shoot? ; ; Expects: ; D = controller bits read from P1 or P2 control ; IY = ??? ; ; See also: TRY.F in Frenzy's MAN.ASM source. TRY_FIRE: 1F01: FD CB 00 4E bit 1,(iy+$00) 1F05: 20 F3 jr nz,$1EFA 1F07: AF xor a 1F08: FD 21 7B 43 ld iy,$437B ; load IY with address of PLAYER_BOLT_1 1F0C: FD B6 04 or (iy+$04) ; is this bolt in use? 1F0F: 28 0A jr z,$1F1B ; no, we can use it to shoot, goto FIRE 1F11: FD 21 83 43 ld iy,$4383 ; load IY with address of PLAYER_BOLT_2 1F15: AF xor a 1F16: FD B6 04 or (iy+$04) ; is this bolt in use? 1F19: 20 DF jr nz,$1EFA ; yes, so goto $1EFA. ; Attempt to fire a bolt. ; ; Expects: ; D= direction bits read from P1 or P2 controls ; IX = pointer to player's VECTOR structure ; IY = pointer to BOLT structure to use for player's bolt ; ; See also: FIRE contained within MAN.ASM in Frenzy's source FIRE: 1F1B: 7A ld a,d ; get joystick + fire button bits from D 1F1C: E6 0F and $0F ; preserve DURL direction bits, discard everything else 1F1E: CA FA 1E jp z,$1EFA ; if joystick in "neutral" position, don't shoot ; Fire a bolt 1F21: CD BD 33 call $33BD ; play bolt shooting sound 1F24: 4F ld c,a ; preserve DURL bits in A 1F25: 21 42 20 ld hl,$2042 ; load HL with address of D.TAB 1F28: 06 00 ld b,$00 1F2A: 50 ld d,b 1F2B: 09 add hl,bc ; now HL points to offset held in D.TAB 1F2C: 5E ld e,(hl) ; read offset from D.TAB 1F2D: 21 67 20 ld hl,$2067 ; load HL with address of SR.TAB 1F30: 19 add hl,de 1F31: 19 add hl,de 1F32: 19 add hl,de ; HL = HL + (offset in DE * 3) ; HL now is pointer to an entry in the SR.TAB table. ; First, make the player stand still to shoot (set his velocity in both axes to 0), ; then select the correct animation for direction player is shooting in 1F33: DD 36 06 00 ld (ix+$06),$00 ; reset VECTOR.V.X and.. 1F37: DD 36 08 00 ld (ix+$08),$00 ; ... reset VECTOR.V.Y - player must stand still while shooting 1F3B: 7E ld a,(hl) 1F3C: 23 inc hl 1F3D: F3 di 1F3E: DD 77 0A ld (ix+$0a),a ; set VECTOR.D.P.L 1F41: 7E ld a,(hl) 1F42: 23 inc hl 1F43: DD 77 0B ld (ix+$0b),a ; set VECTOR.D.P.H 1F46: FB ei 1F47: DD 36 0C 01 ld (ix+$0c),$01 ; set VECTOR.TIME ; wait a bit before spawning bolt 1F4B: 00 nop 1F4C: DD 7E 0C ld a,(ix+$0c) ; read VECTOR.TIME 1F4F: FE 02 cp $02 1F51: 20 F8 jr nz,$1F4B 1F53: 0E FF ld c,$FF 1F55: C5 push bc 1F56: 46 ld b,(hl) ; get X offset for bolt into B 1F57: 23 inc hl 1F58: 4E ld c,(hl) ; get Y offset for bolt into C 1F59: 23 inc hl 1F5A: 56 ld d,(hl) ; get DURL bits for bolt into D 1F5B: DD 7E 07 ld a,(ix+$07) ; read player's P.X (X pos) 1F5E: 80 add a,b ; add X offset for bolt 1F5F: 6F ld l,a ; L now = start X coord for bolt 1F60: DD 7E 09 ld a,(ix+$09) ; read player's P.Y (Y post) 1F63: 81 add a,c ; add Y offset for bolt 1F64: 67 ld h,a ; H now = start Y coord for bolt 1F65: FD 75 02 ld (iy+$02),l ; set BOLT.X 1F68: FD 74 03 ld (iy+$03),h ; set BOLT.Y 1F6B: FD 75 06 ld (iy+$06),l ; set BOLT.TailX 1F6E: FD 74 07 ld (iy+$07),h ; set BOLT.TailY 1F71: F3 di 1F72: FD 72 00 ld (iy+$00),d ; set BOLT.Direction 1F75: FD 36 01 00 ld (iy+$01),$00 ; set BOLT.Length 1F79: FD 72 04 ld (iy+$04),d ; set BOLT.LastDirection 1F7C: FD 36 05 08 ld (iy+$05),$08 ; set BOLT.MaxLength 1F80: FB ei 1F81: 3E 08 ld a,$08 ; delay before man is allowed to shoot again. 1F83: CD 6D 1E call $1E6D ; call ACTIVATE_HEAD_JOB 1F86: FD CB 00 CE set 1,(iy+$00) 1F8A: FD 36 01 0C ld (iy+$01),$0C 1F8E: C3 BB 1E jp $1EBB ; ; Change direction of player ; ; Expects: ; A = DURL bits read from P1 or P2 stick ; IX = pointer to VECTOR structure ; ; Remarks: ; See also: CHANGE within man.asm in Frenzy's source code. ; CHANGE_PLAYER_DIRECTION: 1F91: 4F ld c,a ; set C to "track" stick movement 1F92: E6 0F and $0F CDIR: 1F94: CD 3D 2B call $2B3D ; call SET_VELOCITY. Now DE = offset into P.TAB table 1F97: 21 53 20 ld hl,$2053 ; load HL with address of P.TAB 1F9A: 19 add hl,de ; HL now is pointer to pattern table for player's direction 1F9B: 7E ld a,(hl) ; 1F9C: 23 inc hl 1F9D: 66 ld h,(hl) 1F9E: F3 di 1F9F: DD 77 0A ld (ix+$0a),a 1FA2: DD 74 0B ld (ix+$0b),h 1FA5: FB ei 1FA6: C9 ret ; The player has been killed. ; ; Remarks: ; See also DEAD in man.asm within Frenzy's source code. PLAYER_DEAD: 1FA7: CD 39 34 call $3439 ; play sound of player being electrocuted 1FAA: 3E 10 ld a,$10 ; set direction bits 1FAC: CD 94 1F call $1F94 ; call CDIR 1FAF: DD CB 00 EE set 5,(ix+$00) 1FB3: CD 1F 2C call $2C1F ; call SAY_GOT_THE_HUMANOID_GOT_THE_INTRUDER 1FB6: 3E 2D ld a,$2D ; set timer for how long the frying lasts! 1FB8: CD 6D 1E call $1E6D ; call ACTIVATE_HEAD_JOB ; 1FBB: FD 7E 01 ld a,(iy+$01) 1FBE: B7 or a 1FBF: 28 05 jr z,$1FC6 1FC1: CD 78 1E call $1E78 1FC4: 18 F5 jr $1FBB 1FC6: 2A 76 08 ld hl,($0876) ; load HL with contents of MAN_PTR. Now HL = pointer to player's VECTOR 1FC9: 36 09 ld (hl),$09 ; set STATUS_BIT_ERASE + STATUS_BIT_BLANK flags in VECTOR.Status 1FCB: FD CB 00 86 res 0,(iy+$00) 1FCF: CD 78 1E call $1E78 1FD2: 18 FB jr $1FCF ; ; ; ; See also: M.INIT in man.asm within Frenzy's source code. ; MAN_INIT: 1FD4: FD E1 pop iy ; pop return address off stack into IY ; Allocate and zero 14 bytes on the stack for player's VECTOR 1FD6: 21 00 00 ld hl,$0000 1FD9: 06 07 ld b,$07 1FDB: E5 push hl 1FDC: 10 FD djnz $1FDB 1FDE: DD 21 00 00 ld ix,$0000 1FE2: DD 39 add ix,sp ; IX = SP 1FE4: E5 push hl 1FE5: DD 22 76 08 ld ($0876),ix ; set MAN_PTR ; Set player colour 1FE9: 3A 44 43 ld a,($4344) ; read CURRENT_PLAYER 1FEC: FE 01 cp $01 ; Is it player one's turn? 1FEE: 3E AA ld a,$AA ; Colour for player 1 1FF0: 28 02 jr z,$1FF4 ; It's player one's turn, goto $1FF4 1FF2: 3E DD ld a,$DD ; Colour for player 2 1FF4: 32 78 43 ld ($4378),a ; set PLAYER_COLOUR 1FF7: 2A 47 43 ld hl,($4347) ; get MAN_X into L and MAN_Y into H 1FFA: DD 75 07 ld (ix+$07),l ; set VECTOR.P.X 1FFD: DD 74 09 ld (ix+$09),h ; set VECTOR.P.Y 2000: AF xor a 2001: CD 91 1F call $1F91 ; call CHANGE_PLAYER_DIRECTION 2004: DD 36 0D 02 ld (ix+$0d),$02 ; set VECTOR.TPRIME 2008: DD 36 0C 01 ld (ix+$0c),$01 ; set VECTOR.TIME 200C: FD E9 jp (iy) ; jump to return address popped @ $1fd4 ; ; Allocate space on the stack for a robot's VECTOR ; 200E: E1 pop hl ; pop return address off stack 200F: D9 exx ; Allocate 14 bytes for robot's VECTOR 2010: 06 07 ld b,$07 2012: 11 00 00 ld de,$0000 2015: D5 push de 2016: 10 FD djnz $2015 2018: 21 00 00 ld hl,$0000 201B: 39 add hl,sp ; HL = SP 201C: EB ex de,hl 201D: 3A 71 08 ld a,($0871) 2020: B7 or a 2021: 20 07 jr nz,$202A 2023: D5 push de 2024: ED 53 70 08 ld ($0870),de 2028: 18 13 jr $203D 202A: DD 2A 70 08 ld ix,($0870) 202E: DD 66 FF ld h,(ix-$01) 2031: DD 6E FE ld l,(ix-$02) 2034: E5 push hl 2035: F3 di 2036: DD 72 FF ld (ix-$01),d 2039: DD 73 FE ld (ix-$02),e 203C: FB ei 203D: D5 push de 203E: DD E1 pop ix ; IX = DE 2040: D9 exx 2041: E9 jp (hl) ; ; Maps Direction (DURL) bits to offsets into other tables. ; ; The offsets are sometimes multiplied by another number before being used. ; ; As an example, let's look at how this table is used to calculate an offset into the robot shoot table S.TAB . ; Let's say we have DURL bits of 5, which is LEFT (1) + UP (4). ; ; The 5th entry (with a zero based index) of the D.TAB table is $0E (14 decimal). ; The logic at $28EC multiplies this value by 3 to give 42 decimal. ; 42 bytes into S.TAB @ $296E you have the entry for shooting UP + LEFT. ; ; Remarks: ; See also D.TAB within man.asm in Frenzy's source code. D.TAB: 2042: 00 ; no move 0C ; left 04 ; right 00 10 ; up 0E ; up,left 02 ; up,right 10 ; up default 08 ; down 0A ; down,left 06 ; down,right 08 ; down default 00 0C ; left default 04 ; right default 00 12 ; explode ; ; ; ; Remarks: ; See also P.TAB within man.asm in Frenzy's source code. P.TAB: 2053: 46 10 4B 10 4B 10 4B 10 4B 10 56 10 56 10 56 10 4B 10 B3 12 ; ; Player shoot table. ; ; Defines what animation the player's VECTOR should use when shooting, and deltas to add to the VECTOR's X,Y coordinates ; to compute starting X,Y coordinates for a BOLT. ; ; Each entry in this table requires 6 bytes. ; ; The format of an entry in the table is as follows: ; WORD PatternPtr - pointer to an pattern table for player sprite ; BYTE XDelta - Y Delta to add to player's X coordinate to compute bolt's initial X coordinate ; BYTE YDelta - Y Delta to add to player's Y coordinate to compute bolt's initial Y coordinate ; BYTE Direction - DURL bits representing the direction the bolt will move in DURL bits ; BYTE 0 - padding byte with no other use. ; ; Remarks: ; See also: SR.TAB within man.asm in Frenzy's source code. ; SR.TAB: ; No direction 2067: 46 10 ; pointer to pattern table 00 ; Bolt starting position X Delta (0 as can't shoot if joystick not pointing in a direction) 00 00 ; DURL bits (0 = No direction) 00 ; Player shooting UP + RIGHT 206D: 61 10 ; pointer to pattern table 07 ; Bolt X delta 01 ; Bolt Y delta 06 ; DURL bits (RIGHT + UP) 00 ; Player shooting RIGHT 2073: 66 10 07 03 02 00 ; Player shooting DOWN + RIGHT 2079: 6B 10 06 06 0A 00 ; Player shooting DOWN 207F: 70 10 06 07 08 00 ; Player shooting DOWN + LEFT 2085: 75 10 00 06 09 00 ; Player shooting LEFT 208B: 7A 10 00 03 01 00 ; Player shooting UP + LEFT 2091: 7F 10 00 00 05 00 ; Player shooting UP 2097: 84 10 07 02 04 00 209D: CD 4E 1A call $1A4E ; call CLEAR_SCREEN 20A0: CD 40 25 call $2540 20A3: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 20A6: B7 or a 20A7: 20 2E jr nz,$20D7 ; if demo mode, goto $20D7 20A9: CD D4 1F call $1FD4 20AC: 01 12 18 ld bc,$1812 20AF: 3A 76 43 ld a,($4376) ; read NUMBER_OF_PLAYERS 20B2: FE 02 cp $02 20B4: 28 02 jr z,$20B8 20B6: 06 08 ld b,$08 20B8: DD 71 00 ld (ix+$00),c 20BB: C5 push bc 20BC: DD E5 push ix 20BE: 3E 0A ld a,$0A 20C0: CD 6D 1E call $1E6D 20C3: DD E1 pop ix 20C5: C1 pop bc 20C6: 3E 1B ld a,$1B 20C8: A9 xor c 20C9: 4F ld c,a 20CA: 10 EC djnz $20B8 20CC: 21 00 00 ld hl,$0000 20CF: 22 76 08 ld ($0876),hl ; set MAN_PTR to NULL 20D2: 06 08 ld b,$08 20D4: D1 pop de 20D5: 10 FD djnz $20D4 20D7: FB ei 20D8: 3A 4A 43 ld a,($434A) 20DB: C6 60 add a,$60 20DD: 27 daa 20DE: 32 4A 43 ld ($434A),a 20E1: 3A 4C 43 ld a,($434C) 20E4: FE 01 cp $01 20E6: 28 04 jr z,$20EC 20E8: 3D dec a 20E9: 32 4C 43 ld ($434C),a 20EC: AF xor a 20ED: 32 71 43 ld ($4371),a ; set RCOUNT 20F0: FD 2A 72 08 ld iy,($0872) 20F4: FD 77 01 ld (iy+$01),a 20F7: 3A 4D 43 ld a,($434D) ; read RWAIT 20FA: FE 14 cp $14 20FC: 38 05 jr c,$2103 20FE: D6 0A sub $0A 2100: 32 4D 43 ld ($434D),a ; set RWAIT 2103: FD 21 17 21 ld iy,$2117 2107: 21 F0 FF ld hl,$FFF0 210A: 39 add hl,sp 210B: F9 ld sp,hl 210C: CD 59 1E call $1E59 210F: 21 10 00 ld hl,$0010 2112: 39 add hl,sp 2113: F9 ld sp,hl 2114: C3 57 21 jp $2157 2117: 3E 16 ld a,$16 2119: 32 00 43 ld ($4300),a 211C: 4F ld c,a 211D: 3A 4A 43 ld a,($434A) 2120: 47 ld b,a 2121: CD 78 26 call $2678 ; call RANDOM 2124: B8 cp b 2125: 38 1E jr c,$2145 2127: 21 A0 23 ld hl,$23A0 212A: 06 00 ld b,$00 212C: 09 add hl,bc 212D: 46 ld b,(hl) 212E: 23 inc hl 212F: 4E ld c,(hl) 2130: CD 78 26 call $2678 ; call RANDOM 2133: E6 1F and $1F 2135: 80 add a,b 2136: 47 ld b,a 2137: CD 78 26 call $2678 ; call RANDOM 213A: E6 1F and $1F 213C: 81 add a,c 213D: 4F ld c,a 213E: FD 21 45 21 ld iy,$2145 2142: C3 B8 23 jp $23B8 ; jump to ROBOT 2145: 3A 00 43 ld a,($4300) 2148: 3D dec a 2149: 3D dec a 214A: 32 00 43 ld ($4300),a 214D: 4F ld c,a 214E: 20 CD jr nz,$211D 2150: FD 21 A9 1E ld iy,$1EA9 2154: C3 8E 2A jp $2A8E 2157: DD 2A 76 08 ld ix,($0876) ; read MAN_PTR 215B: DD CB 00 56 bit 2,(ix+$00) 215F: C8 ret z 2160: DD 7E 09 ld a,(ix+$09) 2163: 32 48 43 ld ($4348),a 2166: 47 ld b,a 2167: DD 7E 07 ld a,(ix+$07) 216A: 32 47 43 ld ($4347),a ; set MAN_X 216D: DD CB 00 7E bit 7,(ix+$00) 2171: C2 8D 21 jp nz,$218D 2174: B7 or a 2175: F2 82 21 jp p,$2182 2178: FE FC cp $FC 217A: D2 AC 22 jp nc,$22AC 217D: FE F6 cp $F6 217F: D2 5D 22 jp nc,$225D 2182: 78 ld a,b 2183: FE 02 cp $02 2185: DA 20 22 jp c,$2220 2188: FE BE cp $BE 218A: D2 CF 21 jp nc,$21CF 218D: 3A 6D 43 ld a,($436D) ; read UPDATE flag 2190: B7 or a ; has score changed? 2191: 28 03 jr z,$2196 ; if not, goto $2196 2193: CD 14 23 call $2314 ; call SHOW_SCORE 2196: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 2199: B7 or a 219A: 28 07 jr z,$21A3 219C: CD 7B 19 call $197B 219F: CD 97 19 call $1997 21A2: C0 ret nz 21A3: FD 2A 72 08 ld iy,($0872) ; Load IY with contents of LINKED_LIST_PTR 21A7: FD CB 00 CE set 1,(iy+$00) 21AB: FD 7E 01 ld a,(iy+$01) 21AE: B7 or a 21AF: 20 18 jr nz,$21C9 21B1: FD 36 01 3B ld (iy+$01),$3B 21B5: 06 0C ld b,$0C 21B7: 21 D0 08 ld hl,$08D0 ; load HL with address of CMOS_TOTAL_SECS_OF_PLAY 21BA: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 21BD: B7 or a 21BE: 20 06 jr nz,$21C6 21C0: CD B3 2D call $2DB3 ; call INCREMENT_BY_1 21C3: CD 97 2B call $2B97 21C6: CD 78 26 call $2678 ; call RANDOM 21C9: CD 78 1E call $1E78 21CC: C3 57 21 jp $2157 21CF: 3E 06 ld a,$06 21D1: 32 48 43 ld ($4348),a 21D4: 21 46 43 ld hl,$4346 21D7: 34 inc (hl) 21D8: CD EB 22 call $22EB 21DB: 28 09 jr z,$21E6 21DD: 21 AD 5F ld hl,$5FAD 21E0: 11 DF 5F ld de,$5FDF 21E3: C3 3D 22 jp $223D ; ; Scroll room up ; ; Remarks: ; See also: function S.U in Frenzy's PLAY.ASM ; SCROLL_UP: 21E6: 21 2D 44 ld hl,$442D 21E9: 11 00 44 ld de,$4400 ; load HL with address of screen image RAM S.U: 21EC: E5 push hl 21ED: 3E 1B ld a,$1B 21EF: 21 00 01 ld hl,$0100 21F2: 19 add hl,de 21F3: 01 00 19 ld bc,$1900 21F6: D5 push de 21F7: ED B0 ldir ; remove junk left after scroll 21F9: D1 pop de 21FA: 01 00 01 ld bc,$0100 21FD: 2B dec hl 21FE: 36 00 ld (hl),$00 2200: 0D dec c 2201: C2 FD 21 jp nz,$21FD 2204: 10 F7 djnz $21FD 2206: 3D dec a 2207: 20 E6 jr nz,$21EF ; TODO: ID what this is doing 2209: CD 40 25 call $2540 220C: E1 pop hl 220D: 11 1A 00 ld de,$001A 2210: 0E 02 ld c,$02 2212: 06 06 ld b,$06 2214: 36 FF ld (hl),$FF 2216: 23 inc hl 2217: 10 FB djnz $2214 2219: 19 add hl,de 221A: 0D dec c 221B: 20 F5 jr nz,$2212 221D: C3 D7 20 jp $20D7 2220: 3E B9 ld a,$B9 2222: 32 48 43 ld ($4348),a ; set MAN_Y 2225: 21 46 43 ld hl,$4346 ; load HL with address of ROOM_Y 2228: 35 dec (hl) ; decrement Y coordinate within maze 2229: CD EB 22 call $22EB ; zero flag set if upright cabinet 222C: 28 09 jr z,$2237 ; if an upright cabinet, go to SCROLL_DOWN ; cocktail cabinet 222E: 21 2D 46 ld hl,$462D 2231: 11 00 46 ld de,$4600 2234: C3 EC 21 jp $21EC ; jump to S.U to scroll up ; ; Scroll room down ; ; Remarks: ; See also: function S.D in Frenzy's PLAY.ASM ; SCROLL_DOWN: 2237: 21 AD 5D ld hl,$5DAD 223A: 11 FF 5D ld de,$5DFF 223D: E5 push hl S.D: 223E: 3E 1A ld a,$1A 2240: 01 00 19 ld bc,$1900 2243: 21 00 FF ld hl,$FF00 2246: 19 add hl,de 2247: D5 push de 2248: ED B8 lddr ; execute scroll ; remove junk left after scroll 224A: D1 pop de 224B: 01 00 01 ld bc,$0100 224E: 23 inc hl 224F: 36 00 ld (hl),$00 2251: 0D dec c 2252: C2 4E 22 jp nz,$224E 2255: 10 F7 djnz $224E 2257: 3D dec a 2258: 20 E6 jr nz,$2240 225A: C3 09 22 jp $2209 225D: 3E 08 ld a,$08 225F: 32 47 43 ld ($4347),a ; set MAN_X 2262: 21 45 43 ld hl,$4345 ; load HL with address of ROOM_X 2265: 34 inc (hl) ; increment X coordinate within maze 2266: CD EB 22 call $22EB ; zero flag set if upright cabinet 2269: 28 09 jr z,$2274 ; if upright cabinet goto SCROLL_LEFT ; cocktail cabinet 226B: 21 1F 4F ld hl,$4F1F 226E: 11 E0 5F ld de,$5FE0 2271: C3 C9 22 jp $22C9 ; jump to S.R to scroll right ; ; Scroll room left ; ; Remarks: ; See also: S.L in PLAY.ASM within Frenzy's source code. ; SCROLL_LEFT: 2274: 21 00 4D ld hl,$4D00 2277: 11 00 44 ld de,$4400 ; load DE with address of screen image RAM S.L: 227A: E5 push hl 227B: 3E 20 ld a,$20 227D: 01 FF 19 ld bc,$19FF 2280: 21 01 00 ld hl,$0001 2283: 19 add hl,de 2284: D5 push de 2285: ED B0 ldir ; execute scroll ; remove junk left after scroll 2287: 06 D0 ld b,$D0 2289: 11 E1 FF ld de,$FFE1 228C: 36 00 ld (hl),$00 228E: 2B dec hl 228F: 36 00 ld (hl),$00 2291: 19 add hl,de 2292: 10 F8 djnz $228C 2294: D1 pop de 2295: 3D dec a 2296: 20 E5 jr nz,$227D 2298: 3E 06 ld a,$06 229A: F5 push af 229B: CD 40 25 call $2540 229E: F1 pop af 229F: E1 pop hl 22A0: 11 20 00 ld de,$0020 22A3: 06 40 ld b,$40 22A5: 77 ld (hl),a 22A6: 19 add hl,de 22A7: 10 FC djnz $22A5 22A9: C3 D7 20 jp $20D7 ; ; Player has exited left side of room ; ; Remarks: ; See also: OLEFT in PLAY.ASM within Frenzy's source code. ; 22AC: 3E E6 ld a,$E6 22AE: 32 47 43 ld ($4347),a ; set MAN_X 22B1: 21 45 43 ld hl,$4345 ; load HL with address of ROOM_X 22B4: 35 dec (hl) ; decrement X coordinate within maze 22B5: CD EB 22 call $22EB ; zero flag set if upright cabinet 22B8: 28 09 jr z,$22C3 ; jump to SCROLL_RIGHT if upright cabinet ; cocktail cabinet - need to scroll screen left 22BA: 21 00 4F ld hl,$4F00 22BD: 11 00 46 ld de,$4600 22C0: C3 7A 22 jp $227A ; jump to S.L to scroll left ; ; Scroll room right ; ; Remarks: ; See also: function S.R in PLAY.ASM within Frenzy's source code ; SCROLL_RIGHT: 22C3: 21 1F 4D ld hl,$4D1F 22C6: 11 00 5E ld de,$5E00 S.R: 22C9: E5 push hl 22CA: 3E 20 ld a,$20 22CC: 01 00 1A ld bc,$1A00 22CF: 21 FF FF ld hl,$FFFF 22D2: 19 add hl,de 22D3: D5 push de 22D4: ED B8 lddr ; execute scroll ; remove any garbage left after scroll 22D6: 11 1F 00 ld de,$001F 22D9: 36 00 ld (hl),$00 22DB: 23 inc hl 22DC: 36 00 ld (hl),$00 22DE: 19 add hl,de 22DF: 10 F8 djnz $22D9 22E1: D1 pop de 22E2: 3D dec a 22E3: 20 E7 jr nz,$22CC 22E5: 3E 60 ld a,$60 22E7: F5 push af 22E8: C3 9B 22 jp $229B ; ; TODO: Check if this is equivalent of TREST within Frenzy's PLAY.ASM ; ; Returns: ; Zero flag clear if screen should flip 22EB: CD E4 2B call $2BE4 ; call TRY_SPEAK_ON_PLAYER_LEAVING_ROOM 22EE: CD 4E 36 call $364E 22F1: FD E5 push iy 22F3: E1 pop hl 22F4: FD 74 FF ld (iy-$01),h 22F7: FD 75 FE ld (iy-$02),l 22FA: 21 00 00 ld hl,$0000 22FD: F3 di 22FE: 22 70 08 ld ($0870),hl ; set V.PTR to NULL 2301: 22 76 08 ld ($0876),hl ; set MAN_PTR to NULL 2304: AF xor a 2305: 21 7B 43 ld hl,$437B ; load HL with address of PLAYER_BOLTS 2308: 06 38 ld b,$38 230A: 77 ld (hl),a 230B: 23 inc hl 230C: 10 FC djnz $230A 230E: 3A 79 43 ld a,($4379) ; read FLIP 2311: B7 or a 2312: FB ei 2313: C9 ret ; ; Displays player one's score, and player two's if two player game. ; ; Remarks: ; See also: SHOWS in play.asm within Frenzy's source code. ; SHOW_SCORE: 2314: AF xor a 2315: 32 6D 43 ld ($436D),a ; clear UPDATE flag ; print player 1's score 2318: 11 00 D5 ld de,$D500 231B: 21 3E 43 ld hl,$433E ; load HL with address of P1_SCORE 231E: 06 06 ld b,$06 ; max number of digits in score 2320: CD 40 2A call $2A40 ; call PRINT_DIGITS ; is this a 2 player game? 2323: 3A 76 43 ld a,($4376) ; read NUMBER_OF_PLAYERS 2326: FE 02 cp $02 ; 2 players? 2328: C0 ret nz ; exit if not a 2 player game ; print player 2's score 2329: 11 B0 D5 ld de,$D5B0 232C: 21 41 43 ld hl,$4341 ; load HL with address of P2_SCORE 232F: 06 06 ld b,$06 ; max number of digits in score 2331: C3 40 2A jp $2A40 ; jump to PRINT_DIGITS ; ; Get a pointer to the current player's score ; ; Frenzy also has this routine; it is named "ScorePtr" in PLAY.ASM. ; GET_PLAYER_SCORE_PTR: 2334: 3A 44 43 ld a,($4344) ; read CURRENT_PLAYER 2337: FE 02 cp $02 ; is player 2 playing? 2339: 21 41 43 ld hl,$4341 ; load HL with address of P2_SCORE 233C: C8 ret z ; exit if player 2 playing 233D: 21 3E 43 ld hl,$433E ; otherwise, load HL with address of P1_SCORE 2340: C9 ret ; ; Update player's score. Pretty much same as ADDS within Play.ASM in Frenzy's source code. ; ; Expects: ; B = index of digit to update (where 0 = units, 1 = tens, 2=hundreds, 3=thousands and so on.) ; C = value to add to digit ; ; e.g. to add a score of 100 you would pass B = 2, C = 1. To add 200, you'd pass B = 2, C= 2. ; ; (Note: Frenzy's docs say "ADD C * 10 ^ B TO SCORE", but I think my explanation is more easily understood) ; UPDATE_SCORE: 2341: 3E FF ld a,$FF 2343: 32 6D 43 ld ($436D),a ; set UPDATE flag - player score needs to be redrawn ASAP. 2346: 1E 04 ld e,$04 2348: CD 34 23 call $2334 ; call GET_PLAYER_SCORE_PTR 234B: 23 inc hl 234C: 23 inc hl 234D: 23 inc hl ; bump HL to point to memory address just after last 2 digits of players score 234E: CB 38 srl b ; Divide By 2. If the index in B is an odd number, then carry will be set 2350: 08 ex af,af' ; switch to alternate register pair to preserve flags 2351: 04 inc b ; ensure B is at least 1 2352: 2B dec hl 2353: 1D dec e 2354: 10 FC djnz $2352 2356: 08 ex af,af' ; restore flags 2357: 30 08 jr nc,$2361 ; if carry is not set, then B on entry is even , goto $2361 ; B is an odd number. In this situation we need to add to the upper nibble of the score BCD byte, so we need to change our value ; parameter so that it effects the upper nibble. 2359: CB 21 sla c ; move lower nibble.. 235B: CB 21 sla c 235D: CB 21 sla c 235F: CB 21 sla c ; to upper nibble ; Now HL = pointer to BCD byte to update, C= BCD value to add to byte pointed to by HL 2361: 79 ld a,c ; get value into A 2362: 86 add a,(hl) ; Add to BCD digits in existing score 2363: 27 daa ; Ensure result is valid BCD, and set carry flag if add caused a carry 2364: 77 ld (hl),a ; and update BCD digits in existing score 2365: 30 08 jr nc,$236F ; if no carry occurred, we're done 2367: 2B dec hl ; otherwise, we need to carry over result to previous digit (going from 10s to hundreds to thousands etc if necessary.) 2368: 1D dec e 2369: 28 04 jr z,$236F 236B: 0E 01 ld c,$01 236D: 18 F2 jr $2361 ; Now check if we get a bonus life 236F: CD 34 23 call $2334 ; call GET_PLAYER_SCORE_PTR 2372: 44 ld b,h 2373: 4D ld c,l ; BC = pointer to player score 2374: 21 4F 43 ld hl,$434F ; load HL with address of XTRAMEN flag 2377: 11 49 43 ld de,$4349 ; load DE with address of DEATHS 237A: DB 61 in a,($61) ; read from F2 237C: CB 7F bit 7,a ; test for BONUS LIFE AT 10000 DIP settings 237E: 28 11 jr z,$2391 ; if not set, goto $2391 ; handle BONUS LIFE AT 10000 POINTS 2380: 0A ld a,(bc) ; read first two digits of score (the hundred thousands & ten thousands) 2381: B7 or a ; test if zero 2382: 28 0D jr z,$2391 ; if zero then score isn't at least 10000, goto $2391 2384: CB 4E bit 1,(hl) ; test if XTRAMEN flag has been set 2386: C0 ret nz ; exit if bonus life already awarded to player 2387: CB CE set 1,(hl) ; set XTRAMEN flag. No more bonus lives for you! 2389: EB ex de,hl ; Now HL = address of DEATHS 238A: 34 inc (hl) ; award an extra life 238B: CD 38 35 call $3538 238E: C3 9A 25 jp $259A ; refresh display to show extra life 2391: DB 61 in a,($61) ; read from F2 2393: CB 77 bit 6,a ; test for BONUS LIFE AT 5000 DIP setting 2395: C8 ret z ; exit if the player doesn't get a bonus life at 5000 points ; handle BONUS LIFE AT 5000 POINTS 2396: 03 inc bc ; bump BC to point to the thousands and hundreds digits of the score 2397: 0A ld a,(bc) 2398: FE 50 cp $50 ; is the thousands digit "5" ? 239A: D8 ret c ; exit if lower 239B: CB 46 bit 0,(hl) ; test if XTRAMEN flag has been set 239D: C0 ret nz ; exit if bonus life already awarded to player 239E: CB C6 set 0,(hl) ; set XTRAMEN flag 23A0: 18 E7 jr $2389 ; refresh display to show extra life 23A2: 0C inc c 23A3: 0C inc c 23A4: 40 ld b,b 23A5: 0C inc c 23A6: A0 and b 23A7: 0C inc c 23A8: CE 0C adc a,$0C 23AA: 40 ld b,b 23AB: 50 ld d,b 23AC: 70 ld (hl),b 23AD: 50 ld d,b 23AE: 9E sbc a,(hl) 23AF: 50 ld d,b 23B0: 0C inc c 23B1: 96 sub (hl) 23B2: 40 ld b,b 23B3: 96 sub (hl) 23B4: A0 and b 23B5: 96 sub (hl) 23B6: CE 96 adc a,$96 ; ; Creates a robot. ; ; See also: ROBOT within robot.asm in Frenzy's source code. ; ROBOT: 23B8: C5 push bc 23B9: D1 pop de ; DE = BC 23BA: 21 71 43 ld hl,$4371 ; load HL with address of RCOUNT 23BD: 34 inc (hl) ; increment RCOUNT to count number of robots in room 23BE: 7E ld a,(hl) ; copy RCOUNT .. 23BF: 32 72 43 ld ($4372),a ; .. to RSAVED so we remember how many robots room had for room clearance bonus ; Get a VECTOR for the robot, then initialise it 23C2: CD 0E 20 call $200E ; Allocate VECTOR for robot and store address in IX 23C5: DD 72 07 ld (ix+$07),d ; set VECTOR.P.X (X position) 23C8: DD 73 09 ld (ix+$09),e ; set VECTOR.P.Y (Y position) 23CB: AF xor a 23CC: CD 36 24 call $2436 ; call SETPAT 23CF: DD 36 0C 01 ld (ix+$0c),$01 ; set VECTOR.TIME 23D3: DD 36 00 06 ld (ix+$00),$06 ; set VECTOR.Status to STATUS_BIT_WRITE + STATUS_BIT_MOVE 23D7: CD 22 1E call $1E22 ; call CREATE_JOB ; 23DA: DD E5 push ix 23DC: CD 59 1E call $1E59 23DF: 3A 4D 43 ld a,($434D) ; read RWAIT 23E2: FE 1E cp $1E ; compare to minimum wait time (MinWait in Frenzy's code) 23E4: 30 02 jr nc,$23E8 ; if A>= RWAIT, goto $23E8 23E6: 3E 1E ld a,$1E ; clamp A to 30 decimal minimum ; A = now delay before robots can start shooting. Activate the robot job 23E8: CD 6D 1E call $1E6D ; call ACTIVATE_HEAD_JOB 23EB: DD E1 pop ix 23ED: 0E 00 ld c,$00 ; See also: SEEK within robot.asm in Frenzy's source code. SEEK: 23EF: FD 2A 76 08 ld iy,($0876) ; read contents of MAN_PTR 23F3: C5 push bc ; Delta X = player X coordinate - robot X coordinate 23F4: FD 7E 07 ld a,(iy+$07) ; read P.X of player VECTOR 23F7: DD 96 07 sub (ix+$07) ; subtract P.X of robot VECTOR 23FA: 57 ld d,a ; D = Delta X 23FB: 06 00 ld b,$00 ; if delta X == 0, that means the robot's X coordinate and player's X coordinate are the same. 23FD: 28 06 jr z,$2405 ; if player X == Robot X, goto $2405 ; if the subtraction caused a carry that means the player is to the left of the robot. 23FF: 06 01 ld b,$01 ; DURL bit for LEFT 2401: 38 02 jr c,$2405 ; player is to the right of the robot. 2403: 06 02 ld b,$02 ; DURL bit for RIGHT ; B now holds the horizontal DURL bits indicating if player is to the left or right. ; Delta Y = player Y coordinate - robot Y coordinate 2405: FD 7E 09 ld a,(iy+$09) ; read P.Y of player VECTOR 2408: C6 02 add a,$02 ; player is 2 pixels taller than robot, so compensate 240A: DD 96 09 sub (ix+$09) ; subtract P.Y of robot VECTOR 240D: 5F ld e,a ; E = Delta y ; D and E hold Delta X and Delta Y (the horizontal and vertical distances of the player from the robot). 240E: 0E 00 ld c,$00 ; if delta Y == 0, that means the robot's Y coordinate and player's Y coordinates are about the same. 2410: 28 06 jr z,$2418 ; if Player Y == Robot Y, goto $2418 2412: 0E 04 ld c,$04 ; DURL bit for UP 2414: 38 02 jr c,$2418 2416: 0E 08 ld c,$08 ; DURL bit for DOWN 2418: 78 ld a,b ; get horizontal DURL bits in B 2419: 81 add a,c ; and combine with vertical DURL bits in C 241A: F5 push af ; save DURL bits on stack 241B: 4F ld c,a ; load C with DURL bits as SHOOT routine needs it 241C: CD 7F 28 call $287F ; call SHOOT 241F: F1 pop af 2420: C1 pop bc 2421: CD 36 24 call $2436 ; call SETPAT 2424: DD E5 push ix 2426: C5 push bc 2427: CD 78 1E call $1E78 242A: C1 pop bc 242B: DD E1 pop ix 242D: DD CB 00 7E bit 7,(ix+$00) ; test STATUS_BIT_HIT in VECTOR.Status field 2431: CA EF 23 jp z,$23EF ; if bits not set, robot is still functional, goto $23EF 2434: 18 21 jr $2457 ; Robot's been hit! Goto BLAM! ; Set the sprite pattern table pointer for a robot's VECTOR. ; ; Expects: ; A = direction (DURL bits) of robot ; C = last direction (DURL bits) of robot ; IX = pointer to VECTOR structure for robot. ; ; Remarks: ; See also: SETPAT in robot.asm within Frenzy's source code. SETPAT: 2436: E6 0F and $0F 2438: C4 6E 1C call nz,$1C6E 243B: B9 cp c 243C: C8 ret z 243D: 4F ld c,a 243E: CD 3D 2B call $2B3D ; call SET_VELOCITY. Now DE = offset into a direction table. ; Set pointer to pattern table for robot on room start 2441: 21 2D 25 ld hl,$252D ; load HL with address of ROBOT_ANIMATION_TABLES 2444: 19 add hl,de 2445: 7E ld a,(hl) ; A = low byte of pointer to pattern table 2446: 23 inc hl 2447: 66 ld h,(hl) ; H = high byte of pointer to pattern table. 2448: F3 di 2449: DD 77 0A ld (ix+$0a),a ; set VECTOR.D.P.L 244C: DD 74 0B ld (ix+$0b),h ; set VECTOR.D.P.H 244F: FB ei ; Set robot speed. 2450: 3A 4C 43 ld a,($434C) ; read ROBOT_SPEED 2453: DD 77 0D ld (ix+$0d),a ; set VECTOR.TPRIME 2456: C9 ret ; ; Make a robot explode. ; ; Expects: ; IX = pointer to robot's VECTOR structure ; ; See also: BLAM contained within robot.asm in Frenzy's source code. BLAM: 2457: E5 push hl 2458: DD E5 push ix 245A: CD 8A 34 call $348A ; play sound of robot exploding 245D: E1 pop hl ; HL = IX 245E: 11 06 00 ld de,$0006 2461: 19 add hl,de ; now HL points to VECTOR.V.X (X velocity) 2462: F3 di 2463: 72 ld (hl),d ; set VECTOR.V.X to 0. 2464: 23 inc hl ; bump HL to point to VECTOR.P.X (X coordinate) 2465: 7E ld a,(hl) 2466: D6 04 sub $04 ; offset blast pattern 2468: 77 ld (hl),a 2469: 23 inc hl ; bump HL to point to VECTOR.V.Y (Y velocity) 246A: 72 ld (hl),d ; set VECTOR.V.Y to 0. As both V.X and V.Y are now 0, the robot has no velocity and won't move while it explodes. 246B: 23 inc hl 246C: 7E ld a,(hl) ; bump HL to point to VECTOR.P.Y (Y coordinate) 246D: D6 06 sub $06 ; offset for large blast 246F: 77 ld (hl),a 2470: 23 inc hl ; bump HL to point to VECTOR.D.P.L 2471: 01 3B 10 ld bc,$103B ; pointer to pattern table describing explosion sequence 2474: 71 ld (hl),c ; set VECTOR.D.P.L 2475: 23 inc hl ; bump HL to point to VECTOR.D.P.H 2476: 70 ld (hl),b ; set VECTOR.D.P.H 2477: FB ei 2478: 23 inc hl ; bump HL to point to VECTOR.TIME 2479: 36 01 ld (hl),$01 ; set VECTOR.TIME to 1 (kick off animation immediately) 247B: 23 inc hl ; bump HL to point to VECTOR.TPRIME 247C: 36 01 ld (hl),$01 ; set VECTOR.TPRIME 247E: DD E5 push ix 2480: 01 05 01 ld bc,$0105 ; 50 PTS 2483: CD 41 23 call $2341 ; call UPDATE_SCORE 2486: 21 4E 43 ld hl,$434E ; load HL with address of OTTO_TIME 2489: 34 inc (hl) ; delay otto's appearance slightly! 248A: 34 inc (hl) 248B: 21 71 43 ld hl,$4371 ; load HL with address of RCOUNT 248E: 35 dec (hl) ; decrement count 248F: 20 3A jr nz,$24CB ; if any robots are still alive, goto $24CB ; All the robots in the room have been destroyed. ; Award * 10 points 2491: 3A 72 43 ld a,($4372) ; read RSAVED 2494: F5 push af ; see SCLOP in Frenzy's source code. 2495: 01 01 01 ld bc,$0101 ; 10 PTS 2498: CD 41 23 call $2341 ; call UPDATE_SCORE 249B: F1 pop af 249C: 3D dec a ; reduce counter of robots 249D: 20 F5 jr nz,$2494 ; repeat until 10PTs awarded for each robot. ; And now display message on screen stating the bonus for clearing the room 249F: CD 7B 29 call $297B ; call PRINT_STRING_297B 24A2: 00 60 D5 24A5: 42 4F 4E 55 53 00 BONUS. 24AB: F5 push af 24AC: 3A 72 43 ld a,($4372) ; read RSAVED 24AF: C6 00 add a,$00 24B1: 27 daa 24B2: 0F rrca 24B3: 0F rrca 24B4: 0F rrca 24B5: 0F rrca 24B6: 6F ld l,a 24B7: E6 F0 and $F0 24B9: 67 ld h,a 24BA: 3E 0F ld a,$0F 24BC: A5 and l 24BD: 6F ld l,a 24BE: F1 pop af 24BF: 22 00 43 ld ($4300),hl 24C2: 08 ex af,af' 24C3: 21 00 43 ld hl,$4300 24C6: 06 04 ld b,$04 24C8: CD 4A 2A call $2A4A ; call SHOWO 24CB: 3E 1E ld a,$1E 24CD: CD 6D 1E call $1E6D 24D0: DD E1 pop ix 24D2: 21 08 12 ld hl,$1208 24D5: DD 7E 04 ld a,(ix+$04) 24D8: BD cp l 24D9: 20 06 jr nz,$24E1 24DB: DD 7E 05 ld a,(ix+$05) 24DE: BC cp h 24DF: 28 09 jr z,$24EA 24E1: DD E5 push ix 24E3: CD 78 1E call $1E78 24E6: DD E1 pop ix 24E8: 18 E8 jr $24D2 24EA: CD F7 24 call $24F7 24ED: 2A 72 08 ld hl,($0872) ; load HL with contents of LINKED_LIST_PTR 24F0: CB 86 res 0,(hl) 24F2: CD 78 1E call $1E78 24F5: 18 F6 jr $24ED 24F7: DD E5 push ix 24F9: C1 pop bc 24FA: 50 ld d,b 24FB: 59 ld e,c 24FC: EB ex de,hl 24FD: 2B dec hl 24FE: 56 ld d,(hl) 24FF: 2B dec hl 2500: 5E ld e,(hl) 2501: 78 ld a,b 2502: BA cp d 2503: 20 F7 jr nz,$24FC 2505: 79 ld a,c 2506: BB cp e 2507: 20 F3 jr nz,$24FC 2509: F3 di 250A: DD 7E FE ld a,(ix-$02) 250D: 77 ld (hl),a 250E: 23 inc hl 250F: DD 7E FF ld a,(ix-$01) 2512: 77 ld (hl),a 2513: 23 inc hl 2514: 22 70 08 ld ($0870),hl 2517: FB ei 2518: C9 ret ; Movement table ; ; This table specifies deltas to be added to X,Y coordinates. ; Each entry in the table is a pair of signed bytes. ; ; The first byte of each pair is the X Delta (XDelta) and the second byte ; is the Y Delta (YDelta) ; ; Remarks: ; See also: M.TAB within super.asm in Frenzy's source code. ; M.TAB: 2519: 00 00 ; No direction. Will not affect X,Y coordinates 01 FF ; Up right (XDelta = 1, YDelta =-1) 01 00 ; Right (XDelta = 1, YDelta =0) 01 01 ; Down Right (XDelta = 1, YDelta = 1) 00 01 ; Down (XDelta = 0, YDelta = 1) FF 01 ; Down Left (XDelta =-1, YDelta = 1) FF 00 ; Left (XDelta = -1, YDelta = 0) FF FF ; Up Left (XDelta =-1, YDelta = -1) 00 FF ; Up (XDelta =0, YDelta = -1) 00 00 ; Will not affect X,Y coordinates ; ; Pointers to pattern (sprite data) for the robots. ; ; See also: P.TAB within robot.asm in Frenzy's source code. ; ROBOT_ANIMATION_TABLES: 252D: 00 10 ; Pointer to robot Standing still pattern table 13 10 ; Pointer to Robot moving up & right pattern table 13 10 ; Pointer to Robot moving right pattern table 13 10 ; Pointer to Robot moving down & right pattern table 1C 10 ; Pointer to Robot moving down pattern table 27 10 ; Pointer to Robot moving down & left pattern table 27 10 ; Pointer to Robot moving left pattern table 27 10 ; Pointer to Robot moving up & left pattern table 30 10 ; Pointer to Robot moving up pattern table 253F: 41 ld b,c 2540: 2A 45 43 ld hl,($4345) 2543: 22 5C 43 ld ($435C),hl 2546: 3A 79 43 ld a,($4379) ; read FLIP 2549: B7 or a 254A: 20 05 jr nz,$2551 254C: 21 6A 5E ld hl,$5E6A 254F: 18 03 jr $2554 2551: 21 4A 44 ld hl,$444A 2554: 11 14 00 ld de,$0014 2557: AF xor a 2558: 0E 0C ld c,$0C 255A: 06 0C ld b,$0C 255C: 77 ld (hl),a 255D: 23 inc hl 255E: 10 FC djnz $255C 2560: 19 add hl,de 2561: 0D dec c 2562: 20 F6 jr nz,$255A 2564: 01 0F 00 ld bc,$000F 2567: 11 5E 43 ld de,$435E 256A: 21 8C 26 ld hl,$268C 256D: ED B0 ldir 256F: 21 08 00 ld hl,$0008 2572: CD D4 25 call $25D4 2575: 21 08 CC ld hl,$CC08 2578: CD D4 25 call $25D4 257B: 21 04 00 ld hl,$0004 257E: CD CA 25 call $25CA 2581: 21 F8 00 ld hl,$00F8 2584: CD CA 25 call $25CA 2587: DD 21 5E 43 ld ix,$435E 258B: 21 38 44 ld hl,$4438 258E: CD EB 25 call $25EB 2591: 21 38 88 ld hl,$8838 2594: CD EB 25 call $25EB 2597: CD 9F 36 call $369F ; Display number of lives ; First find out who's playing 259A: 3A 44 43 ld a,($4344) ; read CURRENT_PLAYER 259D: FE 02 cp $02 ; is it player 2 in control? 259F: 21 38 D5 ld hl,$D538 ; H = Y coordinate, L = X coordinate for player 1 lives 25A2: 20 02 jr nz,$25A6 ; not player 2 in control, goto $25A6 25A4: 2E E8 ld l,$E8 ; L = X coordinate for player 2 lives 25A6: 06 00 ld b,$00 ; magic image RAM control bits 25A8: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 25AB: EB ex de,hl ; now DE = magic image RAM address 25AC: 08 ex af,af' 25AD: 3A 49 43 ld a,($4349) ; read DEATHS 25B0: 47 ld b,a ; load B with count of player lives 25B1: 08 ex af,af' 25B2: 05 dec b 25B3: 28 0A jr z,$25BF ; Display B number of player life icons starting from magic image RAM address DE 25B5: C5 push bc 25B6: 0E 80 ld c,$80 ; ordinal for "life" character (looks like a stick man.) 25B8: CD DB 29 call $29DB ; call PRINT_CHAR 25BB: 13 inc de ; bump DE to point to next image ram address 25BC: C1 pop bc 25BD: 10 F6 djnz $25B5 ; repeat until all lives drawn. ; are we in demo mode? If so, print the number of credits inserted too 25BF: 3A 6E 43 ld a,($436E) ; read IS_DEMO_MODE 25C2: B7 or a ; test if in DEMO mode 25C3: C4 CD 18 call nz,$18CD ; we're in demo mode, so call PRINT_CREDITS 25C6: CD 14 23 call $2314 ; call SHOW_SCORE 25C9: C9 ret 25CA: CD 62 26 call $2662 25CD: 3E 40 ld a,$40 25CF: 84 add a,h 25D0: 67 ld h,a 25D1: C3 62 26 jp $2662 25D4: CD 4C 26 call $264C 25D7: CD 4C 26 call $264C 25DA: 3E 30 ld a,$30 25DC: 85 add a,l 25DD: 6F ld l,a 25DE: CD 4C 26 call $264C 25E1: C3 4C 26 jp $264C 25E4: 06 10 ld b,$10 25E6: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 25E9: EB ex de,hl 25EA: C9 ret 25EB: CD 78 26 call $2678 ; call RANDOM 25EE: E5 push hl 25EF: CD 78 26 call $2678 ; call RANDOM 25F2: 01 06 26 ld bc,$2606 25F5: C5 push bc 25F6: E6 03 and $03 25F8: CA 30 26 jp z,$2630 25FB: 3D dec a 25FC: CA 40 26 jp z,$2640 25FF: 3D dec a 2600: CA 14 26 jp z,$2614 2603: C3 20 26 jp $2620 2606: E1 pop hl 2607: DD 23 inc ix 2609: 3E 30 ld a,$30 260B: 85 add a,l 260C: 6F ld l,a 260D: FE DC cp $DC 260F: 38 DA jr c,$25EB 2611: DD 23 inc ix 2613: C9 ret 2614: CD 4C 26 call $264C 2617: DD CB 01 DE set 3,(ix+$01) 261B: DD CB 06 D6 set 2,(ix+$06) 261F: C9 ret 2620: 7D ld a,l 2621: D6 30 sub $30 2623: 6F ld l,a 2624: CD 4C 26 call $264C 2627: DD CB 00 DE set 3,(ix+$00) 262B: DD CB 05 D6 set 2,(ix+$05) 262F: C9 ret 2630: 7C ld a,h 2631: D6 44 sub $44 2633: 67 ld h,a 2634: CD 62 26 call $2662 2637: DD CB 00 CE set 1,(ix+$00) 263B: DD CB 01 C6 set 0,(ix+$01) 263F: C9 ret 2640: CD 62 26 call $2662 2643: DD CB 05 CE set 1,(ix+$05) 2647: DD CB 06 C6 set 0,(ix+$06) 264B: C9 ret 264C: 06 0C ld b,$0C 264E: C5 push bc 264F: E5 push hl 2650: CD E4 25 call $25E4 2653: 21 9B 26 ld hl,$269B 2656: CD 17 28 call $2817 ; call DRAW_SPRITE 2659: E1 pop hl 265A: C1 pop bc 265B: 3E 04 ld a,$04 265D: 85 add a,l 265E: 6F ld l,a 265F: 10 ED djnz $264E 2661: C9 ret 2662: 06 12 ld b,$12 2664: C5 push bc 2665: E5 push hl 2666: CD E4 25 call $25E4 2669: 21 9B 26 ld hl,$269B 266C: CD 17 28 call $2817 ; call DRAW_SPRITE 266F: E1 pop hl 2670: C1 pop bc 2671: 3E 04 ld a,$04 2673: 84 add a,h 2674: 67 ld h,a 2675: 10 ED djnz $2664 2677: C9 ret ; ; Generate a random number. ; ; Returns: A = random number ; ; See alsoL: RANDOM contained within demo.asm in Frenzy's source code. RANDOM: 2678: E5 push hl 2679: 2A 5C 43 ld hl,($435C) ; load HL with RNG_SEED 267C: 54 ld d,h 267D: 5D ld e,l 267E: 29 add hl,hl 267F: 19 add hl,de 2680: 29 add hl,hl 2681: 19 add hl,de 2682: 11 53 31 ld de,$3153 2685: 19 add hl,de 2686: 22 5C 43 ld ($435C),hl ; set RNG_SEED 2689: 7C ld a,h 268A: E1 pop hl 268B: C9 ret 268C: 05 dec b 268D: 04 inc b 268E: 04 inc b 268F: 04 inc b 2690: 06 01 ld b,$01 2692: 00 nop 2693: 00 nop 2694: 00 nop 2695: 02 ld (bc),a 2696: 09 add hl,bc 2697: 08 ex af,af' 2698: 08 ex af,af' 2699: 08 ex af,af' 269A: 0A ld a,(bc) 269B: 01 04 F0 ld bc,$F004 269E: F0 ret p 269F: F0 ret p 26A0: F0 ret p 26A1: 02 ld (bc),a 26A2: 04 inc b 26A3: FF rst $38 26A4: F0 ret p 26A5: FF rst $38 26A6: F0 ret p 26A7: FF rst $38 26A8: F0 ret p 26A9: FF rst $38 26AA: F0 ret p ; Interrupt routine. ; ; Remarks: ; See also: INT within init.asm in Frenzy's source code. 26AB: F3 di 26AC: ED 73 74 08 ld ($0874),sp ; set STACK_PTR 26B0: 31 40 08 ld sp,$0840 26B3: F5 push af 26B4: DB 4E in a,($4E) ; read middle/bottom screen status 26B6: 1F rra 26B7: 38 20 jr c,$26D9 26B9: E5 push hl 26BA: C5 push bc 26BB: 21 9F 08 ld hl,$089F 26BE: 7E ld a,(hl) 26BF: 23 inc hl 26C0: 46 ld b,(hl) 26C1: A8 xor b 26C2: 4F ld c,a 26C3: DB 49 in a,($49) ; read SYSTEM 26C5: 2F cpl 26C6: 77 ld (hl),a 26C7: 2B dec hl 26C8: 70 ld (hl),b 26C9: A1 and c 26CA: E6 E0 and $E0 26CC: 2B dec hl 26CD: 87 add a,a 26CE: 30 03 jr nc,$26D3 26D0: 34 inc (hl) 26D1: 18 F9 jr $26CC 26D3: 20 F7 jr nz,$26CC 26D5: C1 pop bc 26D6: E1 pop hl 26D7: 18 43 jr $271C ; ; ; Remarks: ; See also: BS in init.asm within Frenzy's source code. ; BOTTOM_OF_SCREEN_INTERRUPT: 26D9: FD E5 push iy 26DB: DD E5 push ix 26DD: E5 push hl 26DE: D5 push de 26DF: C5 push bc 26E0: 08 ex af,af' 26E1: F5 push af 26E2: 2A 70 08 ld hl,($0870) ; read V.PTR 26E5: E5 push hl ; Erase the player's sprite from the screen 26E6: 2A 76 08 ld hl,($0876) ; load HL with contents of MAN_PTR 26E9: CD 2D 27 call $272D ; call ERASE_PATTERN 26EC: CD 19 37 call $3719 ; call UNCOLOUR_MAN 26EF: E1 pop hl 26F0: E5 push hl 26F1: CD 2D 27 call $272D ; call ERASE_PATTERN 26F4: CD F3 14 call $14F3 ; call HANDLE_PLAYER_BOLTS ; Update players position on screen 26F7: 2A 76 08 ld hl,($0876) ; load HL with contents of MAN_PTR 26FA: CD A9 27 call $27A9 ; call MOVE_ANIMATE_VECTOR ; 26FD: E1 pop hl 26FE: CD A9 27 call $27A9 ; call MOVE_ANIMATE_VECTOR 2701: 2A 70 08 ld hl,($0870) ; read V.PTR 2704: 7C ld a,h 2705: B5 or l 2706: 28 08 jr z,$2710 2708: 2B dec hl 2709: 56 ld d,(hl) 270A: 2B dec hl 270B: 5E ld e,(hl) 270C: ED 53 70 08 ld ($0870),de ; set V.PTR 2710: CD F5 27 call $27F5 2713: F1 pop af 2714: 08 ex af,af' 2715: C1 pop bc 2716: D1 pop de 2717: E1 pop hl 2718: DD E1 pop ix 271A: FD E1 pop iy 271C: 3E 01 ld a,$01 271E: D3 4F out ($4F),a ; turn on interrupts 2720: 3E 37 ld a,$37 2722: ED 47 ld i,a ; set interrupt flags 2724: ED 5E im 2 2726: F1 pop af 2727: ED 7B 74 08 ld sp,($0874) ; restore SP from STACK_PTR 272B: FB ei 272C: C9 ret ; Expects: ; HL = pointer to VECTOR structure ; ; Remarks: ; See also: SECT1 in Frenzy's INIT.ASM source. ERASE_PATTERN: 272D: 22 70 08 ld ($0870),hl 2730: E5 push hl 2731: FD E1 pop iy ; IY = HL 2733: CB 46 bit 0,(hl) ; test ERASE bit in VECTOR.Status 2735: CA 4D 27 jp z,$274D ; if we're not erasing, we must be writing, goto WRITE_PATTERN 2738: CB 86 res 0,(hl) ; clear ERASE bit so its not done twice 273A: 23 inc hl ; bump HL to point to VECTOR.Magic 273B: 7E ld a,(hl) ; read VECTOR.Magic 273C: D3 4B out ($4B),a ; write to magicram_control_w 273E: 23 inc hl ; 273F: 5E ld e,(hl) ; read VECTOR.O.A.L 2740: 23 inc hl 2741: 56 ld d,(hl) ; read VECTOR.O.A.H 2742: 23 inc hl 2743: 7E ld a,(hl) ; read VECTOR.O.P.L 2744: 23 inc hl 2745: 66 ld h,(hl) ; read VECTOR.O.P.H 2746: 6F ld l,a ; HL now = pointer to sprite width, height, pattern data ; DE = pointer to magic image RAM 2747: CD 17 28 call $2817 ; call DRAW_SPRITE ; Restore pointer to VECTOR structure we preserved @ $272D 274A: 2A 70 08 ld hl,($0870) ; HL = pointer to VECTOR structure ; IY = same as HL ; ; Remarks: ; See also: SECT2 in Frenzy's INIT.ASM source. WRITE_PATTERN: 274D: CB 4E bit 1,(hl) ; test WRITE bit in VECTOR.Status 274F: C8 ret z 2750: CB 8E res 1,(hl) ; clear WRITE bit 2752: 11 07 00 ld de,$0007 2755: 19 add hl,de ; bump HL to point to VECTOR.P.X 2756: 5E ld e,(hl) ; read VECTOR.P.X 2757: 23 inc hl 2758: 23 inc hl ; bump HL to point to VECTOR.P.Y 2759: 56 ld d,(hl) ; read VECTOR.P.Y 275A: 23 inc hl 275B: 06 90 ld b,$90 ; XOR write magic control byte 275D: EB ex de,hl ; Now H = VECTOR.Y, L = VECTOR.X 275E: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS ; now A = magic RAM control byte, and HL = magic RAM address 2761: FD 77 01 ld (iy+$01),a ; write to VECTOR.Magic 2764: EB ex de,hl ; now DE = magic RAM address and HL = pointer to VECTOR.D.P.L 2765: 7E ld a,(hl) ; read VECTOR.D.P.L 2766: 23 inc hl 2767: 66 ld h,(hl) ; read VECTOR.D.P.H 2768: 6F ld l,a 2769: 7E ld a,(hl) 276A: 23 inc hl 276B: 6E ld l,(hl) 276C: 67 ld h,a 276D: 7E ld a,(hl) 276E: CB 7F bit 7,a 2770: 28 19 jr z,$278B 2772: 23 inc hl 2773: E6 7F and $7F 2775: 47 ld b,a 2776: 7E ld a,(hl) 2777: 23 inc hl 2778: 4F ld c,a 2779: EB ex de,hl 277A: 3A 79 43 ld a,($4379) ; read FLIP 277D: B7 or a 277E: CA 86 27 jp z,$2786 ; cocktail cabinet 2781: ED 42 sbc hl,bc 2783: C3 8A 27 jp $278A ; standard cabinet 2786: 09 add hl,bc 2787: C3 8A 27 jp $278A 278A: EB ex de,hl ; HL = pointer to sprite pattern data , DE = pointer to magic image RAM 278B: FD 75 04 ld (iy+$04),l ; set VECTOR.O.P.L 278E: FD 74 05 ld (iy+$05),h ; set VECTOR.O.P.H 2791: FD 73 02 ld (iy+$02),e ; set VECTOR.O.A.L 2794: FD 72 03 ld (iy+$03),d ; set VECTOR.O.A.H 2797: CD 17 28 call $2817 ; call DRAW_SPRITE 279A: 2A 70 08 ld hl,($0870) ; get pointer to next VECTOR to process from V.PTR 279D: DB 4E in a,($4E) ; read middle/bottom screen status 279F: CB 7F bit 7,a 27A1: C8 ret z 27A2: CB FE set 7,(hl) ; set INEPT bit 27A4: FD CB FA C6 set 0,(iy-$06) 27A8: C9 ret ; ; Move and animate a VECTOR, such as player or robot (including Otto) ; ; Expects: ; HL = pointer to VECTOR structure ; ; See also: SECT3 in init.asm within Frenzy's source code. MOVE_ANIMATE_VECTOR: 27A9: 22 70 08 ld ($0870),hl ; set V.PTR to point to next VECTOR structure 27AC: CB 56 bit 2,(hl) ; test if MOVE bit is set in VECTOR.Status 27AE: C8 ret z ; exit if bit not set 27AF: E5 push hl 27B0: FD E1 pop iy ; IY is now a pointer to the VECTOR structure 27B2: 11 0C 00 ld de,$000C ; offset of VECTOR.TIME field 27B5: 19 add hl,de ; point HL to VECTOR.TIME field ; VECTOR.TIME is used to control how fast the VECTOR moves on screen. ; This VECTOR can only move when VECTOR.TIME counts down to zero. 27B6: 35 dec (hl) ; decrement VECTOR.TIME timer 27B7: C0 ret nz ; exit if timer is not zero ; When VECTOR.TIME reaches zero, reload it with VECTOR.TPRIME. 27B8: 23 inc hl ; point HL to VECTOR.TPRIME field 27B9: 7E ld a,(hl) ; read value of TPRIME 27BA: 2B dec hl ; point HL to VECTOR.TIME field 27BB: 77 ld (hl),a ; set TIME field from TPRIME 27BC: 11 FA FF ld de, -6 ; VECTOR.TIME has counted down to zero and the object can move. ; Add velocity deltas VECTOR.V.X and VECTOR.V.Y to VECTOR.P.X and VECTOR.P.Y coordinates ; This changes the screen position of the VECTOR. 27BF: 19 add hl,de ; now HL points to VECTOR.V.X 27C0: 7E ld a,(hl) ; read VECTOR.V.X 27C1: 23 inc hl ; bump HL to point to VECTOR.P.X 27C2: 86 add a,(hl) ; 27C3: 77 ld (hl),a ; VECTOR.P.X += VECTOR.V.X 27C4: 23 inc hl ; bump HL to point to VECTOR.V.Y 27C5: 7E ld a,(hl) ; read VECTOR.V.Y 27C6: 23 inc hl ; bump HL to point to VECTOR.P.Y 27C7: 86 add a,(hl) ; 27C8: 77 ld (hl),a ; VECTOR.P.Y += VECTOR.V.Y ; update pattern (animate) 27C9: 23 inc hl ; bump HL to point to VECTOR.D.P.L 27CA: 5E ld e,(hl) 27CB: 23 inc hl ; bump HL to point to VECTOR.D.P.H 27CC: 56 ld d,(hl) 27CD: 13 inc de 27CE: 13 inc de 27CF: EB ex de,hl ; When we encounter a zero byte this is the end of the pattern table. 27D0: 7E ld a,(hl) 27D1: B7 or a 27D2: C2 DA 27 jp nz,$27DA ; We've reached the end of the pattern table. 27D5: 23 inc hl 27D6: 7E ld a,(hl) 27D7: 23 inc hl 27D8: 66 ld h,(hl) 27D9: 6F ld l,a 27DA: EB ex de,hl 27DB: 72 ld (hl),d 27DC: 2B dec hl 27DD: 73 ld (hl),e 27DE: 3E 1B ld a,$1B 27E0: FD B6 00 or (iy+$00) 27E3: FD 77 00 ld (iy+$00),a 27E6: FD CB 00 6E bit 5,(iy+$00) 27EA: C8 ret z 27EB: 3A 78 43 ld a,($4378) ; read PLAYER_COLOUR 27EE: 07 rlca 27EF: EE 11 xor $11 27F1: 32 78 43 ld ($4378),a ; set PLAYER_COLOUR 27F4: C9 ret ; ; ; ; ; 27F5: 2A 72 08 ld hl,($0872) ; load HL with contents of LINKED_LIST_PTR 27F8: 7C ld a,h 27F9: B5 or l 27FA: C8 ret z ; return if HL is NULL 27FB: 54 ld d,h 27FC: 5D ld e,l 27FD: CB 4E bit 1,(hl) 27FF: 28 09 jr z,$280A 2801: 23 inc hl 2802: 35 dec (hl) 2803: 2B dec hl 2804: 20 04 jr nz,$280A 2806: CB 8E res 1,(hl) 2808: CB C6 set 0,(hl) 280A: 2B dec hl 280B: 7E ld a,(hl) 280C: 2B dec hl 280D: 6E ld l,(hl) 280E: 67 ld h,a 280F: BA cp d 2810: 20 EB jr nz,$27FD 2812: 7D ld a,l 2813: BB cp e 2814: 20 E7 jr nz,$27FD 2816: C9 ret ; ; Draw sprite either 1 or 2 bytes wide (1 bit per pixel, so max sprite width = 16 pixels) ; ; Expects: ; HL = pointer to sprite width, height, pattern data ; DE = pointer to magic image RAM ; First byte: width in bytes. 1 bit per pixel. ; Second byte: height in bytes ; ; See also: PLOT in init.asm within Frenzy's source code. DRAW_SPRITE: 2817: 06 00 ld b,$00 2819: 7E ld a,(hl) ; read width of sprite 281A: 23 inc hl ; bump HL to point to height 281B: 3D dec a 281C: CA 53 28 jp z,$2853 ; if width == 1 byte, goto DRAW_SPRITE_1_BYTE_WIDE ; Sprite is now presumed to be 2 bytes wide 281F: 3A 79 43 ld a,($4379) ; read FLIP 2822: B7 or a ; set zero flag if upright cabinet 2823: 7E ld a,(hl) ; read height of sprite 2824: 23 inc hl ; bump HL to point to first byte of sprite pattern data 2825: C2 3D 28 jp nz,$283D ; if cocktail cabinet, goto $283D ; upright cabinet 2828: 01 1E 00 ld bc,$001E ; $1E (30 decimal) = number of bytes to add to get to next row of image RAM after writing 2 bytes 282B: EB ex de,hl ; now DE = pointer to pattern data, HL = pointer to magic RAM 282C: 08 ex af,af' 282D: 1A ld a,(de) ; read pattern data 282E: 13 inc de ; bump DE to next byte of pattern data 282F: 77 ld (hl),a ; write pattern data to magic image RAM 2830: 23 inc hl ; bump HL to next image RAM address 2831: 1A ld a,(de) ; read pattern data 2832: 13 inc de ; bump DE to next byte of pattern data 2833: 77 ld (hl),a ; write pattern data to magic image RAM 2834: 23 inc hl ; bump HL to next image RAM address 2835: 70 ld (hl),b ; write 0 to image RAM (Frenzys docs says "flush shifter") 2836: 08 ex af,af' ; now A is number of rows left in sprite left to draw 2837: 09 add hl,bc ; adjust HL so that it points to the next row down in image RAM 2838: 3D dec a ; decrement count of rows of sprite left to draw 2839: C2 2C 28 jp nz,$282C ; repeat until all rows done 283C: C9 ret ; cocktail cabinet 283D: 01 E2 FF ld bc,$FFE2 2840: EB ex de,hl 2841: 08 ex af,af' 2842: 1A ld a,(de) 2843: 13 inc de 2844: 77 ld (hl),a 2845: 2B dec hl 2846: 1A ld a,(de) 2847: 13 inc de 2848: 77 ld (hl),a 2849: 2B dec hl 284A: 36 00 ld (hl),$00 284C: 08 ex af,af' 284D: 09 add hl,bc 284E: 3D dec a 284F: C2 41 28 jp nz,$2841 2852: C9 ret ; ; Draw 1 byte wide sprite. ; ; Expects: ; HL = pointer to byte specifying sprite height followed by pattern data ; DE = pointer to magic image RAM ; ; See also: X1PLOT in init.asm within Frenzy's source code DRAW_SPRITE_1_BYTE_WIDE: 2853: 3A 79 43 ld a,($4379) ; read FLIP 2856: B7 or a ; if upright cabinet, zero flag will be set 2857: 7E ld a,(hl) ; read height 2858: 23 inc hl 2859: C2 6D 28 jp nz,$286D ; if cocktail cabinet, goto $286D ; upright mode 285C: 01 1F 00 ld bc,$001F ; $1F (31 decimal) = number of bytes to add to get to next row of image RAM after writing a single byte 285F: EB ex de,hl ; now DE = pointer to pattern data, HL = pointer to magic RAM 2860: 08 ex af,af' 2861: 1A ld a,(de) ; read pattern data 2862: 13 inc de ; bump DE to next byte of pattern data 2863: 77 ld (hl),a ; write pattern data to magic image RAM 2864: 23 inc hl ; bump HL to next image RAM address 2865: 70 ld (hl),b ; write 0 to image RAM (Frenzys docs says "flush shifter") 2866: 08 ex af,af' ; now A is number of rows left in sprite left to draw 2867: 09 add hl,bc ; adjust HL so that it points to the next row down in image RAM 2868: 3D dec a ; decrement count of rows of sprite left to draw 2869: C2 60 28 jp nz,$2860 ; repeat until all rows done 286C: C9 ret ; cocktail mode - see XF1PLT in init.asm within Frenzy's source code 286D: 01 E1 FF ld bc,$FFE1 2870: EB ex de,hl 2871: 08 ex af,af' 2872: 1A ld a,(de) 2873: 13 inc de 2874: 77 ld (hl),a 2875: 2B dec hl 2876: 36 00 ld (hl),$00 2878: 08 ex af,af' 2879: 09 add hl,bc 287A: 3D dec a 287B: C2 71 28 jp nz,$2871 287E: C9 ret ; ; Check if a robot can shoot. ; ; Expects: ; ; C = DURL bits representing direction robot should shoot ; D = Delta X (player's X coordinate subtracted from robot's X coordinate) ; E = Delta Y (player's Y coordinate subtracted from robot's X coordinate) ; IX = pointer to robot's VECTOR structure ; ; ; See also: ; See $23EF for code that calculates deltas. ; SHOOT in shoot.asm within Frenzy's source code. ; SHOOT: 287F: 2A 72 08 ld hl,($0872) ; Load HL with contents of LINKED_LIST_PTR 2882: 23 inc hl 2883: 7E ld a,(hl) 2884: B7 or a 2885: C0 ret nz 2886: C5 push bc 2887: D5 push de ; save X,Y deltas on stack 2888: 11 08 00 ld de,$0008 ; sizeof(BOLT) 288B: 21 8F 43 ld hl,$438F ; load HL with address of ROBOT_BOLTS 288E: 3A 4B 43 ld a,($434B) ; read RBOLTS to check max allowed robot bolts on screen 2891: B7 or a ; check if zero (meaning, robots can't fire) 2892: 28 08 jr z,$289C ; if zero, just exit 2894: 47 ld b,a ; load B with RBOLTS to process 2895: 7E ld a,(hl) ; read BOLT.Direction DURL bits 2896: B7 or a ; if no bits set, then bolt hasn't been fired 2897: 28 06 jr z,$289F 2899: 19 add hl,de 289A: 10 F9 djnz $2895 289C: D1 pop de ; rest 289D: C1 pop bc 289E: C9 ret ; HL = pointer to a BOLT structure 289F: D1 pop de 28A0: C1 pop bc 28A1: 2B dec hl 28A2: 2B dec hl 28A3: 2B dec hl 28A4: 2B dec hl ; Quick Check if the robot should fire horizontally OR vertically (but not diagonally) ; is the X Delta of player and robot between -2 and 5? 28A5: 7A ld a,d ; load A with X Delta 28A6: FE FE cp -2 28A8: D2 D8 28 jp nc,$28D8 ; make shot go vertical 28AB: FE 06 cp $06 28AD: 38 29 jr c,$28D8 ; make shot go vertical ; is the Y Delta of player and robot between -4 and 6? 28AF: 7B ld a,e ; load A with Y Delta 28B0: FE FC cp -4 28B2: 30 1E jr nc,$28D2 ; make shot go horizontal 28B4: FE 07 cp $07 28B6: 38 1A jr c,$28D2 ; make shot go horizontal ; ; OK, now check if the robot should fire diagonally. ; ; First ensure that D (X Delta) and E (Y Delta) are positive integers. ; Skip to $28C8 if you just want to see the calculation. 28B8: 7A ld a,d ; load A with X Delta 28B9: CB 41 bit 0,c ; test LEFT DURL bit 28BB: 28 03 jr z,$28C0 ; if not set, goto $28C0 ; The [shoot] LEFT DURL bit is set in C, meaning the player is to the left of the robot. ; This means the Player X [coordinate] is < Robot X [coordinate]. ; Given that delta X is the product of (Player X - Robot X) (see $23F4) then Delta X will be a negative number. ; We need to convert it to its absolute value. 28BD: ED 44 neg ; Convert X Delta to a positive number 28BF: 57 ld d,a 28C0: 7B ld a,e ; load A with Y Delta 28C1: CB 51 bit 2,c ; test UP DURL bit 28C3: 28 03 jr z,$28C8 ; if not set, goto $28C0 ; The [shoot] UP DURL bit is set in C, meaning the player is standing above the robot. ; This means the Player Y [coordinate] is < Robot Y [coordinate]. ; Given that delta Y is the product of (Player Y - Robot Y) (see $2405) then Delta Y will be a negative number. ; We need to convert it to its absolute value. 28C5: ED 44 neg ; Convert Y Delta to a positive number 28C7: 5F ld e,a ; C = DURL Direction bits indicating what direction robot will shoot ; D = absolute value of X Delta ; E = absolute value of Y Delta ; A = absolute value of Y Delta 28C8: 92 sub d ; A = Y Delta - X Delta 28C9: FE F6 cp $F6 28CB: 30 11 jr nc,$28DE 28CD: FE 06 cp $06 28CF: D0 ret nc 28D0: 18 0C jr $28DE ; Make shot go horizontal 28D2: 79 ld a,c 28D3: E6 03 and $03 ; Mask in LEFT, RIGHT DURL bits 28D5: 4F ld c,a 28D6: 18 06 jr $28DE ; Make shot go vertical 28D8: 79 ld a,c 28D9: E6 0C and $0C ; Mask in UP, DOWN DURL bits 28DB: 4F ld c,a 28DC: 18 00 jr $28DE ; C = DURL bits for robot's bolt 28DE: 06 00 ld b,$00 ; zero B so that BC = index into D.TAB table 28E0: E5 push hl 28E1: CD E7 34 call $34E7 ; call SRFIRE# to make robot shoot noise 28E4: 21 42 20 ld hl,$2042 ; load HL with address of D.TAB table 28E7: 09 add hl,bc ; now HL = pointer to offset in D.TAB table 28E8: 4E ld c,(hl) ; now BC = offset read from D.TAB table 28E9: 21 44 29 ld hl,$2944 ; load HL with address of S.TAB table 28EC: 09 add hl,bc ; HL = HL + (BC * 3) 28ED: 09 add hl,bc 28EE: 09 add hl,bc ; Set the robot's horizontal and vertical velocity to zero, to make the robot stand still before it shoots. ; If you didn't do this, the robot could walk into the bolt it's just fired and blow itself up.... 28EF: DD 70 06 ld (ix+$06),b ; set VECTOR.V.X velocity for robot to 0 28F2: DD 70 08 ld (ix+$08),b ; set VECTOR.V.Y velocity for robot to 0 ; Now make the robot "look" in the direction of the player. 28F5: 7E ld a,(hl) ; get pattern address low byte 28F6: 23 inc hl 28F7: F3 di 28F8: DD 77 0A ld (ix+$0a),a ; set robot's VECTOR.D.P.L 28FB: 7E ld a,(hl) 28FC: DD 77 0B ld (ix+$0b),a ; set robot's VECTOR.D.P.H 28FF: FB ei 2900: 23 inc hl 2901: DD 36 0C 01 ld (ix+$0c),$01 ; set robot's VECTOR.TIME 2905: 46 ld b,(hl) ; get X delta into B 2906: 23 inc hl 2907: 4E ld c,(hl) ; get Y delta into C 2908: 23 inc hl 2909: 56 ld d,(hl) 290A: DD 7E 07 ld a,(ix+$07) ; read robot's VECTOR.X (X coordinate) 290D: 80 add a,b ; add X Delta held in B (see $2905) 290E: 47 ld b,a ; now B is initial X coordinate of bolt 290F: DD 7E 09 ld a,(ix+$09) ; read robot's VECTOR.Y (Y coordinate) 2912: 81 add a,c ; add Y Delta held in C (see $2907) 2913: 4F ld c,a ; now C is initial Y coordinate of bolt ; Restore pointer to BOLT structure 2914: E1 pop hl ; IX = pointer to robot's VECTOR structure ; HL = pointer to BOLT structure ; B = Bolt's initial X coordinate ; C = Bolt's initial Y coordinate ; D = DURL bits for bolt's direction 2915: F3 di 2916: 72 ld (hl),d ; set BOLT.Direction 2917: 23 inc hl 2918: 36 00 ld (hl),$00 ; set BOLT.Length 291A: 23 inc hl 291B: 70 ld (hl),b ; set BOLT.X 291C: 23 inc hl 291D: 71 ld (hl),c ; set BOLT.Y 291E: 23 inc hl 291F: 72 ld (hl),d ; set BOLT.LastDirection 2920: 23 inc hl 2921: 36 05 ld (hl),$05 ; set BOLT.MaxLength 2923: 23 inc hl 2924: 70 ld (hl),b ; Set BOLT.TailX 2925: 23 inc hl 2926: 71 ld (hl),c ; Set BOLT.TailY 2927: FB ei 2928: DD E5 push ix 292A: 3E 0A ld a,$0A ; delay 292C: CD 6D 1E call $1E6D ; call ACTIVATE_HEAD_JOB 292F: DD E1 pop ix 2931: 2A 72 08 ld hl,($0872) ; get head of list by reading contents of LINKED_LIST_PTR 2934: 23 inc hl 2935: 3A 4D 43 ld a,($434D) ; read RWAIT 2938: 77 ld (hl),a 2939: 2B dec hl 293A: CB CE set 1,(hl) 293C: E1 pop hl 293D: 23 inc hl 293E: 23 inc hl 293F: F1 pop af 2940: C1 pop bc 2941: 0E 10 ld c,$10 2943: E9 jp (hl) ; ; Robot shoot table. ; ; Defines what animation a robot's VECTOR should use when shooting, and deltas to add to VECTOR's X,Y coordinates ; to compute starting X,Y coordinates for a BOLT. ; ; Each entry in this table requires 6 bytes. ; ; WORD patternPtr - pointer to sprite pattern for robot to use when shooting. ; BYTE XDelta - X Delta to add to robot's X coordinate to compute bolt's initial X coordinate ; BYTE YDelta - Y Delta to add to robot's Y coordinate to compute bolt's initial Y coordinate ; BYTE Direction - DURL bits specifying direction bolt should go ; BYTE 0 - padding byte with no other use. ; ; See also: ; SR.TAB in this document, and ; S.TAB within shoot.asm in Frenzy's source code. ; ; No direction S.TAB: 2944: 00 10 00 ; Bolt X delta 00 ; Bolt Y delta 00 ; No direction 00 ; UP + RIGHT 294A: 00 10 07 ; Bolt X delta 06 ; Bolt Y delta 06 ; DURL bits (RIGHT + UP) 00 ; RIGHT 2950: 00 10 07 06 02 00 ; DOWN + RIGHT 2956: 00 10 07 06 0A 00 ; DOWN 295C: 00 10 07 06 08 00 ; DOWN + LEFT 2962: 00 10 00 06 09 00 ; LEFT 2968: 00 10 00 06 01 00 ; UP + LEFT 296E: 00 10 00 06 05 00 ; UP 2974: 00 10 07 01 04 00 297A: CA ; Print character string ; ; Expects: ; Return address on stack to point to N bytes: ; Byte 0: magic image RAM control bits ; Byte 1: X coordinate ; Byte 2: Y coordinate ; Byte 3.. N: null (zero byte) terminated text string ; ; When the print routine reads a zero byte, it will then jump to the instruction following the byte. PRINT_STRING_297B: 297B: E1 pop hl ; get return address from stack into HL 297C: 46 ld b,(hl) ; load B with magic RAM control bits 297D: 23 inc hl 297E: 5E ld e,(hl) ; load E with X coordinate 297F: 23 inc hl 2980: 56 ld d,(hl) ; load D with Y coordinate 2981: 23 inc hl 2982: EB ex de,hl ; now H = Y coordinate, L = X coordinate 2983: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 2986: EB ex de,hl ; now HL = pointer to character to print, DE = magic RAM address 2987: 4E ld c,(hl) ; read character to print 2988: CB B9 res 7,c 298A: CD DB 29 call $29DB ; call PRINT_CHAR 298D: 47 ld b,a 298E: 3A 79 43 ld a,($4379) ; read FLIP 2991: B7 or a 2992: 20 03 jr nz,$2997 ; if cocktail setup, goto $2997 ; playing on upright cabinet 2994: 13 inc de ; otherwise, its upright cabinet 2995: 18 01 jr $2998 ; playing on cocktail cabinet 2997: 1B dec de ; 2998: 23 inc hl ; bump HL to next character to print 2999: 7E ld a,(hl) ; read character 299A: B7 or a ; set zero flag if terminating character 0 found 299B: 78 ld a,b 299C: C2 87 29 jp nz,$2987 ; if not string terminator (0) goto $2987 299F: 23 inc hl 29A0: E9 jp (hl) ; jump to code immediately after string terminator byte ; ; Expects: ; H = Y coordinate ; L = X coordinate ; ; Returns: ; HL = Magic image RAM address ; ; Remarks: ; See also: RtoAx (Relative To Absolute) in showa.asm within Frenzy's source code RTOAX: 29A1: 06 90 ld b,$90 ; Magic image RAM control bits - XOR write ; Expects: ; B = bits to write to magicram_control_w ; H = Y coordinate ; L = X coordinate ; ; Returns: ; A = magic image RAM control byte ; HL = magic image RAM address ; if upright cabinet, BC = 0 ; (Cocktail path not investigated, as I deem that unnecessary extra work) ; ; See also: RtoA (Relative To Absolute) in showa.asm within Frenzy's source code CALCULATE_MAGIC_IMAGE_RAM_ADDRESS: 29A3: 3A 79 43 ld a,($4379) ; read FLIP 29A6: B7 or a ; set zero flag if playing on upright cabinet 29A7: 3E 07 ld a,$07 ; magic RAM control byte 29A9: 20 15 jr nz,$29C0 ; playing on upright cabinet 29AB: A5 and l 29AC: B0 or b ; combine with magic image RAM control bits 29AD: D3 4B out ($4B),a ; write to magicram_control_w 29AF: CB 3C srl h ; divide HL.. 29B1: CB 1D rr l 29B3: CB 3C srl h 29B5: CB 1D rr l 29B7: CB 3C srl h 29B9: CB 1D rr l ; .. by 8 29BB: 01 00 64 ld bc,$6400 ; start of magic image RAM 29BE: 09 add hl,bc ; now HL = image RAM address to return 29BF: C9 ret ; Playing on cocktail cabinet 29C0: A5 and l 29C1: B0 or b 29C2: CB DF set 3,a ; set horizontal flip bit 29C4: D3 4B out ($4B),a ; write to magicram_control_w 29C6: CB 3C srl h 29C8: CB 1D rr l 29CA: CB 3C srl h 29CC: CB 1D rr l 29CE: CB 3C srl h 29D0: CB 1D rr l 29D2: 44 ld b,h 29D3: 4D ld c,l 29D4: 21 FF 7F ld hl,$7FFF 29D7: B7 or a 29D8: ED 42 sbc hl,bc 29DA: C9 ret ; ; Plot a single character to the screen ; ; Expects: ; A = magic image RAM control byte ; C = ordinal of character to print ; DE = pointer to address in magic image RAM ; ; See also: SHOWC in showa.asm within Frenzy's source code. PRINT_CHAR: 29DB: E5 push hl 29DC: 21 00 00 ld hl,$0000 29DF: 06 00 ld b,$00 29E1: 09 add hl,bc ; HL = C 29E2: 29 add hl,hl 29E3: 29 add hl,hl 29E4: 29 add hl,hl 29E5: 09 add hl,bc ; HL = C * 9 29E6: 01 1E 2F ld bc,$2F1E 29E9: 09 add hl,bc ; now HL = pointer to start of character bitmap (9 bytes) 29EA: D5 push de 29EB: F5 push af 29EC: EB ex de,hl ; now DE = pointer to character set bitmap data, HL = pointer to magic image RAM 29ED: 3A 79 43 ld a,($4379) ; read FLIP 29F0: B7 or a ; set zero flag if playing on upright cabinet 29F1: 1A ld a,(de) ; read byte from character set bitmap 29F2: 20 26 jr nz,$2A1A ; if zero flag is not set, we're on cocktail cabinet, goto $2A1A ; Upright cabinet character print routine 29F4: B7 or a ; set various flags depending on character set bitmap data 29F5: F2 FC 29 jp p,$29FC ; if bit 7 is clear, goto $29FC 29F8: 01 60 00 ld bc,$0060 29FB: 09 add hl,bc ; move 3 lines down 29FC: 3E 09 ld a,$09 ; each character is 9 pixels high 29FE: 01 1F 00 ld bc,$001F ; offset to add to HL to get to next pixel row down 2A01: 08 ex af,af' 2A02: F1 pop af ; get magic image RAM control byte into A' 2A03: F5 push af 2A04: F3 di ; prevent interrupts while writing to magic RAM 2A05: D3 4B out ($4B),a ; write control byte param to magicram_control_w 2A07: 1A ld a,(de) ; read bitmap data from character set 2A08: E6 7F and $7F 2A0A: 13 inc de 2A0B: 77 ld (hl),a ; write 8 pixels to magic RAM 2A0C: 23 inc hl 2A0D: 36 00 ld (hl),$00 ; ensure character to right is deleted 2A0F: FB ei ; re-enable interrupts 2A10: 09 add hl,bc ; bump HL to point to the pixel row below where we will draw next line of our char 2A11: 08 ex af,af' 2A12: 3D dec a ; decrement count of pixel rows left to do 2A13: C2 01 2A jp nz,$2A01 ; repeat until all rows of character have been drawn 2A16: F1 pop af 2A17: D1 pop de 2A18: E1 pop hl 2A19: C9 ret ; Cocktail character print routine ; A = byte from character set bitmap data 2A1A: B7 or a 2A1B: F2 22 2A jp p,$2A22 2A1E: 01 A0 FF ld bc,$FFA0 2A21: 09 add hl,bc 2A22: 3E 09 ld a,$09 2A24: 01 E1 FF ld bc,$FFE1 2A27: 08 ex af,af' 2A28: F1 pop af 2A29: F5 push af 2A2A: F3 di 2A2B: D3 4B out ($4B),a ; write to magicram_control_w 2A2D: 1A ld a,(de) 2A2E: E6 7F and $7F 2A30: 13 inc de 2A31: 77 ld (hl),a 2A32: 2B dec hl 2A33: 36 00 ld (hl),$00 2A35: FB ei 2A36: 09 add hl,bc 2A37: 08 ex af,af' 2A38: 3D dec a 2A39: C2 27 2A jp nz,$2A27 2A3C: F1 pop af 2A3D: D1 pop de 2A3E: E1 pop hl 2A3F: C9 ret ; Print a BCD-encoded value with specified number of digits at given X, Y coordinates. ; ; Expects: ; B = number of digits to print ; HL = pointer to BCD digits to print ; D = Y coordinate ; E = X coordinate ; ; See also: SHOWN (Show Number) in showa.asm within Frenzy's source code PRINT_DIGITS: 2A40: C5 push bc 2A41: 06 00 ld b,$00 ; magic image RAM control bits 2A43: EB ex de,hl ; now HL = Y/X coordinates 2A44: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 2A47: EB ex de,hl ; now DE = magic image RAM address 2A48: 08 ex af,af' ; Save magic register byte 2A49: C1 pop bc SHOWO: ; bit 0 of C determines if numbers will be padded out to B digits length with leading spaces if required. ; if bit 0 is set, then padding is disabled (see $2A65) 2A4A: CB 81 res 0,c ; clear bit 0 of c, number will be padded with leading spaces 2A4C: 78 ld a,b ; load A with number of digits to print 2A4D: 3D dec a ; zero flag will now be set if number of digits to print is 1 2A4E: 20 02 jr nz,$2A52 ; if number of digits to print != 1, goto $2A52 ; we have 1 digit left to print 2A50: CB C1 set 0,c ; disable "pad with leading spaces" 2A52: 7E ld a,(hl) ; read BCD number 2A53: CB 40 bit 0,b ; is the index of the digit to print odd? 2A55: 20 09 jr nz,$2A60 ; yes, goto $2A60 ; index of digit is even. This means we need to shift the upper nibble to the lower nibble 2A57: CB 3F srl a ; move upper nibble.. 2A59: CB 3F srl a 2A5B: CB 3F srl a 2A5D: CB 3F srl a ; ..to lower nibble 2A5F: 2B dec hl ; decrement hl to compensate for following inc hl instruction. We want to read ; the lower nibble from the same byte next time 2A60: 23 inc hl 2A61: E6 0F and $0F ; test if end result is 0 2A63: 20 08 jr nz,$2A6D ; if not, then we disable the "pad with leading spaces" flag. 2A65: CB 41 bit 0,c ; test "disable pad with leading spaces" bit 2A67: 20 06 jr nz,$2A6F ; if bit is set, padding is disabled, goto $2A6F ; print a leading space character to pad the number out 2A69: 3E 20 ld a,$20 ; ordinal of SPACE character 2A6B: 18 0A jr $2A77 ; set the "disable pad with leading spaces" flag. Its time to start printing numbers! 2A6D: CB C1 set 0,c ; convert numeric value in A to an ASCII digit, e.g. 0 -> '0' (48 decimal in ASCII) 2A6F: C6 30 add a,$30 ; convert A to ASCII ordinal 2A71: FE 3A cp $3A 2A73: 38 02 jr c,$2A77 ; if A< 58 decimal its fine to print as is, goto $2A77 2A75: C6 07 add a,$07 ; A= ordinal of character to print 2A77: E5 push hl 2A78: C5 push bc 2A79: 4F ld c,a ; load C with ordinal of character to print 2A7A: 08 ex af,af' ; Restore magic register byte 2A7B: CD DB 29 call $29DB ; call PRINT_CHAR 2A7E: 08 ex af,af' 2A7F: C1 pop bc 2A80: E1 pop hl 2A81: 3A 79 43 ld a,($4379) ; read FLIP 2A84: B7 or a ; set zero flag if playing on upright cabinet 2A85: 20 03 jr nz,$2A8A ; if zero flag is not set, we're on cocktail cabinet, goto $2A8A ; upright cabinet 2A87: 13 inc de 2A88: 18 01 jr $2A8B ; cocktail cabinet setup 2A8A: 1B dec de ; called for both upright & cocktail 2A8B: 10 BF djnz $2A4C 2A8D: C9 ret ; ; Initialise Evil Otto. ; ; TODO: Analysis in progress, comments incomplete. ; ; Remarks: ; See also function SUPER in super.asm within Frenzy's source code. 2A8E: C5 push bc 2A8F: D1 pop de 2A90: CD 0E 20 call $200E 2A93: CD 22 1E call $1E22 ; call CREATE_JOB 2A96: DD E5 push ix 2A98: CD 59 1E call $1E59 2A9B: DD E1 pop ix ; Look at the player's start position in order to calculate Otto's start position. 2A9D: 2A 47 43 ld hl,($4347) ; load MAN_X into L and MAN_Y into H 2AA0: 7D ld a,l ; get MAN_X into A 2AA1: FE 18 cp $18 2AA3: 30 04 jr nc,$2AA9 ; if A>= then goto 2AA5: 2E 02 ld l,$02 2AA7: 18 06 jr $2AAF 2AA9: FE E6 cp $E6 2AAB: 38 02 jr c,$2AAF ; if A< then goto 2AAD: 2E F8 ld l,$F8 2AAF: 7C ld a,h ; get MAN_Y into A 2AB0: FE B4 cp $B4 2AB2: 38 02 jr c,$2AB6 2AB4: 26 A0 ld h,$A0 2AB6: DD 75 07 ld (ix+$07),l ; set VECTOR.X 2AB9: DD 74 09 ld (ix+$09),h ; set VECTOR.Y 2ABC: 3A 4C 43 ld a,($434C) ; read ROBOT_SPEED 2ABF: 47 ld b,a 2AC0: 3A 72 43 ld a,($4372) ; read RSAVED 2AC3: 80 add a,b 2AC4: 47 ld b,a 2AC5: 3A 4B 43 ld a,($434B) ; read RBOLTS 2AC8: 80 add a,b 2AC9: 32 4E 43 ld ($434E),a ; set OTTO_TIME 2ACC: DD E5 push ix 2ACE: 3E 28 ld a,$28 2AD0: CD 6D 1E call $1E6D 2AD3: DD E1 pop ix 2AD5: 21 4E 43 ld hl,$434E ; load HL with address of OTTO_TIME 2AD8: 35 dec (hl) 2AD9: 20 F1 jr nz,$2ACC ; time for otto to appear!!! 2ADB: CD DE 2B call $2BDE ; say "INTRUDER ALERT! INTRUDER ALERT!" 2ADE: 21 0B 12 ld hl,$120B ; address of Otto's sprite data 2AE1: DD 75 0A ld (ix+$0a),l 2AE4: DD 74 0B ld (ix+$0b),h 2AE7: DD 36 0C 01 ld (ix+$0c),$01 2AEB: DD 36 0D 02 ld (ix+$0d),$02 2AEF: DD 36 00 06 ld (ix+$00),$06 2AF3: AF xor a 2AF4: CD 39 2B call $2B39 2AF7: DD E5 push ix 2AF9: C5 push bc 2AFA: 3E 28 ld a,$28 2AFC: CD 6D 1E call $1E6D 2AFF: C1 pop bc 2B00: DD E1 pop ix 2B02: FD 2A 76 08 ld iy,($0876) ; load IY with contents of MAN_PTR 2B06: C5 push bc 2B07: FD 7E 07 ld a,(iy+$07) 2B0A: C6 02 add a,$02 2B0C: DD 96 07 sub (ix+$07) 2B0F: 57 ld d,a 2B10: 06 00 ld b,$00 2B12: 28 06 jr z,$2B1A 2B14: 06 01 ld b,$01 2B16: 38 02 jr c,$2B1A 2B18: 06 02 ld b,$02 2B1A: FD 7E 09 ld a,(iy+$09) 2B1D: DD 96 09 sub (ix+$09) 2B20: 5F ld e,a 2B21: 0E 00 ld c,$00 2B23: 28 06 jr z,$2B2B 2B25: 0E 04 ld c,$04 2B27: 38 02 jr c,$2B2B 2B29: 0E 08 ld c,$08 2B2B: 78 ld a,b 2B2C: 81 add a,c 2B2D: C1 pop bc 2B2E: CD 39 2B call $2B39 2B31: 3E 04 ld a,$04 2B33: CD 54 2B call $2B54 2B36: C3 02 2B jp $2B02 2B39: E6 0F and $0F 2B3B: B9 cp c 2B3C: C8 ret z ; ; Set X and Y velocities for a VECTOR. ; ; Expects: ; A = DURL Direction bits (bit 0 set: left, 1: right, 2: up, 3:down) ; IX = pointer to VECTOR structure ; ; Returns: ; DE = offset to be used to read from a direction-based table, such as M.TAB ; ; Remarks: ; See also: SETVXY in super.asm within Frenzy's source code SET_VELOCITY: 2B3D: 4F ld c,a 2B3E: 06 00 ld b,$00 ; Extend A into BC (meaning, BC = A) 2B40: 50 ld d,b 2B41: 21 42 20 ld hl,$2042 ; load HL with address of D.TAB 2B44: 09 add hl,bc ; now HL = pointer to entry in table 2B45: 5E ld e,(hl) ; read offset byte from table. Now DE = offset 2B46: 21 19 25 ld hl,$2519 ; load HL with address of M.TAB 2B49: 19 add hl,de ; now HL = pointer to entry in M.TAB 2B4A: 7E ld a,(hl) ; read X delta from table 2B4B: 23 inc hl 2B4C: DD 77 06 ld (ix+$06),a ; set VECTOR.X 2B4F: 7E ld a,(hl) ; read Y delta from table 2B50: DD 77 08 ld (ix+$08),a ; set VECTOR.Y 2B53: C9 ret 2B54: 2A 72 08 ld hl,($0872) 2B57: 36 82 ld (hl),$82 2B59: 23 inc hl 2B5A: 77 ld (hl),a 2B5B: DD E5 push ix 2B5D: E5 push hl 2B5E: C5 push bc 2B5F: CD 78 1E call $1E78 2B62: C1 pop bc 2B63: E1 pop hl 2B64: DD E1 pop ix 2B66: DD CB 00 7E bit 7,(ix+$00) 2B6A: C9 ret ; ; Select random sentences from a speech table and insert them into a speech buffer. ; VOICE_PC can then be set to point to this buffer, and The NMI handler @ $1748 will ; make the robots say the words represented by the speech bytes stored in the buffer. ; ; Expects: ; HL = pointer to a speech table (see ROBOT_TARGET_SPEECH_TABLE @ $2C25 for an example) ; DE = pointer to buffer in RAM that will hold result ; B = number of entries ("sentences") held in table at HL ; ; The last speech byte for each "sentence" in the table must have bit 7 set. ; ; Algorithm: ; Calculate a random number between 0..15. Let's call it RAND. ; Subtract the value in B from RAND until the result is a negative number. ; Add B to negative result to make it positive again. Call this value SENTENCENUMBER ; Scan memory from HL for exactly SENTENCENUMBER bytes that have bit 7 set. Or, put another way, ; skip number of sentences in the table. ; ; HL then points to a sequence of speech bytes. The last speech byte in the sequence will have bit 7 set, as a "marker" bit. ; From HL: ; read byte from HL. ; and byte with $7F to remove bit 7. ; write byte to speech buffer. ; increment HL and DE. ; if bit 7 of byte read was not set, continue loop. ; else, this is the last speech byte in the word sequence, so exit routine. WRITE_RANDOM_SENTENCE_TO_BUFFER: 2B6B: D5 push de 2B6C: CD 78 26 call $2678 ; call RANDOM 2B6F: D1 pop de ; A now = random number. ; Looks like this is just shaking A up a bit more - adding a wee bit more "randomness" perhaps?. I can't discern any other logic. 2B70: 07 rlca 2B71: 07 rlca 2B72: EE 09 xor $09 2B74: E6 0F and $0F ; A is now a pseudo-random number between 0 and 15 decimal (RAND in docs above) ; Keep subtracting B from A until A is a negative number, then add B to A again to make it positive. ; A is then the sentence number (SENTENCENUMBER) to read from the speech table pointed to by HL 2B76: 90 sub b 2B77: FA 7C 2B jp m,$2B7C ; if A is negative, goto $2B7C 2B7A: 18 FA jr $2B76 ; otherwise, keep subtracting B from A. 2B7C: 80 add a,b ; Ensure A is a positive number 2B7D: 28 0C jr z,$2B8B ; if A is 0 then we're selecting the first sentence from the speech table. HL already points to it, ; so no need to go into a loop to find the word. ; We need to loop through the speech table to find the correct sentence. ; A is the sentence number (SENTENCENUMBER) to read from the speech table pointed to by HL 2B7F: 47 ld b,a ; preserve A in B, as A will be used for other purposes ; This code will read from and increment HL until it reads exactly bytes with bit 7 set ; In Plain English - look for sentence terminating bytes. 2B80: 7E ld a,(hl) ; read a byte from the speech template 2B81: CB 7F bit 7,a ; test if bit 7 is set 2B83: 20 03 jr nz,$2B88 ; if bit 7 is set, decrement B, and if B!=0 goto $2b80 2B85: 23 inc hl ; otherwise ignore this byte 2B86: 18 F8 jr $2B80 ; Increment HL and decrement B. Loop until B==0. 2B88: 23 inc hl 2B89: 10 F5 djnz $2B80 ; HL now points to the sentence we want to copy into the SPEECH_BUFFER ; DE = pointer to a byte in SPEECH_BUFFER ; The last byte of the word in the sentence has bit 7 set. 2B8B: 7E ld a,(hl) ; read byte from sentence 2B8C: 47 ld b,a ; preserve in B 2B8D: E6 7F and $7F ; mask out bit 7 and preserve rest. 2B8F: 12 ld (de),a ; write speech byte into SPEECH_BUFFER 2B90: 13 inc de ; bump DE to next byte of speech buffer 2B91: CB 78 bit 7,b ; test bit 7 - is the "end of sentence" marker set? 2B93: 23 inc hl ; bump HL to point to next byte in speech template 2B94: 28 F5 jr z,$2B8B ; if bit 7 is not set, goto $2B8B to read another speech byte. 2B96: C9 ret ; ; Generates random speech for robots to say ; ; Speech is processed in NMI_HANDLER @ $1748 ; ; Remarks: I could not find a corresponding routine in Frenzy's source code. ; I guess this makes sense, as Frenzy is much less talkative than Berzerk. ; Nevertheless, I enjoyed working out the logic here - very satisfying to crack it by oneself. ; GENERATE_ROBOT_SPEECH: 2B97: 2A 98 08 ld hl,($0898) ; read VOICE_PC 2B9A: 7C ld a,h 2B9B: B5 or l ; if H is 0 and L is 0 then A will be 0. HL is thus NULL and zero flag will be set. 2B9C: C0 ret nz ; exit if VOICE_PC is not a null pointer ; Time for the robots to speak? 2B9D: 21 9B 08 ld hl,$089B ; Load HL with address of TALK_TIMER 2BA0: 35 dec (hl) ; decrement countdown. 2BA1: C0 ret nz ; if counter hasn't hit zero, it's not time for the robots to talk, exit ; Set countdown before robots next speak 2BA2: CD 78 26 call $2678 ; call RANDOM 2BA5: 07 rlca 2BA6: 07 rlca 2BA7: E6 0C and $0C 2BA9: C6 04 add a,$04 ; ensure timer is 4 minimum, otherwise the robots will speak too often 2BAB: 77 ld (hl),a ; set TALK_TIMER ; OK, its time for the robots to speak. Generate a sentence in SPEECH_BUFFER. 2BAC: 21 18 09 ld hl,$0918 ; load HL with address of SPEECH_BUFFER ; ; Algorithm: ; Select voice pitch at random. ; Let firstWord = a random word from ROBOT_FIRST_WORD_SPEECH_TABLE. ; Let LastWords = a random sentence chosen from ROBOT_TARGET_SPEECH_TABLE. ; Let sentenceToSpeak = firstWord + LastWords. ; Store sentenceToSpeak in SPEECH_BUFFER ; Say sentenceToSpeak. ; ; Example: if firstWord is "GET" and lastwords are "THE HUMANOID", create "GET THE HUMANOID" in SPEECH_BUFFER then speak it ; ; first byte in buffer is pitch for voice. Generate this at random 2BAF: CD 78 26 call $2678 ; call RANDOM 2BB2: E6 1F and $1F ; ensure number is between 0..31 decimal 2BB4: F6 60 or $60 2BB6: 77 ld (hl),a ; first byte = set pitch/ speed 2BB7: 23 inc hl ; bump HL to next byte in SPEECH_BUFFER 2BB8: EB ex de,hl ; Get a random byte from ROBOT_FIRST_WORD_SPEECH_TABLE speech table and insert it into SPEECH_BUFFER. 2BB9: 21 2C 2C ld hl,$2C2C ; load HL with address of ROBOT_FIRST_WORD_SPEECH_TABLE 2BBC: 06 06 ld b,$06 ; there are 6 words available to choose from in the table 2BBE: CD 6B 2B call $2B6B ; call WRITE_RANDOM_SENTENCE_TO_BUFFER - just writes a single spoken word. ; Write the bytes representing the word(s) comprising the target of the sentence (the player!) to SPEECH_BUFFER. 2BC1: 21 25 2C ld hl,$2C25 ; load HL with address of ROBOT_TARGET_SPEECH_TABLE speech table 2BC4: 06 04 ld b,$04 ; There are 4 word sequences in the table to choose from 2BC6: 3A 9A 08 ld a,($089A) ; read IS_CHICKEN flag 2BC9: B7 or a ; test if flag is set 2BCA: 20 03 jr nz,$2BCF ; if flag is set, the player's a chicken, goto $2BCF ; The player's not a chicken, but HL currently points to a list of word sequences that include "THE CHICKEN" ; We can't call the player a chicken if they aren't, so adjust HL to skip over the words "THE CHICKEN" in ; ROBOT_TARGET_SPEECH_TABLE table. 2BCC: 23 inc hl 2BCD: 23 inc hl ; now HL points to "IT" in the ROBOT_TARGET_SPEECH_TABLE speech table. 2BCE: 05 dec b ; decrement B to 3, which means "only 3 word sequences left to choose from" ; Code executes whether chicken or not ;) 2BCF: CD 6B 2B call $2B6B ; call WRITE_RANDOM_SENTENCE_TO_BUFFER 2BD2: EB ex de,hl 2BD3: 36 47 ld (hl),$47 ; write "end of sentence" byte required by speech synthesiser 2BD5: 23 inc hl 2BD6: 36 FF ld (hl),$FF ; write terminator byte for NMI routine to read (see $1755 which detects it) 2BD8: 21 18 09 ld hl,$0918 ; load HL with address of SPEECH_BUFFER 2BDB: C3 1B 2C jp $2C1B ; jump to TALK SAY_INTRUDER_ALERT_INTRUDER_ALERT: 2BDE: 21 4A 2C ld hl,$2C4A ; load HL with address of INTRUDER_ALERT_INTRUDER_ALERT speech data 2BE1: C3 1B 2C jp $2C1B ; jump to TALK ; ; Called when exiting a room after killing all robots (with exception of Otto, of course). ; ; TRY_SPEAK_ON_PLAYER_LEAVING_ROOM: ; Has the player killed all of the robots? 2BE4: 3A 71 43 ld a,($4371) ; read RCOUNT 2BE7: B7 or a ; test if zero. 2BE8: 20 29 jr nz,$2C13 ; if there's still some robots left in the maze, player's a chicken. Goto SAY_CHICKEN_FIGHT_LIKE_A_ROBOT ; Player's not a chicken. ; Say "THE HUMANOID MUST NOT ESCAPE" or "THE INTRUDER MUST NOT ESCAPE" ; First, select pitch of robot voice. 2BEA: 21 18 09 ld hl,$0918 ; load HL with address of SPEECH_BUFFER 2BED: CD 78 26 call $2678 ; call RANDOM 2BF0: E6 07 and $07 ; clamp number to 0..7 2BF2: F6 70 or $70 2BF4: 77 ld (hl),a ; first byte = set pitch/ speed 2BF5: 23 inc hl ; bump to next byte in SPEECH_BUFFER 2BF6: EB ex de,hl ; Add bytes representing "THE HUMANOID" or "THE INTRUDER" and insert them into SPEECH_BUFFER. 2BF7: 21 28 2C ld hl,$2C28 ; point to the second word sequence, "THE HUMANOID", within ROBOT_TARGET_SPEECH_TABLE 2BFA: 06 02 ld b,$02 ; 2 remaining word sequences to choose from in the list 2BFC: CD 6B 2B call $2B6B ; call WRITE_RANDOM_SENTENCE_TO_BUFFER ; Append MUST NOT ESCAPE 2BFF: 21 32 2C ld hl,$2C32 ; load HL with address of MUST_NOT_ESCAPE_SPEECH_TABLE 2C02: 06 01 ld b,$01 ; MUST NOT ESCAPE is the sole word sequence available, so just 1 to choose from. 2C04: CD 6B 2B call $2B6B ; call WRITE_RANDOM_SENTENCE_TO_BUFFER 2C07: EB ex de,hl 2C08: 36 44 ld (hl),$44 ; write "end of sentence" byte required by speech synthesiser 2C0A: 23 inc hl 2C0B: 36 FF ld (hl),$FF ; write terminator byte for NMI routine to read (see $1755 which detects it) 2C0D: 21 18 09 ld hl,$0918 ; load HL with address of SPEECH_BUFFER 2C10: AF xor a ; clear the IS_CHICKEN flag 2C11: 18 05 jr $2C18 ; jump to tTALK ; ; The player's exited the room. Taunt them with "Chicken, fight like a robot" (!) ; ; SAY_CHICKEN_FIGHT_LIKE_A_ROBOT: 2C13: 21 35 2C ld hl,$2C35 ; load HL with address of CHICKEN_FIGHT_LIKE_A_ROBOT_SPEECH_BYTES speech data 2C16: 3E FF ld a,$FF ; This will make the player a chicken in the robot's eyes! 2C18: 32 9A 08 ld ($089A),a ; set IS_CHICKEN flag ; Set VOICE_PC - the NMI handler ; HL = pointer to speech data TALK: 2C1B: 22 98 08 ld ($0898),hl ; update VOICE_PC 2C1E: C9 ret SAY_GOT_THE_HUMANOID_GOT_THE_INTRUDER: 2C1F: 21 40 2C ld hl,$2C40 ; load HL with address of GOT_THE_HUMANOID_GOT_THE_INTRUDER_SPEECH_BYTES speech data 2C22: AF xor a ; clear the IS_CHICKEN flag 2C23: 18 F3 jr $2C18 ; ; Used in dynamically generating robot speech ; ; ; There are 4 sentences available in this speech table. They are as follows: ; ; THE CHICKEN ; IT ; THE HUMANOID ; THE INTRUDER ; ; Note how bit 7 of the CHICKEN, IT, HUMANOID, INTRUDER speech bytes are set; this bit marks the end of a sentence. ; (See docs for WRITE_RANDOM_SENTENCE_TO_BUFFER @ $2B6B) ; ; See also: ; docs @ $2BAC for more info. ROBOT_TARGET_SPEECH_TABLE: 2C25: 0A ; THE 98 ; CHICKEN 8C ; IT 0A ; THE 8F ; HUMANOID 0A ; THE 92 ; INTRUDER ; bit 7 set to terminate the sentence ; ; ROBOT_FIRST_WORD_SPEECH_TABLE contains a list of words that begin a sentence spoken by the robots. ; Note how bit 7 of each byte is set; this stops WRITE_RANDOM_SENTENCE_TO_BUFFER @ $2B6B from taking more than a single word from this table. ; ; See also: ; $2BB9 within GENERATE_ROBOT_SPEECH ; ROBOT_FIRST_WORD_SPEECH_TABLE: 2C2C: 86 ; GET 83 ; CHARGE 82 ; ATTACK 95 ; DESTROY 85 ; SHOOT 81 ; KILL ; ; Used to generate the sentence " MUST NOT ESCAPE" ; Note how bit 7 of ESCAPE (the last word) is set. MUST_NOT_ESCAPE_SPEECH_TABLE: 2C32: 16 ; MUST 17 ; NOT 94 ; ESCAPE CHICKEN_FIGHT_LIKE_A_ROBOT_SPEECH_BYTES: 2C35: 73 ; Pitch of speech 18 ; CHICKEN 47 1B ; "A" - TODO: why is this here? Wonder if its silent just to introduce a delay? 73 19 ; FIGHT 1A ; LIKE 1B ; A 1C ; ROBOT 47 FF ; Terminator byte GOT_THE_HUMANOID_GOT_THE_INTRUDER_SPEECH_BYTES: 2C40: 7B ; Pitch of speech 04 ; GOT 0A ; THE 0F ; HUMANOID 7D 04 ; GOT 0A ; THE 12 ; INTRUDER 47 FF ; Terminator byte INTRUDER_ALERT_INTRUDER_ALERT: 2C4A: 7B ; Pitch of speech 12 ; INTRUDER 08 ; ALERT 12 ; INTRUDER 08 ; ALERT 47 FF ; Terminator byte 2C51: CD 34 23 call $2334 ; call GET_PLAYER_SCORE_PTR 2C54: E5 push hl 2C55: 23 inc hl 2C56: 23 inc hl 2C57: EB ex de,hl 2C58: 21 C4 08 ld hl,$08C4 ; load HL with address of CMOS_TOTAL_SCORE 2C5B: 0E 03 ld c,$03 2C5D: 06 0C ld b,$0C 2C5F: 1A ld a,(de) 2C60: E6 0F and $0F 2C62: 28 06 jr z,$2C6A 2C64: CD B3 2D call $2DB3 ; call INCREMENT_BY_1 2C67: 3D dec a 2C68: 20 FA jr nz,$2C64 2C6A: 05 dec b 2C6B: 1A ld a,(de) 2C6C: E6 F0 and $F0 2C6E: 28 07 jr z,$2C77 2C70: CD B3 2D call $2DB3 ; call INCREMENT_BY_1 2C73: D6 10 sub $10 2C75: 20 F9 jr nz,$2C70 2C77: 05 dec b 2C78: 1B dec de 2C79: 0D dec c 2C7A: 20 E3 jr nz,$2C5F 2C7C: 0E 0A ld c,$0A 2C7E: 11 02 43 ld de,$4302 2C81: E1 pop hl 2C82: E5 push hl 2C83: D5 push de 2C84: 06 03 ld b,$03 2C86: 1A ld a,(de) 2C87: BE cp (hl) 2C88: 38 11 jr c,$2C9B 2C8A: 20 04 jr nz,$2C90 2C8C: 13 inc de 2C8D: 23 inc hl 2C8E: 10 F6 djnz $2C86 2C90: D1 pop de 2C91: 21 06 00 ld hl,$0006 2C94: 19 add hl,de 2C95: EB ex de,hl 2C96: E1 pop hl 2C97: 0D dec c 2C98: 20 E8 jr nz,$2C82 2C9A: C9 ret 2C9B: D1 pop de 2C9C: D5 push de 2C9D: 06 00 ld b,$00 2C9F: 0D dec c 2CA0: 28 14 jr z,$2CB6 2CA2: 21 00 00 ld hl,$0000 2CA5: 09 add hl,bc 2CA6: 29 add hl,hl 2CA7: 09 add hl,bc 2CA8: 29 add hl,hl 2CA9: E5 push hl 2CAA: 19 add hl,de 2CAB: 2B dec hl 2CAC: 54 ld d,h 2CAD: 5D ld e,l 2CAE: 01 06 00 ld bc,$0006 2CB1: 09 add hl,bc 2CB2: EB ex de,hl 2CB3: C1 pop bc 2CB4: ED B8 lddr 2CB6: D1 pop de 2CB7: E1 pop hl 2CB8: 06 03 ld b,$03 2CBA: 7E ld a,(hl) 2CBB: 23 inc hl 2CBC: 12 ld (de),a 2CBD: 13 inc de 2CBE: 10 FA djnz $2CBA 2CC0: EB ex de,hl 2CC1: E5 push hl 2CC2: CD 4E 1A call $1A4E ; call CLEAR_SCREEN 2CC5: CD 1C 36 call $361C 2CC8: CD ED 1A call $1AED ; call LTABLE 2CCB: 1B dec de 2CCC: 00 nop 2CCD: D8 ret c 2CCE: 2D dec l 2CCF: 3A 00 F4 ld a,($F400) 2CD2: 2D dec l 2CD3: 08 ex af,af' 2CD4: 06 01 ld b,$01 2CD6: 21 44 43 ld hl,$4344 2CD9: CD 4A 2A call $2A4A 2CDC: CD ED 1A call $1AED ; call LTABLE 2CDF: 93 sub e 2CE0: 07 rlca 2CE1: 71 ld (hl),c 2CE2: 2E 13 ld l,$13 2CE4: 2E CB ld l,$CB 2CE6: 2E CD ld l,$CD 2CE8: 7B ld a,e 2CE9: 29 add hl,hl 2CEA: 90 sub b 2CEB: 78 ld a,b 2CEC: 62 ld h,d 2CED: 5F ld e,a 2CEE: 5F ld e,a 2CEF: 5F ld e,a 2CF0: 00 nop 2CF1: CD ED 1A call $1AED ; call LTABLE 2CF4: 1B dec de 2CF5: 2F cpl 2CF6: 1B dec de 2CF7: 2F cpl 2CF8: 61 ld h,c 2CF9: 2F cpl 2CFA: BC cp h 2CFB: 2F cpl 2CFC: 06 00 ld b,$00 2CFE: 21 78 60 ld hl,$6078 2D01: CD A3 29 call $29A3 ; call CALCULATE_MAGIC_IMAGE_RAM_ADDRESS 2D04: EB ex de,hl 2D05: E1 pop hl 2D06: E5 push hl 2D07: 06 03 ld b,$03 2D09: 36 20 ld (hl),$20 2D0B: 23 inc hl 2D0C: 10 FB djnz $2D09 2D0E: E1 pop hl 2D0F: 3E 1E ld a,$1E 2D11: 32 49 43 ld ($4349),a ; set DEATHS 2D14: 06 03 ld b,$03 2D16: 0E 41 ld c,$41 2D18: C5 push bc 2D19: 3A 79 43 ld a,($4379) ; read FLIP 2D1C: CD DB 29 call $29DB ; call PRINT_CHAR 2D1F: D5 push de 2D20: E5 push hl 2D21: 3E 0F ld a,$0F 2D23: CD 6D 1E call $1E6D 2D26: E1 pop hl 2D27: D1 pop de 2D28: C1 pop bc 2D29: FD CB 00 CE set 1,(iy+$00) 2D2D: FD 36 01 3C ld (iy+$01),$3C 2D31: FD 7E 01 ld a,(iy+$01) 2D34: B7 or a 2D35: 20 0B jr nz,$2D42 2D37: 3A 49 43 ld a,($4349) ; read DEATHS 2D3A: 3D dec a 2D3B: 32 49 43 ld ($4349),a ; set DEATHS 2D3E: 28 3A jr z,$2D7A 2D40: 18 E7 jr $2D29 2D42: CD CE 2D call $2DCE 2D45: CB 67 bit 4,a 2D47: 20 46 jr nz,$2D8F 2D49: 71 ld (hl),c 2D4A: C5 push bc 2D4B: 3A 79 43 ld a,($4379) ; read FLIP 2D4E: B7 or a 2D4F: 01 40 00 ld bc,$0040 2D52: 28 03 jr z,$2D57 2D54: 01 C0 FF ld bc,$FFC0 2D57: D5 push de 2D58: EB ex de,hl 2D59: 09 add hl,bc 2D5A: EB ex de,hl 2D5B: 3A 79 43 ld a,($4379) ; read FLIP 2D5E: F6 90 or $90 2D60: 0E 5F ld c,$5F 2D62: CD DB 29 call $29DB ; call PRINT_CHAR 2D65: D1 pop de 2D66: C1 pop bc 2D67: 23 inc hl 2D68: 3A 79 43 ld a,($4379) ; read FLIP 2D6B: B7 or a 2D6C: 13 inc de 2D6D: 28 02 jr z,$2D71 2D6F: 1B dec de 2D70: 1B dec de 2D71: CD CE 2D call $2DCE 2D74: CB 67 bit 4,a 2D76: 28 F9 jr z,$2D71 2D78: 10 9E djnz $2D18 2D7A: 21 02 43 ld hl,$4302 2D7D: 11 DC 08 ld de,$08DC 2D80: 06 1E ld b,$1E 2D82: 7E ld a,(hl) 2D83: 23 inc hl 2D84: 12 ld (de),a 2D85: 13 inc de 2D86: 07 rlca 2D87: 07 rlca 2D88: 07 rlca 2D89: 07 rlca 2D8A: 12 ld (de),a 2D8B: 13 inc de 2D8C: 10 F4 djnz $2D82 2D8E: C9 ret 2D8F: CD CE 2D call $2DCE 2D92: 2F cpl 2D93: CB 47 bit 0,a 2D95: 28 04 jr z,$2D9B 2D97: 3E FF ld a,$FF 2D99: 18 07 jr $2DA2 2D9B: CB 4F bit 1,a 2D9D: CA 31 2D jp z,$2D31 2DA0: 3E 01 ld a,$01 2DA2: 81 add a,c 2DA3: FE 40 cp $40 2DA5: 20 02 jr nz,$2DA9 2DA7: 3E 5A ld a,$5A 2DA9: FE 5B cp $5B 2DAB: 20 02 jr nz,$2DAF 2DAD: 3E 41 ld a,$41 2DAF: 4F ld c,a 2DB0: C3 18 2D jp $2D18 ; ; Increment a BCD-packed number by 1. ; ; Expects: ; B = length of number in digits ; HL = pointer to bytes containing digits. Upper nibble of each byte contains digits. ; ; Remarks: ; ; Algorithm: ; Working from the last digit to the first: ; 1. Read byte ; 2. Mask in (preserve) upper nibble and treat that as a number from 0-9. ; 3. Add 1 to that number. ; 4. Update byte with result ; 5. If no carry (ie: result of increment is <=9) then exit ; 6. Otherwise repeat step 1 with byte before last ; ; See also: ItemInc in books.asm within Frenzy's source code INCREMENT_BY_1: 2DB3: F5 push af 2DB4: C5 push bc 2DB5: D5 push de 2DB6: E5 push hl 2DB7: 16 00 ld d,$00 ; Extend B.. 2DB9: 58 ld e,b ; into DE. 2DBA: 1D dec e ; Effectively DE is now B-1. 2DBB: 19 add hl,de ; make HL point to very last digit 2DBC: 0E 10 ld c,$10 2DBE: 7E ld a,(hl) ; read byte 2DBF: E6 F0 and $F0 ; mask in upper nibble 2DC1: 81 add a,c ; add 1 to upper nibble 2DC2: 27 daa ; ensure valid BCD 2DC3: 77 ld (hl),a ; and write it back 2DC4: 30 03 jr nc,$2DC9 ; if the operation didn't cause a carry, restore regs and exit 2DC6: 2B dec hl 2DC7: 10 F5 djnz $2DBE ; repeat until no more digits to process 2DC9: E1 pop hl 2DCA: D1 pop de 2DCB: C1 pop bc 2DCC: F1 pop af 2DCD: C9 ret 2DCE: 3A 79 43 ld a,($4379) ; read FLIP 2DD1: B7 or a 2DD2: DB 48 in a,($48) ; read player 1 controls 2DD4: C8 ret z 2DD5: DB 4A in a,($4A) ; read player 2 controls 2DD7: C9 ret 2DD8: CD 7B 29 call $297B ; call PRINT_STRING_297B 2DDB: 90 20 08 ; X/Y coordinates 2DDE: 47 72 61 74 75 6C 69 65 72 65 2C 20 53 70 69 65 Gratuliere, Spie 2DEE: 6C 65 72 20 00 C9 CD 7B 29 90 20 08 46 65 6C 69 ler ...{). .Feli 2DFE: 63 69 74 61 63 69 6F 6E 65 73 20 6A 75 67 61 64 citaciones jugad 2E0E: 6F 72 20 00 C9 CD 7B 29 90 08 20 56 6F 75 73 20 or ...{).. Vous 2E1E: 61 76 65 7A 20 6A 6F 69 6E 74 20 6C 65 73 20 69 avez joint les i 2E2E: 6D 6D 6F 72 74 65 6C 73 00 CD 7B 29 90 08 30 64 mmortels..{)..0d 2E3E: 75 20 70 61 6E 74 68 65 6F 6E 20 42 45 52 5A 45 u pantheon BERZE 2E4E: 52 4B 2E 00 CD 7B 29 90 08 50 49 6E 73 63 72 69 RK...{)..PInscri 2E5E: 72 65 20 76 6F 73 20 69 6E 69 74 69 61 6C 65 73 re vos initiales 2E6E: 3A 00 C9 CD 7B 29 90 08 20 44 61 73 20 57 61 72 :...{).. Das War 2E7E: 20 65 69 6E 20 52 75 68 6D 76 6F 6C 6C 65 72 20 ein Ruhmvoller 2E8E: 53 69 65 67 21 00 CD 7B 29 90 08 40 54 72 61 67 Sieg!..{)..@Trag 2E9E: 20 44 65 69 6E 65 6E 20 4E 61 6D 65 6E 20 69 6E Deinen Namen in 2EAE: 20 64 69 65 00 CD 7B 29 90 08 50 48 65 6C 64 65 die..{)..PHelde 2EBE: 6E 6C 69 73 74 65 20 65 69 6E 21 00 C9 CD 7B 29 nliste ein!...{) 2ECE: 90 04 20 53 65 20 70 75 6E 74 61 6A 65 20 65 73 .. Se puntaje es 2EDE: 74 61 20 65 6E 74 72 65 20 6C 6F 73 20 64 69 65 ta entre los die 2EEE: 7A 00 CD 7B 29 90 08 30 6D 65 6A 6F 72 65 73 2E z..{)..0mejores. 2EFE: 00 CD 7B 29 90 18 50 45 6E 74 72 65 20 73 75 73 ..{)..PEntre sus 2F0E: 20 69 6E 69 63 69 61 6C 65 73 3A 00 C9 CD 7B 29 iniciales:...{) 2F1E: 90 08 80 4D 6F 76 65 20 73 74 69 63 6B 20 74 6F ...Move stick to 2F2E: 20 63 68 61 6E 67 65 20 6C 65 74 74 65 72 00 CD change letter.. 2F3E: 7B 29 90 08 90 74 68 65 6E 20 70 72 65 73 73 20 {)...then press 2F4E: 46 49 52 45 20 74 6F 20 73 74 6F 72 65 20 69 74 FIRE to store it 2F5E: 2E 00 C9 CD 7B 29 90 04 80 50 6F 75 73 73 65 7A ....{)...Poussez 2F6E: 20 62 61 74 6F 6E 6E 65 74 20 70 6F 75 72 20 76 batonnet pour v 2F7E: 6F 73 00 CD 7B 29 90 04 90 69 6E 69 74 69 61 6C os..{)...initial 2F8E: 65 73 2E 20 50 6F 75 73 73 65 7A 20 46 49 52 45 es. Poussez FIRE 2F9E: 20 71 75 61 6E 64 00 CD 7B 29 90 04 A0 6C 65 74 quand..{)...let 2FAE: 74 72 65 20 63 6F 72 72 65 63 74 65 00 C9 CD 7B tre correcte...{ 2FBE: 29 90 04 80 4D 6F 76 69 65 6E 64 6F 20 6C 61 20 )...Moviendo la 2FCE: 70 61 6C 61 6E 63 61 20 70 61 72 61 00 CD 7B 29 palanca para..{) 2FDE: 90 04 90 63 61 6D 62 69 61 72 20 6C 61 73 20 6C ...cambiar las l 2FEE: 65 74 72 61 73 2C 20 6C 75 65 67 6F 00 CD 7B 29 etras, luego..{) 2FFE: 90 04 A0 61 70 6C 61 73 74 65 20 65 6C 20 62 6F ...aplaste el bo 300E: 74 6F 6E 20 64 65 20 64 69 73 70 61 72 6F 00 CD ton de disparo.. 301E: 7B 29 90 04 B0 70 61 72 61 20 72 65 74 65 6E 65 {)...para retene 302E: 72 6C 61 73 2E 00 C9 00 3E 41 5D 51 5D 41 3E 00 rlas....>A]Q]A>. 303E: 00 nop 303F: 00 nop 3040: 00 nop 3041: 00 nop 3042: 00 nop 3043: 00 nop 3044: 00 nop 3045: 00 nop 3046: 00 nop 3047: 10 10 djnz $3059 3049: 10 10 djnz $305B 304B: 10 10 djnz $305D 304D: 10 00 djnz $304F 304F: 10 14 djnz $3065 3051: 14 inc d 3052: 14 inc d 3053: 00 nop 3054: 00 nop 3055: 00 nop 3056: 00 nop 3057: 00 nop 3058: 00 nop 3059: 14 inc d 305A: 14 inc d 305B: 14 inc d 305C: 7F ld a,a 305D: 14 inc d 305E: 7F ld a,a 305F: 14 inc d 3060: 14 inc d 3061: 14 inc d 3062: 14 inc d 3063: 7F ld a,a 3064: 54 ld d,h 3065: 54 ld d,h 3066: 7F ld a,a 3067: 15 dec d 3068: 15 dec d 3069: 7F ld a,a 306A: 14 inc d 306B: 20 51 jr nz,$30BE 306D: 22 04 08 ld ($0804),hl 3070: 10 22 djnz $3094 3072: 45 ld b,l 3073: 02 ld (bc),a 3074: 00 nop 3075: 18 24 jr $309B 3077: 28 10 jr z,$3089 3079: 29 add hl,hl 307A: 46 ld b,(hl) 307B: 46 ld b,(hl) 307C: 39 add hl,sp 307D: 08 ex af,af' 307E: 08 ex af,af' 307F: 08 ex af,af' 3080: 00 nop 3081: 00 nop 3082: 00 nop 3083: 00 nop 3084: 00 nop 3085: 00 nop 3086: 04 inc b 3087: 08 ex af,af' 3088: 10 10 djnz $309A 308A: 10 10 djnz $309C 308C: 10 08 djnz $3096 308E: 04 inc b 308F: 10 08 djnz $3099 3091: 04 inc b 3092: 04 inc b 3093: 04 inc b 3094: 04 inc b 3095: 04 inc b 3096: 08 ex af,af' 3097: 10 00 djnz $3099 3099: 00 nop 309A: 08 ex af,af' 309B: 2A 1C 1C ld hl,($1C1C) 309E: 2A 08 00 ld hl,($0008) 30A1: 00 nop 30A2: 00 nop 30A3: 08 ex af,af' 30A4: 08 ex af,af' 30A5: 3E 08 ld a,$08 30A7: 08 ex af,af' 30A8: 00 nop 30A9: 00 nop 30AA: 80 add a,b 30AB: 00 nop 30AC: 00 nop 30AD: 00 nop 30AE: 18 18 jr $30C8 30B0: 08 ex af,af' 30B1: 10 00 djnz $30B3 30B3: 00 nop 30B4: 00 nop 30B5: 00 nop 30B6: 00 nop 30B7: 3E 00 ld a,$00 30B9: 00 nop 30BA: 00 nop 30BB: 00 nop 30BC: 00 nop 30BD: 00 nop 30BE: 00 nop 30BF: 00 nop 30C0: 00 nop 30C1: 00 nop 30C2: 00 nop 30C3: 18 18 jr $30DD 30C5: 00 nop 30C6: 00 nop 30C7: 01 02 04 ld bc,$0402 30CA: 08 ex af,af' 30CB: 10 20 djnz $30ED 30CD: 40 ld b,b ; ; Character "0" ; 30CE: 1C 22 41 41 41 41 41 22 1C ; ; Character "1" ; 30D7: 08 18 08 08 08 08 08 08 1C ; ; Character "2" ; 30E0: 3E 41 01 01 3E 40 40 40 7F ; ; Character "3" ; 30E9: 3E 41 01 01 1E 01 01 41 3E ; ; Character "4" ; 30F2: 02 06 0A 12 22 7F 02 02 02 ; ; Character "5" ; 30FB: 7F 40 40 40 7E 01 01 41 3E ; ; Character "6" ; 3104: 3E 41 40 40 7E 41 41 41 3E ; ; Character "7" ; 310D: 7F 01 02 02 04 04 08 08 08 ; ; Character "8" ; 3116: 3E 41 41 41 3E 41 41 41 3E ; ; Character "9" ; 311F: 3E 41 41 41 3F 01 01 41 3E ; ; Character ":" ; 3128: 00 00 00 18 18 00 00 18 18 ; ; Character ";" ; 3131: 98 18 00 00 18 18 08 10 00 ; ; Character "<" ; 313A: 02 04 08 10 20 10 08 04 02 ; ; Character "=" ; 3143: 00 00 00 3E 00 3E 00 00 00 ; ; Character ">" ; 314C: 20 10 08 04 02 04 08 10 20 ; ; Character "?" ; 3155: 1C 22 02 02 04 08 08 00 08 ; ; Character "@" ; 315E: 3E 41 3160: 4F 3161: 49 3162: 49 3163: 4F 3164: 40 3165: 40 3166: 3F 3167: 3E 41 3169: 41 316A: 41 316B: 7F 316C: 41 316D: 41 316E: 41 316F: 41 3170: 7E 3171: 41 3172: 41 3173: 41 3174: 7E 3175: 41 3176: 41 3177: 41 3178: 7E 3179: 3E 41 317B: 40 317C: 40 317D: 40 317E: 40 317F: 40 3180: 41 3181: 3E 7E 3183: 41 3184: 41 3185: 41 3186: 41 3187: 41 3188: 41 3189: 41 318A: 7E 318B: 7F 318C: 40 318D: 40 318E: 40 318F: 7C 3190: 40 3191: 40 3192: 40 3193: 7F 3194: 7F 3195: 40 3196: 40 3197: 40 3198: 7C 3199: 40 319A: 40 319B: 40 319C: 40 319D: 3E 41 319F: 40 31A0: 40 31A1: 47 31A2: 41 31A3: 41 31A4: 41 31A5: 3F 31A6: 41 31A7: 41 31A8: 41 31A9: 41 31AA: 7F 31AB: 41 31AC: 41 31AD: 41 31AE: 41 31AF: 1C 31B0: 08 31B1: 08 31B2: 08 31B3: 08 31B4: 08 31B5: 08 31B6: 08 31B7: 1C 31B8: 01 01 01 31BB: 01 01 01 31BE: 01 41 3E 31C1: 41 31C2: 42 31C3: 44 31C4: 48 31C5: 50 31C6: 68 31C7: 44 31C8: 42 31C9: 41 31CA: 40 31CB: 40 31CC: 40 31CD: 40 31CE: 40 31CF: 40 31D0: 40 31D1: 40 31D2: 7F 31D3: 41 31D4: 63 31D5: 55 31D6: 49 31D7: 41 31D8: 41 31D9: 41 31DA: 41 31DB: 41 31DC: 41 31DD: 61 31DE: 51 31DF: 49 31E0: 45 31E1: 43 31E2: 41 31E3: 41 31E4: 41 31E5: 3E 41 31E7: 41 31E8: 41 31E9: 41 31EA: 41 31EB: 41 31EC: 41 31ED: 3E 7E 31EF: 41 31F0: 41 31F1: 41 31F2: 7E 31F3: 40 31F4: 40 31F5: 40 31F6: 40 31F7: 3E 41 31F9: 41 31FA: 41 31FB: 41 31FC: 41 31FD: 45 31FE: 42 31FF: 3D 3200: 7E 3201: 41 3202: 41 3203: 41 3204: 7E 3205: 48 3206: 44 3207: 42 3208: 41 3209: 3E 41 320B: 40 320C: 40 320D: 3E 01 320F: 01 41 3E 3212: 7F 3213: 08 3214: 08 3215: 08 3216: 08 3217: 08 3218: 08 3219: 08 321A: 08 321B: 41 321C: 41 321D: 41 321E: 41 321F: 41 3220: 41 3221: 41 3222: 41 3223: 3E 41 3225: 41 3226: 41 3227: 22 22 14 322A: 14 322B: 08 322C: 08 322D: 41 322E: 41 322F: 41 3230: 41 3231: 41 3232: 49 3233: 55 3234: 63 3235: 41 3236: 41 3237: 41 3238: 22 14 08 323B: 14 323C: 22 41 41 323F: 41 3240: 41 3241: 22 14 08 3244: 08 3245: 08 3246: 08 3247: 08 3248: 7F 3249: 01 02 04 324C: 08 324D: 10 20 324F: 40 3250: 7F 3251: 3C 3252: 20 20 3254: 20 20 3256: 20 20 3258: 20 3C 325A: 00 325B: 00 325C: 40 325D: 20 10 325F: 08 3260: 04 3261: 02 3262: 01 3C 04 3265: 04 3266: 04 3267: 04 3268: 04 3269: 04 326A: 04 326B: 3C 326C: 08 326D: 14 326E: 22 41 00 3271: 00 3272: 00 3273: 00 3274: 00 3275: 80 3276: 00 3277: 00 3278: 00 3279: 00 327A: 00 327B: FF 327C: 00 327D: 00 327E: 18 18 3280: 10 08 3282: 00 3283: 00 3284: 00 3285: 00 3286: 00 ; ; Character "a" ; 3287: 00 00 00 3A 46 42 42 46 3A ; ; Character "b" ; 3290: 40 40 40 5C 62 42 42 62 5C ; ; Character "c" ; 3299: 00 00 00 3C 42 40 40 42 3C ; ; Character "d" ; 32A2: 02 02 02 3A 46 42 42 46 3A ; ; Character "e" ; 32AB: 00 00 00 3C 42 7E 40 40 3C ; ; Character "f" ; 32B4: 0C 12 10 10 38 10 10 10 10 ; ; Character "g" ; 32BD: BA 46 42 42 46 3A 02 42 3C ; ; Character "h" ; 32C6: 40 40 40 7C 42 42 42 42 42 ; ; Character "i" ; 32CF: 00 08 00 08 08 08 08 08 08 ; ; Character "j" ; 32D8: 84 04 04 04 04 04 04 44 38 ; ; Character "k" ; 32E1: 40 40 40 44 48 50 70 48 44 ; ; Character "l" ; 32EA: 10 10 10 10 10 10 10 10 10 ; ; Character "m" ; 32F3: 00 00 00 76 49 49 49 49 49 ; ; Character "n" ; 32FC: 00 00 00 7C 42 42 42 42 42 ; ; Character "o" ; 3305: 00 00 00 3C 42 42 42 42 3C ; ; Character "p" ; 330E: DC 62 42 42 62 5C 40 40 40 ; ; Character "q" ; 3317: BA 46 42 42 46 3A 02 02 02 ; ; Character "r" ; 3320: 00 00 00 5C 62 40 40 40 40 ; ; Character "s" ; 3329: 00 00 00 3C 42 30 0C 42 3C ; ; Character "t" ; 3332: 00 10 10 7C 10 10 10 10 10 ; ; Character "u" ; 333B: 00 00 00 42 42 42 42 42 3C ; ; Character "v" ; 3344: 00 00 00 44 44 44 44 28 10 ; ; Character "w" ; 334D: 00 00 00 41 41 41 49 49 36 ; ; Character "x" ; 3356: 00 00 00 42 24 18 18 24 42 ; ; Character "y" ; 335F: C2 42 42 42 46 3A 02 42 3C ; ; Character "z" ; 3368: 00 00 00 7E 04 08 10 20 7E ; ; Character "{" ; 3371: 0C 10 10 10 20 10 10 10 0C ; ; Character "|" ; 337A: 08 08 08 00 00 08 08 08 00 ; ; Character "}" ; 3383: 18 04 04 04 02 04 04 04 18 ; ; Character "~" ; 338C: 30 49 06 00 00 00 00 00 00 3395: 55 ld d,l 3396: 2A 55 2A ld hl,($2A55) 3399: 55 ld d,l 339A: 2A 55 2A ld hl,($2A55) 339D: 55 ld d,l 339E: 08 ex af,af' 339F: 00 nop 33A0: 1C inc e 33A1: 2A 08 08 ld hl,($0808) 33A4: 14 inc d 33A5: 22 00 21 ld ($2100),hl 33A8: 89 adc a,c 33A9: 08 ex af,af' 33AA: F5 push af 33AB: 3E FF ld a,$FF 33AD: BE cp (hl) 33AE: 38 09 jr c,$33B9 33B0: D3 4D out ($4D),a ; write to nmi_disable_r 33B2: 77 ld (hl),a 33B3: 21 29 34 ld hl,$3429 33B6: 22 85 08 ld ($0885),hl 33B9: F1 pop af 33BA: D3 4C out ($4C),a ; write to nmi_enable_r 33BC: C9 ret ; ; Play Bolt shooting sound. ; ; See also: START macro contained within NMI.ASM in Frenzy's source code. SFIRE: 33BD: 21 89 08 ld hl,$0889 ; load HL with address of PC1 33C0: F5 push af 33C1: 3E 00 ld a,$00 ; priority of bolt sound 33C3: BE cp (hl) ; compare with current sound's priority 33C4: 38 09 jr c,$33CF ; if 0 < current sound priority, don't play sound, goto $33CF 33C6: D3 4D out ($4D),a ; write to nmi_disable_r 33C8: 77 ld (hl),a ; set current sound priority 33C9: 21 D3 33 ld hl,$33D3 33CC: 22 85 08 ld ($0885),hl 33CF: F1 pop af 33D0: D3 4C out ($4C),a ; write to nmi_enable_r 33D2: C9 ret 33D3: 0E 04 ld c,$04 33D5: 81 add a,c 33D6: 08 ex af,af' 33D7: 00 nop 33D8: 05 dec b 33D9: 06 06 ld b,$06 33DB: 0E 03 ld c,$03 33DD: 78 ld a,b 33DE: 08 ex af,af' 33DF: 92 sub d 33E0: 92 sub d 33E1: 92 sub d 33E2: 0F rrca 33E3: 03 inc bc 33E4: 7B ld a,e 33E5: 08 ex af,af' 33E6: 32 00 32 ld ($3200),a 33E9: 00 nop 33EA: 32 00 06 ld ($0600),a 33ED: 04 inc b 33EE: 95 sub l 33EF: 08 ex af,af' 33F0: 06 32 ld b,$32 33F2: 93 sub e 33F3: 08 ex af,af' 33F4: 01 0B 0F ld bc,$0F0B 33F7: 00 nop 33F8: 7B ld a,e 33F9: 08 ex af,af' 33FA: 0B dec bc 33FB: 11 00 7D ld de,$7D00 33FE: 08 ex af,af' 33FF: 0B dec bc 3400: 10 00 djnz $3402 3402: 7F ld a,a 3403: 08 ex af,af' 3404: 03 inc bc 3405: 93 sub e 3406: 08 ex af,af' 3407: EC 07 32 call pe,$3207 340A: 00 nop 340B: 7B ld a,e 340C: 08 ex af,af' 340D: 03 inc bc 340E: 95 sub l 340F: 08 ex af,af' 3410: DF rst $18 3411: 06 FA ld b,$FA 3413: 93 sub e 3414: 08 ex af,af' 3415: 01 0B 0A ld bc,$0A0B 3418: 00 nop 3419: 7B ld a,e 341A: 08 ex af,af' 341B: 0B dec bc 341C: 0D dec c 341D: 00 nop 341E: 7D ld a,l 341F: 08 ex af,af' 3420: 0B dec bc 3421: 0F rrca 3422: 00 nop 3423: 7F ld a,a 3424: 08 ex af,af' 3425: 03 inc bc 3426: 93 sub e 3427: 08 ex af,af' 3428: EC 0E 03 call pe,$030E 342B: 78 ld a,b 342C: 08 ex af,af' 342D: 00 nop 342E: 00 nop 342F: 00 nop 3430: 0E 04 ld c,$04 3432: 82 add a,d 3433: 08 ex af,af' 3434: 00 nop 3435: 00 nop 3436: 00 nop 3437: 00 nop 3438: 00 nop ; ; Play the "player being electrocuted" sounds. ; ; See also: START macro in NMI.ASM within Frenzy's source code. SFRY: 3439: 21 89 08 ld hl,$0889 ; load HL with address of PC1 343C: F5 push af 343D: 3E 03 ld a,$03 343F: BE cp (hl) 3440: 38 09 jr c,$344B 3442: D3 4D out ($4D),a ; write to nmi_disable_r 3444: 77 ld (hl),a 3445: 21 4F 34 ld hl,$344F 3448: 22 85 08 ld ($0885),hl ; set PC0. 344B: F1 pop af 344C: D3 4C out ($4C),a ; write to nmi_enable_r 344E: C9 ret 344F: 0E 04 ld c,$04 3451: 81 add a,c 3452: 08 ex af,af' 3453: 00 nop 3454: 06 07 ld b,$07 3456: 07 rlca 3457: 0E 03 ld c,$03 3459: 78 ld a,b 345A: 08 ex af,af' 345B: 90 sub b 345C: 90 sub b 345D: 90 sub b 345E: 06 10 ld b,$10 3460: 93 sub e 3461: 08 ex af,af' 3462: 07 rlca 3463: AC xor h 3464: 00 nop 3465: 7B ld a,e 3466: 08 ex af,af' 3467: 0F rrca 3468: 02 ld (bc),a 3469: 7D ld a,l 346A: 08 ex af,af' 346B: 14 inc d 346C: 00 nop 346D: 0A ld a,(bc) 346E: 00 nop 346F: 06 19 ld b,$19 3471: 95 sub l 3472: 08 ex af,af' 3473: 01 0A 05 ld bc,$050A 3476: 7D ld a,l 3477: 08 ex af,af' 3478: 0A ld a,(bc) 3479: 1E 7F ld e,$7F 347B: 08 ex af,af' 347C: 03 inc bc 347D: 95 sub l 347E: 08 ex af,af' 347F: F3 di 3480: 0A ld a,(bc) 3481: FC 7B 08 call m,$087B 3484: 03 inc bc 3485: 93 sub e 3486: 08 ex af,af' 3487: DF rst $18 3488: 02 ld (bc),a 3489: 9F sbc a,a ; ; Play sound of robot exploding. ; ; See also: START macro contained within NMI.ASM in Frenzy's source code. ; SBLAM: 348A: 21 89 08 ld hl,$0889 348D: F5 push af 348E: 3E 01 ld a,$01 3490: BE cp (hl) 3491: 38 09 jr c,$349C 3493: D3 4D out ($4D),a ; write to nmi_disable_r 3495: 77 ld (hl),a 3496: 21 A0 34 ld hl,$34A0 3499: 22 85 08 ld ($0885),hl 349C: F1 pop af 349D: D3 4C out ($4C),a ; write to nmi_enable_r 349F: C9 ret 34A0: 0E 03 ld c,$03 34A2: 78 ld a,b 34A3: 08 ex af,af' 34A4: 82 add a,d 34A5: 80 add a,b 34A6: 80 add a,b 34A7: 0E 04 ld c,$04 34A9: 81 add a,c 34AA: 08 ex af,af' 34AB: 03 inc bc 34AC: 07 rlca 34AD: 07 rlca 34AE: 07 rlca 34AF: 0F rrca 34B0: 03 inc bc 34B1: 7B ld a,e 34B2: 08 ex af,af' 34B3: 01 00 01 ld bc,$0100 34B6: 00 nop 34B7: 05 dec b 34B8: 00 nop 34B9: 01 0E 03 ld bc,$030E 34BC: 78 ld a,b 34BD: 08 ex af,af' 34BE: 92 sub d 34BF: 90 sub b 34C0: 90 sub b 34C1: 06 37 ld b,$37 34C3: 95 sub l 34C4: 08 ex af,af' 34C5: 06 06 ld b,$06 34C7: 93 sub e 34C8: 08 ex af,af' 34C9: 01 03 93 ld bc,$9303 34CC: 08 ex af,af' 34CD: FB ei 34CE: 0B dec bc 34CF: 01 00 7B ld bc,$7B00 34D2: 08 ex af,af' 34D3: 03 inc bc 34D4: 95 sub l 34D5: 08 ex af,af' 34D6: EE 0E xor $0E 34D8: 03 inc bc 34D9: 78 ld a,b 34DA: 08 ex af,af' 34DB: 00 nop 34DC: 00 nop 34DD: 00 nop 34DE: 0E 04 ld c,$04 34E0: 81 add a,c 34E1: 08 ex af,af' 34E2: 00 nop 34E3: 00 nop 34E4: 00 nop 34E5: 00 nop 34E6: 00 nop ; ; Robot shoot sound. ; ; See also: SRFIRE# in NMI.ASM within Frenzy's source code. ; SRFIRE#: 34E7: 21 89 08 ld hl,$0889 34EA: F5 push af 34EB: 3E 01 ld a,$01 34ED: BE cp (hl) 34EE: 38 09 jr c,$34F9 34F0: D3 4D out ($4D),a ; write to nmi_disable_r 34F2: 77 ld (hl),a 34F3: 21 FD 34 ld hl,$34FD 34F6: 22 85 08 ld ($0885),hl 34F9: F1 pop af 34FA: D3 4C out ($4C),a ; write to nmi_enable_r 34FC: C9 ret 34FD: 0E 03 ld c,$03 34FF: 78 ld a,b 3500: 08 ex af,af' 3501: 92 sub d 3502: 92 sub d 3503: 92 sub d 3504: 0E 04 ld c,$04 3506: 81 add a,c 3507: 08 ex af,af' 3508: 00 nop 3509: 06 06 ld b,$06 350B: 07 rlca 350C: 0F rrca 350D: 03 inc bc 350E: 7B ld a,e 350F: 08 ex af,af' 3510: 14 inc d 3511: 00 nop 3512: 2D dec l 3513: 00 nop 3514: 5A ld e,d 3515: 00 nop 3516: 06 04 ld b,$04 3518: 95 sub l 3519: 08 ex af,af' 351A: 06 50 ld b,$50 351C: 93 sub e 351D: 08 ex af,af' 351E: 01 0B 08 ld bc,$080B 3521: 00 nop 3522: 7B ld a,e 3523: 08 ex af,af' 3524: 0B dec bc 3525: 11 00 7D ld de,$7D00 3528: 08 ex af,af' 3529: 0B dec bc 352A: 2F cpl 352B: 00 nop 352C: 7F ld a,a 352D: 08 ex af,af' 352E: 03 inc bc 352F: 93 sub e 3530: 08 ex af,af' 3531: EC 03 95 call pe,$9503 3534: 08 ex af,af' 3535: E4 02 9F call po,$9F02 3538: 21 89 08 ld hl,$0889 353B: F5 push af 353C: 3E 02 ld a,$02 353E: BE cp (hl) 353F: 38 09 jr c,$354A 3541: D3 4D out ($4D),a ; write to nmi_disable_r 3543: 77 ld (hl),a 3544: 21 4E 35 ld hl,$354E 3547: 22 85 08 ld ($0885),hl 354A: F1 pop af 354B: D3 4C out ($4C),a ; write to nmi_enable_r 354D: C9 ret 354E: 0E 04 ld c,$04 3550: 81 add a,c 3551: 08 ex af,af' 3552: 00 nop 3553: 07 rlca 3554: 07 rlca 3555: 07 rlca 3556: 0E 03 ld c,$03 3558: 78 ld a,b 3559: 08 ex af,af' 355A: 92 sub d 355B: 92 sub d 355C: 92 sub d 355D: 0F rrca 355E: 03 inc bc 355F: 7B ld a,e 3560: 08 ex af,af' 3561: C8 ret z 3562: 00 nop 3563: 3C inc a 3564: 00 nop 3565: 28 00 jr z,$3567 3567: 06 14 ld b,$14 3569: 95 sub l 356A: 08 ex af,af' 356B: 06 14 ld b,$14 356D: 93 sub e 356E: 08 ex af,af' 356F: 01 0B 14 ld bc,$140B 3572: 00 nop 3573: 7B ld a,e 3574: 08 ex af,af' 3575: 0B dec bc 3576: 06 00 ld b,$00 3578: 7D ld a,l 3579: 08 ex af,af' 357A: 0B dec bc 357B: 04 inc b 357C: 00 nop 357D: 7F ld a,a 357E: 08 ex af,af' 357F: 03 inc bc 3580: 93 sub e 3581: 08 ex af,af' 3582: EC 06 14 call pe,$1406 3585: 93 sub e 3586: 08 ex af,af' 3587: 01 0B EC ld bc,$EC0B 358A: FF rst $38 358B: 7B ld a,e 358C: 08 ex af,af' 358D: 0B dec bc 358E: FA FF 7D jp m,$7DFF 3591: 08 ex af,af' 3592: 0B dec bc 3593: FC FF 7F call m,$7FFF 3596: 08 ex af,af' 3597: 03 inc bc 3598: 93 sub e 3599: 08 ex af,af' 359A: EC 03 95 call pe,$9503 359D: 08 ex af,af' 359E: CC 0E 03 call z,$030E 35A1: 78 ld a,b 35A2: 08 ex af,af' 35A3: 00 nop 35A4: 00 nop 35A5: 00 nop 35A6: 0E 04 ld c,$04 35A8: 81 add a,c 35A9: 08 ex af,af' 35AA: 00 nop 35AB: 00 nop 35AC: 00 nop 35AD: 00 nop 35AE: 00 nop ; ; Set colour attributes for the screen ; ; SET_COLOUR_ATTRS_35AF: 35AF: AF xor a 35B0: 32 79 43 ld ($4379),a ; set FLIP to upright cabinet mode 35B3: 3E 1E ld a,$1E 35B5: 00 nop 35B6: 00 nop 35B7: CD 57 36 call $3657 ; call COLOUR_FILL 35BA: 00 00 05 20 AA 35BF: CD 57 36 call $3657 ; call COLOUR_FILL 35C2: A0 00 29 20 11 35C7: CD 57 36 call $3657 ; call COLOUR_FILL 35CA: A0 00 29 09 99 35CF: CD 57 36 call $3657 ; call COLOUR_FILL 35D2: A9 00 29 08 BB 35D7: CD 57 36 call $3657 ; call COLOUR_FILL 35DA: B0 00 29 10 55 35DF: CD 57 36 call $3657 ; call COLOUR_FILL 35E2: C0 05 0A 20 77 35E7: CD 57 36 call $3657 ; call COLOUR_FILL 35EA: 80 06 04 0A AA 35EF: CD 57 36 call $3657 ; call COLOUR_FILL 35F2: 96 06 04 0A DD 35F7: C9 ret COLOUR_FILL_WHITE: 35F8: CD 57 36 call $3657 ; call COLOUR_FILL 35FB: 00 00 38 20 FF 3600: C9 ret 3601: CD 57 36 call $3657 ; call COLOUR_FILL 3604: E0 05 04 20 33 3609: C9 ret 360A: CD 57 36 call $3657 ; call COLOUR_FILL 360D: E0 05 04 20 99 3612: C9 ret 3613: CD 57 36 call $3657 ; call COLOUR_FILL 3616: E0 05 04 20 66 361B: C9 ret 361C: CD 57 36 call $3657 ; call COLOUR_FILL 361F: 00 00 08 20 BB 3624: CD 57 36 call $3657 ; call COLOUR_FILL 3627: 00 01 10 20 66 362C: CD 57 36 call $3657 ; call COLOUR_FILL 362F: 00 03 04 20 FF 3634: CD 57 36 call $3657 ; call COLOUR_FILL 3637: 80 03 1C 20 AA 363C: C9 ret 363D: CD 57 36 call $3657 ; call COLOUR_FILL 3640: 00 00 2F 20 CC 3645: CD 57 36 call $3657 ; call COLOUR_FILL 3648: E0 05 09 20 AA 364D: C9 ret 364E: CD 57 36 call $3657 ; call COLOUR_FILL 3651: 00 00 34 20 44 3656: C9 ret ; ; Updates colour attribute RAM such that fills a rectangular area of screen with a specified colour. ; Or, in plain English - rectangular colour fill! ; ; Expects: ; Return address on stack to point to 5 bytes: ; Byte 0: LSB of *offset into colour RAM ; Byte 1: MSB of offset into colour RAM ; Byte 2: number of lines ; Byte 3: width in bytes ; Byte 4: colour ; ; Remarks: ; See also C.BOX in color.asm within Frenzy's source code. COLOUR_FILL: 3657: E1 pop hl ; get parameter address 3658: 5E ld e,(hl) ; Read 1st parameter (offset LSB) 3659: 23 inc hl 365A: 56 ld d,(hl) ; Read 2nd parameter (offset MSB). DE now offset into colour lookup RAM 365B: 23 inc hl 365C: E5 push hl ; save address of 3rd parameter byte on stack 365D: 3A 79 43 ld a,($4379) ; read FLIP 3660: B7 or a 3661: 20 06 jr nz,$3669 ; if cocktail setup goto $3669 ; upright cabinet 3663: 21 00 81 ld hl,$8100 ; load HL with address in colour lookup RAM 3666: 19 add hl,de 3667: 18 05 jr $366E ; cocktail cabinet 3669: 21 FF 87 ld hl,$87FF 366C: ED 52 sbc hl,de ; both cabinet types 366E: EB ex de,hl 366F: E1 pop hl ; restore address of 3rd parameter byte from stack 3670: 4E ld c,(hl) ; read 3rd parameter (number of lines) 3671: 23 inc hl 3672: 08 ex af,af' 3673: 7E ld a,(hl) ; read 4th parameter (width in bytes) 3674: 23 inc hl 3675: 08 ex af,af' 3676: B7 or a ; set zero flag if upright cabinet 3677: 7E ld a,(hl) ; read 5th parameter (colour) byte 3678: 23 inc hl 3679: E5 push hl 367A: EB ex de,hl 367B: 20 11 jr nz,$368E ; upright cabinet ; HL = start of colour attribute RAM to fill ; A = colour to fill cells with ; A' = count of columns to fill ; C = count of rows to fill 367D: 11 20 00 ld de,$0020 ; sizeof a row of colour attributes 3680: 08 ex af,af' 3681: 47 ld b,a ; load b with count of attribute cells to fill 3682: 08 ex af,af' 3683: E5 push hl 3684: 77 ld (hl),a ; write colour to cell 3685: 23 inc hl 3686: 10 FC djnz $3684 ; repeat until all cells for row are coloured 3688: E1 pop hl 3689: 19 add hl,de ; bump HL 368A: 0D dec c 368B: 20 F3 jr nz,$3680 ; repeat until all rows done 368D: C9 ret ; cocktail cabinet 368E: 11 E0 FF ld de,$FFE0 3691: 08 ex af,af' 3692: 47 ld b,a 3693: 08 ex af,af' 3694: E5 push hl 3695: 77 ld (hl),a 3696: 2B dec hl 3697: 10 FC djnz $3695 3699: E1 pop hl 369A: 19 add hl,de 369B: 0D dec c 369C: 20 F3 jr nz,$3691 369E: C9 ret 369F: CD 57 36 call $3657 ; call COLOUR_FILL 36A2: 80 06 04 20 77 36A7: CD E7 35 call $35E7 36AA: CD 34 23 call $2334 ; call GET_PLAYER_SCORE_PTR 36AD: EB ex de,hl 36AE: 01 05 00 ld bc,$0005 36B1: 13 inc de 36B2: 1A ld a,(de) 36B3: 08 ex af,af' 36B4: 1B dec de 36B5: 1A ld a,(de) 36B6: B7 or a 36B7: 21 94 37 ld hl,$3794 36BA: 28 0F jr z,$36CB 36BC: E6 0F and $0F 36BE: 67 ld h,a 36BF: 08 ex af,af' 36C0: E6 F0 and $F0 36C2: B4 or h 36C3: 07 rlca 36C4: 07 rlca 36C5: 07 rlca 36C6: 07 rlca 36C7: 21 BC 37 ld hl,$37BC 36CA: 08 ex af,af' 36CB: 08 ex af,af' 36CC: BE cp (hl) 36CD: 38 06 jr c,$36D5 36CF: 08 ex af,af' 36D0: 09 add hl,bc 36D1: 7E ld a,(hl) 36D2: B7 or a 36D3: 20 F6 jr nz,$36CB 36D5: 23 inc hl 36D6: 7E ld a,(hl) 36D7: 23 inc hl 36D8: 32 4B 43 ld ($434B),a ; set RBOLTS 36DB: 7E ld a,(hl) 36DC: 23 inc hl 36DD: 32 7A 43 ld ($437A),a 36E0: 7E ld a,(hl) 36E1: 23 inc hl 36E2: 32 4D 43 ld ($434D),a ; set RWAIT 36E5: 4E ld c,(hl) 36E6: 3A 79 43 ld a,($4379) ; read FLIP 36E9: B7 or a ; set zero flag if upright cabinet 36EA: DD 21 00 81 ld ix,$8100 36EE: 21 00 44 ld hl,$4400 ; load HL with address of screen image RAM 36F1: 28 07 jr z,$36FA ; cocktail cabinet 36F3: DD 21 80 81 ld ix,$8180 36F7: 21 00 46 ld hl,$4600 ; both cocktail and upright 36FA: 3E 34 ld a,$34 36FC: 08 ex af,af' 36FD: 06 20 ld b,$20 36FF: 7E ld a,(hl) 3700: 23 inc hl 3701: 5F ld e,a 3702: E6 44 and $44 3704: 57 ld d,a 3705: 7B ld a,e 3706: 2F cpl 3707: A1 and c 3708: B2 or d 3709: DD 77 00 ld (ix+$00),a 370C: DD 23 inc ix 370E: 10 EF djnz $36FF 3710: 11 60 00 ld de,$0060 3713: 19 add hl,de 3714: 08 ex af,af' 3715: 3D dec a 3716: 20 E4 jr nz,$36FC 3718: C9 ret ; ; Restore original colour attributes of maze at player position ; ; Expects: ; HL = pointer to VECTOR struct for player ; ; Remarks: See UNCMAN within color.asm in Frenzy's source code. ; UNCOLOUR_MAN: 3719: CB 5E bit 3,(hl) ; test BLANK bit 371B: CA 3C 37 jp z,$373C ; if not set, jump to COLOUR_MAN 371E: CB 9E res 3,(hl) 3720: E5 push hl ; Restore colour attributes 3721: 2A 40 09 ld hl,($0940) ; read PLAYER_COLOUR_ADDR 3724: 11 42 09 ld de,$0942 ; load DE with address of PLAYER_COLOUR_SAVE 3727: 3E 05 ld a,$05 ; 5 attribute rows high 3729: 08 ex af,af' ; Use alternate register AF' for reading from PLAYER_COLOUR_SAVE buffer 372A: 06 02 ld b,$02 ; 2 attribute columns wide 372C: 1A ld a,(de) ; read from PLAYER_COLOUR_SAVE buffer 372D: 13 inc de 372E: 77 ld (hl),a ; and write to attributes 372F: 23 inc hl 3730: 10 FA djnz $372C ; repeat until all columns done 3732: 01 1E 00 ld bc,$001E 3735: 09 add hl,bc ; bump HL to point to attribute row below 3736: 08 ex af,af' ; Now A = number of rows left to fill with colour 3737: 3D dec a ; decrement counter 3738: C2 29 37 jp nz,$3729 ; if not all rows done, goto $3729 373B: E1 pop hl ; ; Colour the player sprite. ; ; Expects: ; HL = pointer to player's VECTOR structure ; ; See also: COLMAN in color.asm within Frenzy's source code. ; COLOUR_MAN: 373C: CB 66 bit 4,(hl) ; test STATUS_BIT_COLOR bit in VECTOR.Status 373E: C8 ret z ; if the flag isn't set to colour the player sprite, exit 373F: CB DE set 3,(hl) ; set STATUS_BIT_BLANK bit in VECTOR.Status 3741: E5 push hl 3742: 11 07 00 ld de,$0007 3745: 19 add hl,de ; bump HL to point to VECTOR P.X 3746: 5E ld e,(hl) ; E = man's X position on screen 3747: 23 inc hl 3748: 23 inc hl ; bump HL to point to VECTOR.P.Y 3749: 3A 79 43 ld a,($4379) ; read FLIP 374C: B7 or a ; is upright cabinet? 374D: 7E ld a,(hl) ; A = man's Y position on screen 374E: 28 0A jr z,$375A ; if upright cabinet goto $375A ; for cocktail cabinet only. 3750: ED 44 neg 3752: C6 D0 add a,$D0 3754: 08 ex af,af' 3755: 3E F7 ld a,$F7 3757: 93 sub e 3758: 5F ld e,a 3759: 08 ex af,af' ; for both upright and cocktail cabinets ; calculate offset into colour attribute RAM. A = Y coordinate of player, E = X coordinate 375A: CB 3F srl a 375C: CB 3F srl a 375E: 67 ld h,a 375F: 6B ld l,e 3760: CB 3C srl h 3762: CB 1D rr l 3764: CB 3C srl h 3766: CB 1D rr l 3768: CB 3C srl h 376A: CB 1D rr l 376C: 01 00 81 ld bc,$8100 ; load BC with address of attribute RAM 376F: 09 add hl,bc ; HL now = address in colour attribute RAM to update 3770: 22 40 09 ld ($0940),hl ; set PLAYER_COLOUR_ADDR 3773: 3A 78 43 ld a,($4378) ; read PLAYER_COLOUR 3776: 11 1E 00 ld de,$001E 3779: FD 21 42 09 ld iy,$0942 ; load IY with address of PLAYER_COLOUR_SAVE 377D: 0E 05 ld c,$05 ; 5 attribute rows high 377F: 06 02 ld b,$02 ; 2 attribute columns wide 3781: 08 ex af,af' 3782: 7E ld a,(hl) ; read from screen attribute RAM 3783: FD 77 00 ld (iy+$00),a ; write to PLAYER_COLOUR_SAVE buffer 3786: FD 23 inc iy 3788: 08 ex af,af' ; Now A = PLAYER_COLOUR 3789: 77 ld (hl),a ; write colour to screen attribute memory 378A: 23 inc hl 378B: 10 F4 djnz $3781 ; repeat until all columns done 378D: 19 add hl,de ; bump HL to point to attribute row below 378E: 0D dec c ; decrement row counter 378F: C2 7F 37 jp nz,$377F ; if not all rows done, goto $377F to do more 3792: E1 pop hl ; restore HL from stack (was pushed @ $3741) 3793: C9 ret 3794: 03 inc bc 3795: 00 nop 3796: 00 nop 3797: 50 ld d,b 3798: 33 inc sp 3799: 15 dec d 379A: 01 00 50 ld bc,$5000 379D: 99 sbc a,c 379E: 30 02 jr nc,$37A2 37A0: 00 nop 37A1: 14 inc d 37A2: 66 ld h,(hl) 37A3: 45 ld b,l 37A4: 03 inc bc 37A5: 00 nop 37A6: 0A ld a,(bc) 37A7: AA xor d 37A8: 60 ld h,b 37A9: 04 inc b 37AA: 00 nop 37AB: 0A ld a,(bc) 37AC: 55 ld d,l 37AD: 75 ld (hl),l 37AE: 05 dec b 37AF: 00 nop 37B0: 0F rrca 37B1: BB cp e 37B2: 90 sub b 37B3: 01 01 3C ld bc,$3C01 37B6: FF rst $38 37B7: 00 nop 37B8: 01 01 32 ld bc,$3201 37BB: FF rst $38 37BC: 10 01 djnz $37BF 37BE: 01 2D FF ld bc,$FF2D 37C1: 11 02 02 ld de,$0202 37C4: 23 inc hl 37C5: 66 ld h,(hl) 37C6: 13 inc de 37C7: 03 inc bc 37C8: 03 inc bc 37C9: 19 add hl,de 37CA: DD db $dd 37CB: 15 dec d 37CC: 04 inc b 37CD: 04 inc b 37CE: 14 inc d 37CF: 77 ld (hl),a 37D0: 17 rla 37D1: 05 dec b 37D2: 05 dec b 37D3: 0F rrca 37D4: 33 inc sp 37D5: 19 add hl,de 37D6: 05 dec b 37D7: 05 dec b 37D8: 0A ld a,(bc) 37D9: 99 sbc a,c 37DA: 00 nop 37DB: 05 dec b 37DC: 05 dec b 37DD: 05 dec b 37DE: EE 81 xor $81 37E0: 94 sub h 37E1: 0C inc c 37E2: 02 ld (bc),a 37E3: AD xor l 37E4: 20 75 jr nz,$385B 37E6: 7A ld a,d 37E7: 0D dec c 37E8: 5F ld e,a 37E9: 40 ld b,b 37EA: 93 sub e 37EB: D5 push de 37EC: 67 ld h,a 37ED: 8A adc a,d 37EE: 49 ld c,c 37EF: 14 inc d 37F0: F5 push af 37F1: 74 ld (hl),h 37F2: CF rst $08 37F3: 80 add a,b 37F4: 21 2B CA ld hl,$CA2B 37F7: CC 2B 3C call z,$3C2B 37FA: 04 inc b 37FB: FB ei 37FC: AB xor e 37FD: 26 F8 ld h,$F8 37FF: 00 nop