; **************************************************************************** ; ; Odyssey II BIOS Disassembly ; =========================== ; ; by Paul Robson ; ; Version 1.0 (26-Nov-1997) ; Version 1.2 (04-Jun-2006) by Rene van den Enden ; ; **************************************************************************** ; ; BIOS ROM Routine Addresses: ; ; $000 Reset 8048 ; $003 External Interrupt ; $007 Timer/Clock Interrupt ; $009 VBlank Interrupt Routine 1 ; $01A VBlank Interrupt Routine 2 (Collision & Clock) ; $044 VBlank Interrupt Routine 3 (Tune) ; $089 RAM to VDC VBlank Copying Check Code ; $0A3 Copying Code ; $0B0 Keyboard Routine ; $0E7 Set up VDC Access ; $0EC Set up RAM Access ; $0F1 Reset ; $11C Display Off ; $127 Display On ; $132 Enable Data Copy next VSYNC ; $13D Get Keystroke ; $14B Character/Colour Translation ; $16B Clear all Characters ; $176 Wait for Interrupt ; $17C Display 2 digit BCD Characters ; $1A2 Start Tune ; $1B0 Up/Down Counter ; $23A Set up Quad Score Characters ; $261 Translate & Copy Character & Colour ; $26A Bit test ; $280 Bit clear ; $28A Bit set ; $293 Random number ; $2C3 Select Game ; $300 Frequency Data ; $328 Tune Data ; $376 Keyboard routine (end) ; $37E Bank switch routines ; $38F Read Joystick ; $3B1 Decode Joystick ; $3CF Divide ; $3DD Multiply ; $3EA Character Write ; ; **************************************************************************** ; ; Vectors in Odyssey II ROM Cartridges. ; ; $400 Restart ; $402 VBlank (External) Interrupt ; $404 Timer/Clock Interrupt ; $406 VBlank Routine Vector (if $402 = JMP $009) ; $408 End of Select Game, A = Selection ; $40A Continuation of VBlank (if $406 = JMP $01A) ; ; **************************************************************************** 0000 : 84 00 jmp 400 ; start the game 0002 : 00 nop 0003 : 84 02 jmp 402 ; external interrupt 0005 : 00 nop 0006 : 00 nop 0007 : 84 04 jmp 404 ; timer/clock interrupt ; **************************************************************************** ; ; External Interrupt is often redirected here, by $0402 = JMP 0009. ; This alters Registers 5 and 6 of the base set. ; It completes by going to $0406 if VBLANK is on, returning otherwise. ; ; **************************************************************************** 0009 : c5 sel rb0 ; back to main bank 000a : ad mov r5,a ; save A in R5 000b : 09 in a,p1 ; read enable/switch status 000c : ae mov r6,a ; save in r6 000d : 14 e7 call 0e7 ; access the VDC 000f : b8 a1 mov r0,a1 ; read $0A1 in VDC 0011 : 80 movx a,@ r0 0012 : 72 18 jb3,18 ; in VSYNC ? 0014 : fe mov a,r6 ; get the old switch status 0015 : 39 outl p1,a ; set the enable/switch status 0016 : fd mov a,r5 ; restore A 0017 : 93 retr ; return from interrupt 0018 : 84 06 jmp 406 ; VSYNC vector ; **************************************************************************** ; ; Vertical Sync Routine. Above routine can ; be directed here by $0406 = JMP 001A. ; ; Registers : 3D = Collision,3E = Clock,3F = Status ; ; 3F bit 7 if set causes copy from RAM to VDC, see later. ; 3F bit 6 if set causes jump to sound routine (JMP 040A), returning otherwise ; ; **************************************************************************** 001a : a5 clr f1 ; Set F1 001b : b5 cpl f1 001c : b9 a2 mov r1,a2 ; R1 = $A2 (Collision) 001e : b8 3d mov r0,3d ; R0 = $3D 0020 : 81 movx a,@ r1 ; A = Collision Register 0021 : a0 mov @ r0,a ; put in R$3D 0022 : 18 inc r0 ; increment R0 (now $3E) 0023 : 10 inc @ r0 ; increment R$3E (Clock) 0024 : f0 mov a,@ r0 0025 : 53 3f anl a,3f ; mask $3E with 00111111 0027 : d3 3c xrl a,3c ; zero now if $3E was 60(dec) 0029 : 96 2f jnz,2f ; if non zero skip 002b : f0 mov a,@ r0 ; wrap it round back to zero 002c : 53 c0 anl a,c0 002e : a0 mov @ r0,a 002f : 18 inc r0 ; look at $3F which is some 0030 : f0 mov a,@ r0 ; sort of status flag 0031 : 37 cpl a 0032 : f2 3a jb7 3a ; if bit 7 of 3F was set 0034 : 37 cpl a ; clear bit 7 0035 : 53 7f anl a,7f 0037 : a0 mov @ r0,a ; update register $3F 0038 : 14 89 call 089 ; do the data copy 003a : b9 3f mov r1,3f ; look at R$3F but bit 6 003c : f1 mov a,@ r1 003d : 37 cpl a 003e : d2 14 jb6 14 ; if its clear, exit 0040 : eb 14 djnz r3 14 ; don't do sound routine yet. 0042 : 84 0a jmp 40a ; call sound routine ; **************************************************************************** ; ; Sound Routine. Continuation by setting $40A to ; jmp $044. - it is unpacking a tune from $0300 ; ; **************************************************************************** 0044 : fc mov a,r4 ; A= R4 (start address of tune) 0045 : e3 movp3 a,@ a ; Read Data Table into A 0046 : a9 mov r1,a ; and R1 [300+R4] 0047 : 1c inc r4 0048 : fc mov a,r4 0049 : e3 movp3 a,@ a ; R2 = [301+R4], R4 inc. 004a : aa mov r2,a 004b : f9 mov a,r1 ; test 300+R4 bits 004c : f2 5c jb7 5c ; bit 7 do the set note data 004e : d2 73 jb6 73 ; bit 6 set the delay & volume 0050 : b2 7d jb5 7d ; bit 5 silence 0052 : 92 84 jb4,84 ; bit 4 tune finished. 0054 : b9 3f mov r1,3f ; bits 4,5,6,7 all clear 0056 : f1 mov a,@ r1 ; turn sound off again 0057 : 53 bf anl a,bf ; clear bit 6 of Reg $3F 0059 : a1 mov @ r1,a 005a : 04 14 jmp 014 ; exit interrupt routine ; *** BIT 7 SET *** 005c : 53 7f anl a,7f ; bit 7 set 005e : ab mov r3,a ; R3 = Value in table 005f : b8 aa mov r0,aa ; R0 = $AA 0061 : 27 clr a 0062 : 90 movx @ r0,a ; Clear ($AA) (sound off) 0063 : b8 a7 mov r0,a7 ; R0 = $A7 0065 : b9 03 mov r1,03 ; R1 = 3 0067 : fa mov a,r2 ; Read value from table 0068 : e3 movp3 a,@ a ; ($300+2nd value) 0069 : 90 movx @ r0,a ; Copying three bytes from 006a : 18 inc r0 ; 2nd value in table to 006b : 1a inc r2 ; $A7,$A8,$A9 006c : e9 67 djnz r1 67 006e : fa mov a,r2 ; 2nd Value = (300+2nd Value) 006f : e3 movp3 a,@ a ; e.g. the next one 0070 : aa mov r2,a ; plonk it in R2 0071 : 04 76 jmp 076 ; *** BIT 6 SET *** 0073 : 53 3f anl a,3f ; mask out 0075 : ab mov r3,a ; plonk it in R3. (delay) 0076 : 1c inc r4 ; skip the 2nd value 0077 : b8 aa mov r0,aa ; $(AA) is the last value 0079 : fa mov a,r2 007a : 90 movx @ r0,a 007b : 04 14 jmp 014 ; continue the handler ; *** BIT 5 SET *** 007d : 53 1f anl a,1f ; set delay to bits 0..4 007f : ab mov r3,a 0080 : ba 00 mov r2,00 ; volume = 0 0082 : 04 77 jmp 077 ; set it ; *** BIT 4 SET *** 0084 : fa mov a,r2 ; bit 4 is a 'jump' 0085 : ac mov r4,a ; to the second value 0086 : 84 0a jmp 40a ; tune complete ! 0088 : 00 nop ; **************************************************************************** ; ; RAM to VDC Copier. ; Called in VBlank Handler once if R3F Bit 7 is set. Bit is ; cleared by the interrupt handler. ; ; **************************************************************************** 0089 : b8 7f mov r0,7f ; R0 = $7F Copy Count 008b : b9 a0 mov r1,a0 ; R1 = $A0 VDC Control 008d : 81 movx a,@ r1 ; Turn off Grid,Foreground 008e : 53 d6 anl a,d6 0090 : 91 movx @ r1,a 0091 : 89 7c orl p1,7c ; set : !kbscan !vdcen !ramen copyen 0093 : 99 e7 anl p1,e7 ; clear : !vdcen !ramen 0095 : 80 movx a,@ r0 ; if RAM($7F) is non-zero 0096 : 96 a3 jnz,a3 ; jump to $A3 0098 : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 009a : 99 b7 anl p1,b7 ; clear : !vdcen copyen 009c : b9 a0 mov r1,a0 ; turn on grid & foreground 009e : 81 movx a,@ r1 009f : 43 28 orl a,28 00a1 : 91 movx @ r1,a 00a2 : 83 ret ; **************************************************************************** ; ; R0 = ($7F), A = Byte Count. This is the active RAM->VDC Copying Code ; ; $7F = Count of Bytes ; $7E = Address to Copy to. ; $7D = Data (Backwards !) ; ; **************************************************************************** 00a3 : aa mov r2,a ; save count in R2 00a4 : c8 dec r0 ; point at address 00a5 : 80 movx a,@ r0 ; R1 = Address. 00a6 : a9 mov r1,a ; put in r1 00a7 : c8 dec r0 ; point to first data byte 00a8 : 80 movx a,@ r0 ; copy from RAM to VDC 00a9 : 91 movx @ r1,a 00aa : c8 dec r0 ; previous copy from 00ab : 19 inc r1 ; next copy to 00ac : ea a8 djnz r2 a8 ; keep copyin' man 00ae : 04 95 jmp 095 ; exit. ; **************************************************************************** ; ; Keyboard Check Routine ; ; **************************************************************************** 00b0 : 15 dis i 00b1 : c5 sel rb0 00b2 : 09 in a,p1 ; read enable/switch status 00b3 : ae mov r6,a ; save it in R6 00b4 : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 00b6 : 99 bb anl p1,bb ; clear : !kbscan copyen 00b8 : b8 f0 mov r0,f0 ; R0 = Scan Row 00ba : ba 06 mov r2,06 ; R2 = Rows to Scan 00bc : f8 mov a,r0 ; set the row counter 00bd : 3a outl p2,a ; update keyboard scan row 00be : 0a in a,p2 ; read keyboard status 00bf : 92 da jb4,da ; no key pressed, try next 00c1 : ba 30 mov r2,30 ; r2 = 110000 00c3 : a8 mov r0,a ; r0 = scan value 00c4 : 0a in a,p2 ; read keyboard status 00c5 : d8 xrl a,r0 ; check debouncing 00c6 : 96 df jnz,df ; return none if a bounce 00c8 : ea c4 djnz r2 c4 00ca : f8 mov a,r0 ; a = scan value 00cb : 47 swap a ; nibl exchange of A ; 4-6=row,0=press,1-3=col 00cc : 77 rr a ; 0-2=col,3-5=row 00cd : d3 07 xrl a,07 ; and signed correctly ? 00cf : 53 3f anl a,3f ; drop upper 2 bits 00d1 : a9 mov r1,a ; save in r1 00d2 : ff mov a,r7 ; r7 = Column & 3F 00d3 : 53 3f anl a,3f 00d5 : d9 xrl a,r1 ; check different to last one 00d6 : 96 e5 jnz,e5 ; if so, go to exit point 00d8 : 04 df jmp 0df ; same, return no key. 00da : 18 inc r0 ; no key pressed-next row 00db : ea bc djnz r2 bc ; loop back 00dd : bf ff mov r7,ff ; r7 = a = FF 00df : ff mov a,r7 ; no key pressed 00e0 : 43 c0 orl a,c0 ; A = A or 1100 0000 00e2 : af mov r7,a ; put in return reg... Failed 00e3 : 64 78 jmp 378 ; key fail code 00e5 : 64 76 jmp 376 ; key succeed code ; **************************************************************************** ; ; Set up the VDC access ; ; **************************************************************************** 00e7 : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 00e9 : 99 b7 anl p1,b7 ; clear : !vdcen copyen (?) 00eb : 83 ret ; **************************************************************************** ; ; Set up the RAM access ; ; **************************************************************************** 00ec : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 00ee : 99 af anl p1,af ; clear : !ramen copyen 00f0 : 83 ret ; **************************************************************************** ; ; Reset the Odyssey II ; ; **************************************************************************** 00f1 : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 00f3 : 99 b7 anl p1,b7 ; clear : !vdcen copyen 00f5 : 23 20 mov a,20 ; clear registers $20 - $40 00f7 : a8 mov r0,a 00f8 : a9 mov r1,a 00f9 : 27 clr a 00fa : a0 mov @ r0,a 00fb : 18 inc r0 00fc : e9 fa djnz r1 fa 00fe : 14 ec call 0ec ; access RAM 0100 : b9 ff mov r1,ff ; and clear that 0102 : 91 movx @ r1,a 0103 : e9 02 djnz r1 02 0105 : 91 movx @ r1,a 0106 : 14 e7 call 0e7 ; access the VDC Chip 0108 : 34 1c call 11c ; turn off the display 010a : b8 ff mov r0,ff ; fill 80-FF with Zero 010c : b9 80 mov r1,80 ; (clearing the grids) 010e : 27 clr a 010f : 90 movx @ r0,a 0110 : c8 dec r0 0111 : e9 0f djnz r1 0f 0113 : 23 f8 mov a,f8 ; fill 00-7F with $F8 0115 : 90 movx @ r0,a ; move chars,sprites,quads 0116 : e8 15 djnz r0 15 ; off screen 0118 : 90 movx @ r0,a 0119 : 34 27 call 127 ; turn the display back on 011b : 83 ret ; **************************************************************************** ; ; Turn off the Display ; ; **************************************************************************** 011c : 15 dis i ; no interrupts 011d : c5 sel rb0 ; base register set 011e : b8 a0 mov r0,a0 0120 : 80 movx a,@ r0 ; read $A0 VDC Control Register 0121 : 53 d6 anl a,d6 ; Turn off foreground,grid 0123 : 90 movx @ r0,a ; update VDC Control 0124 : d5 sel rb1 0125 : 05 en i ; interrupts back on 0126 : 83 ret ; **************************************************************************** ; ; Turn the display back on ; ; **************************************************************************** 0127 : 15 dis i ; int off 0128 : c5 sel rb0 ; base register set 0129 : b8 a0 mov r0,a0 012b : 80 movx a,@ r0 012c : 43 28 orl a,28 ; set Foreground,Grid on 012e : 90 movx @ r0,a 012f : d5 sel rb1 0130 : 05 en i ; int back on 0131 : 83 ret ; **************************************************************************** ; ; Enable a Data Copy at the next VSYNC ; ; **************************************************************************** 0132 : 27 clr a ; Memory(R0) = 0 0133 : 90 movx @ r0,a 0134 : b8 3f mov r0,3f ; Set Bit 7 of r63. 0136 : f0 mov a,@ r0 0137 : 43 80 orl a,80 0139 : a0 mov @ r0,a 013a : 14 e7 call 0e7 ; access the VDC Chip 013c : 83 ret ; **************************************************************************** ; ; Get Keystroke into A ; ; **************************************************************************** 013d : 34 76 call 176 ; Wait for Interrupt 013f : 14 b0 call 0b0 ; Keyboard Check Routine 0141 : f2 3d jb7 3d ; go back if no key pressed 0143 : 23 56 mov a,56 ; R4 = 56,Set 3F bit 6 0145 : 34 a2 call 1a2 ; play tune at $0356 0147 : c5 sel rb0 ; reselect page zero 0148 : ff mov a,r7 ; get the result 0149 : d5 sel rb1 ; reselect page 1 014a : 83 ret ; **************************************************************************** ; ; R4 = Vertical R5 = Character. R6 = Colour Byte * 2. ; Convert for suitable use in VDC registers ; ; **************************************************************************** 014b : fe mov a,r6 ; Bit 0 is part of the char set 014c : 53 fe anl a,fe 014e : ae mov r6,a 014f : fd mov a,r5 ; R5 = R5 * 8 0150 : 97 clr c 0151 : f7 rlc a 0152 : f7 rlc a 0153 : f7 rlc a 0154 : ad mov r5,a 0155 : 27 clr a ; A = 9th bit of character 0156 : f7 rlc a ; there are 64 characters 0157 : 4e orl a,r6 ; or that bit into R6 0158 : ae mov r6,a 0159 : fc mov a,r4 ; A = Vertical Position 015a : 67 rrc a ; A = -Vertical / 2 015b : 37 cpl a ; each pixel is two 015c : 17 inc a ; scanlines high. 015d : 6d add a,r5 ; Add it to the lower position 015e : ad mov r5,a ; subtract y/2 from char set pointer 015f : f6 6a jc 6a ; if no borrow,exit ; else toggle bit 0 of R6 0161 : fe mov a,r6 ; A = ~R6 & 1 0162 : 37 cpl a 0163 : 53 01 anl a,01 0165 : 2e xch a,r6 ; swap A and R6 0166 : 53 fe anl a,fe ; Mask off bits of R6 0168 : 4e orl a,r6 ; or the borrow in 0169 : ae mov r6,a ; put it back - who wrote this ? 016a : 83 ret ; **************************************************************************** ; ; Delete all characters by moving horizontal position to 248 ; which is off the right hand side. ; ; **************************************************************************** 016b : 23 f8 mov a,f8 ; A = $F8 016d : b8 10 mov r0,10 ; Start at VDC $10 016f : ba 30 mov r2,30 ; Fill $30 characters 0171 : 90 movx @ r0,a 0172 : 18 inc r0 0173 : ea 71 djnz r2 71 0175 : 83 ret ; **************************************************************************** ; ; Wait for Interrupt ; ; **************************************************************************** 0176 : a5 clr f1 ; F1 = 0 0177 : 05 en i ; Enable Interrupts 0178 : 76 75 jf1,75 ; Interrupt called ? Yes,exit 017a : 24 78 jmp 178 ; wait for interrupt ; **************************************************************************** ; ; Display BCD 2 digit A at VDC address R1. ; R4 = Y R3 = X R6 = Colour ; ; **************************************************************************** 017c : 14 ec call 0ec ; access RAM only 017e : aa mov r2,a ; save A in R2 017f : b8 7f mov r0,7f 0181 : 23 08 mov a,08 ; Copy 8 bytes ($7F) 0183 : 90 movx @ r0,a 0184 : c8 dec r0 0185 : f9 mov a,r1 ; Address in R1 0186 : 90 movx @ r0,a ; To VDC Address R1 ($7E) 0187 : c8 dec r0 ; R0 = $7D First Data Byte 0188 : fa mov a,r2 ; R2 = First Data Byte (low) 0189 : 47 swap a ; A = First Data Byte (High) 018a : 53 0f anl a,0f ; R5 = High Nibble 018c : ad mov r5,a ; put in R5 018d : 34 97 call 197 ; write it 018f : fa mov a,r2 ; Write Low Nibble 0190 : 53 0f anl a,0f 0192 : ad mov r5,a 0193 : 34 97 call 197 0195 : 24 32 jmp 132 ; data copy at next VSYNC 0197 : fc mov a,r4 ; Write Y 0198 : 90 movx @ r0,a 0199 : c8 dec r0 019a : fb mov a,r3 ; Write X 019b : 90 movx @ r0,a 019c : c8 dec r0 019d : 03 08 add a,08 ; Offset X 8 right 019f : ab mov r3,a 01a0 : 44 2c jmp 22c ; Copy Data into Copy Space ; **************************************************************************** ; ; Start playing tune. Tune data at 03 ; ; **************************************************************************** 01a2 : 15 dis i ; no interrupts 01a3 : c5 sel rb0 ; use the bank 0 01a4 : ac mov r4,a ; R4 = Entered Value 01a5 : bb 01 mov r3,01 ; R3 = 1 01a7 : b8 3f mov r0,3f ; R0 = 63 01a9 : f0 mov a,@ r0 ; Read Register 3F 01aa : 43 40 orl a,40 ; Set Bit 6 01ac : a0 mov @ r0,a ; write it back 01ad : d5 sel rb1 ; reselect memory bank 1 01ae : 05 en i ; enable interrupts 01af : 83 ret ; and return ; **************************************************************************** ; ; Handle and display counter. 1 (High) 2 (Low) are the counter ; values in BCD. ($3E). Bit 6 = 1 Increment, 0 Decrement. ; Bit 7 is set when times out. R6 = Colour. ; ; **************************************************************************** 01b0 : b8 3e mov r0,3e ; check if clock is stopped 01b2 : f0 mov a,@ r0 ; if so enable VDC and exit 01b3 : f2 3a jb7 3a ; 01b5 : 53 3f anl a,3f ; if frame != 59 then exit 01b7 : d3 3b xrl a,3b ; 01b9 : 96 3a jnz,3a ; 01bb : 14 ec call 0ec ; Access RAM 01bd : f0 mov a,@ r0 ; A = Character Pointer 01be : b8 02 mov r0,02 ; R0 = 2 01c0 : b9 01 mov r1,01 ; R1 = 1 01c2 : d2 e2 jb6 e2 ; A = RAM($3E) bit 6 ; zero = decrement timer 01c4 : ba 99 mov r2,99 ; R2 = 99 01c6 : 80 movx a,@ r0 ; A = RAM($2) 01c7 : c6 ce jz ce ; if zero goto 1CE 01c9 : 6a add a,r2 ; decrement value 01ca : 57 daa a ; decimal adjust 01cb : 90 movx @ r0,a ; save in RAM($2) 01cc : 24 fc jmp 1fc ; go to drawing code 01ce : 81 movx a,@ r1 ; if high byte timed out 01cf : c6 da jz da ; goto $1DA 01d1 : 23 59 mov a,59 ; RAM($2) = 59 01d3 : 90 movx @ r0,a 01d4 : 81 movx a,@ r1 ; decrement RAM($1) by 01d5 : 6a add a,r2 ; adding 99 to it 01d6 : 57 daa a 01d7 : 91 movx @ r1,a ; update RAM($1) 01d8 : 24 fc jmp 1fc 01da : b8 3e mov r0,3e ; R0 = $3E 01dc : f0 mov a,@ r0 ; A = RAM($3E) 01dd : 43 80 orl a,80 ; set bit 7 (timed out) 01df : a0 mov @ r0,a 01e0 : 24 3a jmp 13a ; re-enable VDC & exit 01e2 : ba 01 mov r2,01 ; R2 = 1 01e4 : 80 movx a,@ r0 ; if RAM(2) is 59 01e5 : d3 59 xrl a,59 01e7 : c6 ef jz ef ; go to tick over 01e9 : 80 movx a,@ r0 ; inc RAM(2) BCD 01ea : 6a add a,r2 01eb : 57 daa a 01ec : 90 movx @ r0,a 01ed : 24 fc jmp 1fc ; and display 01ef : 90 movx @ r0,a ; zero RAM (2) 01f0 : 81 movx a,@ r1 ; check RAM(1) is 59 01f1 : d3 59 xrl a,59 01f3 : 96 f8 jnz,f8 ; if not, increment 01f5 : 91 movx @ r1,a ; zero RAM(1), no timeout 01f6 : 24 fc jmp 1fc ; display 01f8 : 81 movx a,@ r1 ; increment RAM(1) BCD 01f9 : 6a add a,r2 01fa : 57 daa a 01fb : 91 movx @ r1,a ; display RAM(1) RAM(2) 01fc : b8 7f mov r0,7f ; start write at 007F 01fe : 54 35 call 235 ; copy 2 bytes 0200 : 23 42 mov a,42 ; to VDC $42 (Quads). 0202 : 90 movx @ r0,a 0203 : c8 dec r0 ; R0 = 007D now. 0204 : b9 01 mov r1,01 ; A = RAM(1) 0206 : 81 movx a,@ r1 0207 : 47 swap a ; high nibble first 0208 : 54 29 call 229 ; write character data 020a : 54 35 call 235 ; copy 2 bytes 020c : 23 52 mov a,52 ; to VDC $52 020e : 90 movx @ r0,a 020f : c8 dec r0 0210 : 81 movx a,@ r1 ; low nibble 0211 : 54 29 call 229 0213 : 54 35 call 235 ; copy 2 bytes 0215 : 23 56 mov a,56 ; to VDC $56 0217 : 90 movx @ r0,a 0218 : c8 dec r0 0219 : 19 inc r1 ; Get next 2 nibbles from RAM(2) 021a : 81 movx a,@ r1 ; high nibble 021b : 47 swap a 021c : 54 29 call 229 021e : 54 35 call 235 ; copy 2 bytes 0220 : 23 4a mov a,4a ; to VDC $4A 0222 : 90 movx @ r0,a 0223 : c8 dec r0 0224 : 81 movx a,@ r1 ; last one now.... 0225 : 54 29 call 229 0227 : 24 32 jmp 132 ; Data copy at next VSYNC ; **************************************************************************** ; ; R0 points to RAM (for copying), A is character, R6 is colour ; ; **************************************************************************** 0229 : 53 0f anl a,0f ; char in range 0-15 022b : ad mov r5,a ; **************************************************************************** ; the BCD Version routine jumps in here. R5 contains the character ; (from $01A0) ; **************************************************************************** 022c : 34 4b call 14b ; translate character for writing 022e : fd mov a,r5 ; write the character 022f : 90 movx @ r0,a 0230 : c8 dec r0 0231 : fe mov a,r6 ; write the colour 0232 : 90 movx @ r0,a 0233 : c8 dec r0 0234 : 83 ret 0235 : 23 02 mov a,02 ; write 2 into the to-copy 0237 : 90 movx @ r0,a 0238 : c8 dec r0 0239 : 83 ret ; **************************************************************************** ; ; Set up Quad Characters. R3,R4 = X,Y Position ; ; sets up as xx:xxsss (s = space, x to be filled in later) ; ; **************************************************************************** 023a : b8 40 mov r0,40 ; R0 = $40 023c : b9 50 mov r1,50 ; R1 = $50 023e : fc mov a,r4 ; A = R4 023f : 90 movx @ r0,a ; $(40) = R4 (Y Quad 1) 0240 : 91 movx @ r1,a ; $(50) = R4 (Y Quad 2) 0241 : 18 inc r0 0242 : 19 inc r1 0243 : fb mov a,r3 ; $(41) = R3 (X Quad 1) 0244 : 90 movx @ r0,a 0245 : 03 08 add a,08 ; $(51) = R3+8 (X Quad 2) 0247 : 91 movx @ r1,a ; interleave Quad's 0248 : bd 0a mov r5,0a ; colon 024a : b8 46 mov r0,46 024c : 54 61 call 261 ; write char (chr R5,col R6 @ R0) 024e : bd 0c mov r5,0c ; space 0250 : b8 4e mov r0,4e 0252 : 54 61 call 261 ; write char (chr R5,col R6 @ R0) 0254 : bd 0c mov r5,0c ; space 0256 : b8 5a mov r0,5a 0258 : 54 61 call 261 ; write char (chr R5,col R6 @ R0) 025a : bd 0c mov r5,0c ; space 025c : b8 5e mov r0,5e 025e : 54 61 call 261 ; write char (chr R5,col R6 @ R0) 0260 : 83 ret ; **************************************************************************** ; ; R0 points to Foreground Character, R5 Character, R6 Colour ; ; **************************************************************************** 0261 : 34 4b call 14b ; translate R5 & R6 to suitable data 0263 : fd mov a,r5 ; for use as single characters 0264 : 90 movx @ r0,a ; copy them into single character 0265 : 18 inc r0 ; memory 0266 : fe mov a,r6 0267 : 90 movx @ r0,a 0268 : 18 inc r0 0269 : 83 ret ; and exit ; **************************************************************************** ; ; Bit test routine. R1 points to first byte after data. R2 is ; the bit number as byte * 8 + bit (0 = LSB). Returns A <> 0 ; if bit clear ; ; **************************************************************************** 026a : 07 dec a ; A = A - 1 026b : ba f8 mov r2,f8 ; dividing A by 8. R1 is 026d : 6a add a,r2 ; decremented each time. 026e : c9 dec r1 ; decrement count of times 026f : f6 6d jc 6d ; loop back if r2 < 8 0271 : 6a add a,r2 0272 : 53 07 anl a,07 0274 : 17 inc a ; so it shifts at least once 0275 : aa mov r2,a ; r2 = remainder ? 0276 : 27 clr a ; A = C = 0 0277 : 97 clr c 0278 : a7 cpl c ; C = 1 0279 : f7 rlc a 027a : ea 79 djnz r2 79 ; A = 1 shifted by remainder. 027c : aa mov r2,a 027d : 81 movx a,@ r1 027e : 5a anl a,r2 027f : 83 ret ; **************************************************************************** ; ; Clear bit (as above). Returns A <> 0 if was previously set ; ; **************************************************************************** 0280 : 54 6a call 26a ; call bit test 0282 : c6 89 jz 89 ; exit if zero (not set) 0284 : 81 movx a,@ r1 ; toggle bit 0285 : da xrl a,r2 0286 : 91 movx @ r1,a 0287 : 27 clr a ; A = 1, collision (?) 0288 : 17 inc a 0289 : 83 ret ; **************************************************************************** ; ; Set bit (as above). Returns A <> 0 if was previously set ; ; **************************************************************************** 028a : 54 6a call 26a ; call bit test 028c : 96 92 jnz,92 ; if already set exit 028e : 81 movx a,@ r1 ; toggle it 028f : da xrl a,r2 0290 : 91 movx @ r1,a 0291 : 27 clr a 0292 : 83 ret ; **************************************************************************** ; ; Random number generator ; ; **************************************************************************** 0293 : 42 mov a,t ; A = timer value 0294 : ac mov r4,a ; R4 = timer value 0295 : 53 0f anl a,0f 0297 : ad mov r5,a ; R5 = timer & 00001111 0298 : 54 a4 call 2a4 029a : 2a xch a,r2 ; A <--> R2 029b : af mov r7,a 029c : fc mov a,r4 029d : 53 f0 anl a,f0 029f : 47 swap a 02a0 : ad mov r5,a 02a1 : 54 a4 call 2a4 02a3 : 83 ret 02a4 : fd mov a,r5 ; A = R5 + B3 02a5 : 03 b3 add a,b3 02a7 : a3 movp a,@ a ; A = [02B3 + R5] 02a8 : 96 ac jnz,ac ; if Non Zero, Inc R5 02aa : ad mov r5,a ; else R5 = 0 02ab : cd dec r5 02ac : 1d inc r5 02ad : ab mov r3,a ; R3 = Value 02ae : 6f add a,r7 ; loop back if < R7 02af : f6 a4 jc a4 02b1 : fb mov a,r3 ; A = value read from table 02b2 : 83 ret 02b3: 0f 0e 0d 02 0a 05 0b 03 06 0c 09 01 04 08 07 00 ; **************************************************************************** ; ; Select Game Routine ; ; **************************************************************************** 02c3 : bf ff mov r7,ff ; R7 = FF 02c5 : d5 sel rb1 ; Select High Registers 02c6 : 14 f1 call 0f1 ; reset the machine 02c8 : b9 f2 mov r1,f2 ; R1 points to the text 02ca : b8 10 mov r0,10 ; R0 points to FGR Character 02cc : ba 0b mov r2,0b ; R2 is the character counter 02ce : bb 28 mov r3,28 ; R3 is X Position 02d0 : bc 70 mov r4,70 ; R4 is Y Position 02d2 : be 04 mov r6,04 ; R6 is Colour 02d4 : 34 1c call 11c ; turn off the display 02d6 : f9 mov a,r1 ; A = F2. 02d7 : a3 movp a,@ a ; R5 = @02F2, text 02d8 : ad mov r5,a 02d9 : 74 ea call 3ea 02db : 19 inc r1 ; Next Character 02dc : 1e inc r6 ; Next Horizontal Position 02dd : 1e inc r6 02de : ea d6 djnz r2 d6 ; Do it R2 times. 02e0 : 34 27 call 127 ; turn the display back on 02e2 : 23 4a mov a,4a ; R4 = $4A. Set 3F bit 6 02e4 : 34 a2 call 1a2 02e6 : 34 3d call 13d ; Get keystroke 02e8 : a9 mov r1,a ; Save the keystroke 02e9 : 34 1c call 11c ; turn off the display 02eb : 34 6b call 16b ; clear the characters 02ed : 34 27 call 127 ; turn the display back on 02ef : f9 mov a,r1 ; get the result 02f0 : 84 08 jmp 408 ; jump to the ROM vector. 02f2 : 19 inc r1 ; S 02f3 : 12 0e jb0,0e ; E L 02f5 : 12 23 jb0,23 ; E C 02f7 : 14 0c call 00c ; T 02f9 : 1c inc r4 ; G 02fa : 20 xcha,@ r0 ; A 02fb : 26 12 jnt0,12 ; M E 02fd : 20 xcha,@ r0 ; padding..... 02fe : 20 xcha,@ r0 02ff : 20 xcha,@ r0 ; **************************************************************************** ; ; Data for the 8 default tunes ; ; **************************************************************************** ; frequency data 0300: 00 0F FF CF - 03 F0 3F CF - 0F 0F 0F CF - 1C 71 C7 CF 0310: 33 33 33 CF - 03 F0 3F EF - 0F 0F 0F EF - 1C 71 C7 EF 0320: 33 33 33 EF - 55 55 55 EF ; tune data 0328: 90 10 94 00 - 21 00 56 DF 0330: 53 DD 50 DA - 4D D8 4A D5 - 47 D2 21 00 - 92 20 4A CD 0340: 52 EB 4A C9 - 52 E7 4A C5 - 21 00 85 04 - 85 0C 85 14 0350: 85 1C 85 24 - 21 00 82 1C - 21 00 8A 00 - 21 00 85 24 0360: 85 1C 85 14 - 85 0C 85 04 - 21 00 44 FF - 4D DD 48 DA 0370: 44 D5 42 D3 - 21 00 ; **************************************************************************** ; ; the tail of the keyboard code ; ; **************************************************************************** 0376 : f9 mov a,r1 ; key ok comes here 0377 : af mov r7,a ; r7 = result 0378 : fe mov a,r6 ; restore old switch status 0379 : 39 outl p1,a ; set the enable/switch status 037a : ff mov a,r7 037b : d5 sel rb1 ; select correct bank 037c : 05 en i ; enable interrupts 037d : 83 ret ; and exit ; **************************************************************************** ; ; Bank switch routines ; ; **************************************************************************** 037e : 20 xcha,@ r0 ; padding 037f : 99 fe anl p1,fe ; clear : bank0 0381 : 84 08 jmp 408 0383 : 99 fd anl p1,fd ; clear : bank1 0385 : 84 08 jmp 408 0387 : 99 fc anl p1,fc ; clear : bank0 bank1 0389 : 84 08 jmp 408 038b : 89 03 orl p1,03 ; set : bank0 bank1 038d : 84 08 jmp 408 ; **************************************************************************** ; ; Read the Joystick. R1 = 0 (Stick 1) 1 (Stick2) ; ; On exit R1 = Bit Pattern,R2 = HOffset,R3 = VOffset,F0 = Fire ; ; **************************************************************************** 038f : 09 in a,p1 ; read enable/switch status 0390 : a8 mov r0,a ; save current status in R0 0391 : 89 bc orl p1,bc ; set : !kbscan !vdcen !ramen lumen 0393 : 99 9b anl p1,9b ; clear : !kbscan copyen 0395 : f9 mov a,r1 0396 : 43 f0 orl a,f0 ; A = F0 or F1 0398 : 3a outl p2,a ; update keyboard scan row 0399 : 85 clr f0 ; F0,A,R2,R3 = 0 039a : 27 clr a 039b : aa mov r2,a 039c : ab mov r3,a 039d : 08 ins a,bus ; read joypad 039e : a9 mov r1,a ; save in r0 039f : 12 a2 jb0,a2 ; r2 (horiz) r3 (vert) 03a1 : cb dec r3 03a2 : 32 a5 jb1,a5 03a4 : 1a inc r2 03a5 : 52 a8 jb2,a8 03a7 : 1b inc r3 03a8 : 72 ab jb3,ab 03aa : ca dec r2 03ab : 92 ae jb4,ae ; set the fire button 03ad : 95 cpl f0 03ae : f8 mov a,r0 ; reset the enable flags 03af : 39 outl p1,a ; set the enable/switch status 03b0 : 83 ret ; **************************************************************************** ; ; Decode Joystick ; ; **************************************************************************** 03b1 : fb mov a,r3 03b2 : 53 0f anl a,0f 03b4 : a8 mov r0,a 03b5 : fa mov a,r2 03b6 : 53 0f anl a,0f 03b8 : 47 swap a 03b9 : 48 orl a,r0 03ba : a8 mov r0,a 03bb : b9 07 mov r1,07 03bd : 23 c7 mov a,c7 03bf : 69 add a,r1 03c0 : a3 movp a,@ a 03c1 : d8 xrl a,r0 03c2 : c6 c6 jz c6 03c4 : e9 bd djnz r1 bd 03c6 : 83 ret 03c7 : 10 inc @ r0 03c8 : 1f inc r7 03c9 : 0f movd a,p7 03ca : ff mov a,r7 03cb : f0 mov a,@ r0 03cc : f1 mov a,@ r1 03cd : 01 illegal 03ce : 11 inc @ r1 ; **************************************************************************** ; ; Divide R4 = R2/R3 , R5 = R2%R3 ; ; **************************************************************************** 03cf : bc ff mov r4,ff 03d1 : fb mov a,r3 03d2 : 37 cpl a 03d3 : 17 inc a 03d4 : ae mov r6,a 03d5 : fa mov a,r2 03d6 : 6e add a,r6 ; r2 - r3 03d7 : 1c inc r4 03d8 : f6 d6 jc d6 03da : 6b add a,r3 03db : ad mov r5,a 03dc : 83 ret ; **************************************************************************** ; ; Multiply A = R2 * R3 ; ; **************************************************************************** 03dd : fa mov a,r2 03de : 96 e1 jnz,e1 03e0 : 83 ret 03e1 : fb mov a,r3 03e2 : 96 e5 jnz,e5 03e4 : 83 ret 03e5 : 27 clr a 03e6 : 6b add a,r3 03e7 : ea e6 djnz r2 e6 03e9 : 83 ret ; **************************************************************************** ; ; R3 = X , R4 = Y, R0 = Char Pointer in VDC,R5 = Char,R6 = Colour ; Draw it. Part of "Select Game" code. ; ; **************************************************************************** 03ea : fc mov a,r4 ; VDC Memory (R0) = R4 03eb : 90 movx @ r0,a 03ec : 18 inc r0 03ed : f8 mov a,r0 ; reached end of available 03ee : d2 f9 jb6 f9 ; characters 03f0 : fb mov a,r3 ; VDC Memory (R0+1) = R3 03f1 : 90 movx @ r0,a 03f2 : 03 08 add a,08 ; advance text pointer 03f4 : ab mov r3,a 03f5 : 18 inc r0 ; R0 points to character set 03f6 : 54 61 call 261 03f8 : 83 ret 03f9 : 53 0f anl a,0f ; For Quad's... 03fb : 07 dec a ; increment the X-position... 03fc : c6 f0 jz f0 ; only for the first character 03fe : 64 f5 jmp 3f5 ; write the quad