Site Map | Contact Info | Home  
  
 Home
 Products
 ROMHACK Toolbox
 Ordering Info
 Code Disassembly
  Bega's Battle
  Cliffhanger
  Thayer's Quest
 My Gameroom
 Links

 

 

Page1

Page2

Page3

Page4

Page5

;----------------------------------------------------
; Disassembly of the Thayer's Quest ROMs
;       by Jeff Kulczycki, Jun 19, 2001
;----------------------------------------------------
;
;----------------------------------------------------
;    RAM VARIABLES (8k RAM at A000-BFFF)
;----------------------------------------------------
;    Address      Description
;----------------------------------------------------     
;   A000          OUT (4) Speech Register 0: Duration/Phonetic
;   A100          OUT (3) Speech Register 1: Inflection
;   A200          OUT (2) Speech Register 2: Speech Rate
;   A300          OUT (1) Speech Register 3: Amplitude
;   A400          OUT (0) Speech Register 4: Filter Frequency
;   A500          Holds Copy of A000
;----------------------------------------------------
;   A604-A605     Temp pointer to start of Speech Buffer
;   A608-A609     Pointer to A400
;   A60A-A60B     Unknown
;   A60E          Unknown
;   A612-A613     Save Phoneme entry starting location
;   A614          Number of characters in Speech Buffer
;   A615          Unknown - speech, characters, timer
;   A618          Marker (0,1)
;   A619
;   A61C          Z_Adder (+1,-1)
;   A61D          X_Adder (+1,-1)
;   A61F          A100 Speech Control Code (F0-FF)
;   A620          Backslash Flag (1 = backslash in speech buffer, 0 = no backslash)
;   A621          Question Flag, checks occurance of "WH" in speech buffer
;   A630          Unknown
;   A63A          Equations: Number of chacters to the right of the equals sign
;   A641          Pointer to End of Speech Buffer
;   A64A          Length of Player's (full) Name
;   A64B-A68A     String containing Player's (full) Name
;   A68B          Length of Player's First Name
;   A68C-A6CA     String containing Player's First Name
;   A6CB-A6CE     Copy of score
;   A6CF          Word Properties (Plural, Inflection Level, etc.)
;   A6D0-A6D2     Speakable number (n) in digits
;   A6D3          Unknown
;   A6D4-A6D5     Previous phrase pointer to avoid repeating same phrase
;   A6D6          Ring Buffer 0-3 to keep track of repeated phrases
;   A6D9          Temp location:  Save Timer
;                                 Save word length for vulgarities
;   A782    .0
;           .1
;           .5
;           .7
;   A783    .4    Coin Counter Hardware Increment
;           .5    Set LDPlayer data bus as Input
;           .6    LDPlayer ENTER
;           .7    LDPlayer INT/EXT
;   A784          Command Byte to LDPlayer
;   A787          Number of SEARCH Retries
;   A788          Attract Mode Count (1-8)
;   A7B5-A7B7     BCD, Number after converted to BCD
;   A794-A796     Number awaiting conversion to BCD
;   A79A    .3    0 = PR-7820, 1 = LD-V1000
;         
;----------------------------------------------------
;  Saved Game Banks
;----------------------------------------------------
;   A800-A9FF     SAVED GAME Bank 1
;   AA00-ABFF     SAVED GAME Bank 2
;   AC00-ADFF     SAVED GAME Bank 3
;   AE00-AFFF     SAVED GAME Bank 4
;   B000-B1FF     SAVED GAME Bank 5
;   B200-B3FF     SAVED GAME Bank 6
;   B400-B5FF     SAVED GAME Bank 7
;   B600-B7FF     SAVED GAME Bank 8
;   B800-B9FF     SAVED GAME Bank 9
;   BA00-BBFF     SAVED GAME Bank 10
;----------------------------------------------------
;    Current Working BANK area       
;----------------------------------------------------
;   BC00          Bank Number of current SAVED GAME
;   BC01          Unknown
;   BC03          Buffer pointer to 32
;   BC24-BC64     Player's Full Name? LABEL
;   BC65-BC6A     6 bytes get copied from BE27
;   BC6B-BC71     6 bytes get copied from BE27
;   BC80    .0    0 = Audio Track1, 1 = Audio Track2
;   BC81          Scene Index
;   BC82
;   BC83-BC84     Scene Jumpers
;   BC85-BC86     Scene Jumpers
;   BC87-BC9F     Scene Jumpers (BC83)
;   BCA0-BCBA     Items in Inventory
;           .0    1 = Item is valid (has key associated)
;           .1    1 = Item Held
;           .2    1 = ?
;   BCC0          inventory2?
;   BCE0          Index to Health Table (C97E) <Default 08h>
;   BCE1          Wounds/Health
;   BCE2-BCE4     Score
;   BCE5          xxx Timer Control Register
;           .0    1 = Timer ON, 0 = Timer OFF
;           .1    1 = Timer Expired, 0 = Not expired
;   BCE6-BCE7     xxx Timer Value
;   BCE8          Number of Lives
;   BCF0-BDFF     Hints given to player
;----------------------------------------------------
;   BE00          Index to Routine (Table1) 1 thru 8
;   BE01    .0    1 = Exit Main Loop
;           .1    1 = SAVE GAME in progress
;           .2
;           .6    Audio Status 0 = Single Channel,1 = Stereo
;           .7    Audio Source 0 = AUDIO1, 1 = AUDIO2
;   BE02          Index to Routine (Table2)
;   BE03    .0    1 = Reset Main Loop
;           .1    REPLAY
;           .2    1 = Combine Mode enabled, waiting for object selection
;           .3    1 = Drop Mode enabled, waiting for object selection       
;           .4     0 = Audio Track1, 1 = Audio Track2
;   BE04          Game Timer Control Register
;           .0    1 = Timer ON, 0 = Timer OFF
;           .1    1 = Timer Expired, 0 = Not expired
;   BE05-BE06     Game Timer Value
;   BE07          Programmable Timer Control Register
;           .0    1 = Timer ON, 0 = Timer OFF
;           .1    1 = Timer Expired, 0 = Not expired
;   BE08-BE09     Programmable Timer Value
;   BE0A          Keyboard Character Pressed
;   BE0B    .0    Keyboard Buffer Indicator
;           .1    Unknown
;   BE0C    .0-.4 Unknown
;           .5-.7 Unknown
;   BE0D          Number of Credits, Tens/Ones
;   BE0E          Number of Credits, Hundreds
;   BE0F          Hold DIP Switch A
;   BE10          Coin Slot 1 Debounce
;   BE11          Coin Slot 2 Debounce
;   BE12          Unknown
;   BE13-BE14     Number of
;   BE15-BE16     Temp BANK address
;   BE17    .0    Unknown
;           .7    Unknown
;   BE18          Temporary RAM Spot
;   BE23          DecisionTimer Control Register
;           .0    1 = Timer ON, 0 = Timer OFF
;           .1    1 = Timer Expired, 0 = Not expired
;   BE24-BE25     DecisionTimer Value   
;   BE27-BC2C     Unknown -important-
;   BE2D-BE2F     Initials - "RDI"
;   BE30
;   BE31-BE37     Unknown
;   BE44-BE46     score, ranking?
;   BE48          Timer Register
;           .0
;           .7    ??
;----------------------------------------------------
;  Scoreboard Output Port is F6/F7, Data as follows
;  where x is the digit to store
;----------------------------------------------------
;   0x   Player1 Game time Remaining 1
;   1x   Player1 Game time Remaining 10
;   2x   Player1 Game time Remaining 100
;   3x   Player1 Game time Remaining 1000
;   4x   Player1 Game time Remaining 10000
;   5x   Player1 Game time Remaining 100000
;   6x   Credits 10
;   7x   Credits 1
;  x = [0,1,2,3,4,5,6,7,8,9]
;----------------------------------------------------
; INPUT/OUTPUT PORTS
;----------------------------------------------------
;     Address      Description
;       00          Unknown
;       01          Unknown
;       02          Unknown
;       03          Unknown
;       04          Unknown
;       20          Unknown
;       80          Unknown
;       C0          Reset Keyboard Input Ready
;       A0          Unknown
;       E0          Unknown
;       F0          Input Byte from LDPlayer
;       F1          DIP Switch B/Coin Slots/READY Status
;       F2          DIP Switch A
;       F3          Interrupt Request
;       F4          Output Byte to LDPlayer
;       F5          Hardware
;          .4       Coin Counter Hardware Increment       
;          .5       Set LDPlayer data bus as Input
;          .6       LDPlayer ENTER
;          .7       LDPlayer INT/EXT
;       F6          Scoreboard
;       F7          Scoreboard
;----------------------------------------------------
;       KEYBOARD CHARACTERS
;----------------------------------------------------
;        F1 (080h)  CLEAR
;        F2 (081h)  none
;        F3 (082h)  ENTER
;        F4 (083h)  SPACE 
;----------------------------------------------------
;       DEFINES
;----------------------------------------------------

        org     
0000h
        CPU     = Z180
        globals on


 


;----------------------------------------------------
;                   Start of RESET
;----------------------------------------------------
Reset:       
L0000:  DI                     
; Disable Interrupts
        IM      1               ; Set Interrupt Mode 1
        LD      SP,0BFFFh       ; Set Stack Pointer to end of RAM
        OUT     (0C0h),A        ; Reset Keyboard Data Ready Interrupt
        OUT     (0A0h),A
       
XOR     A               ; A = 0
        LD      (0BE43h),A      ;
        LD      A,010h          ;
        LD      (0BE0Ch),A      ;
        OUT     (020h),A        ; Set Keyboard to Output

        LD      B,
0FFh          ;
L0017:  LD      A,(0BFFFh)      ;
        DJNZ    L0017           ;

       
CALL    L1247           ; Initialize Speech Chip
        LD      HL,0BE2Dh       ; Set up pointer to initials
        CALL    L003B           ; Check if initials are "RDI"
        JP      NZ, L00BA       ; Not RDI, so jump ahead
        LD      A,0F5h
       
OUT     (080h),A        ; Write to Keyboard Interface (COP421L)
        LD      HL,0BE17h
        SET     
7,(HL)
       
JP      L0095           ;

;----------------------------------------------------
;                  Not Used
;----------------------------------------------------
        DB   0FFh, 0FFh, 0FFh, 0FFh   

;----------------------------------------------------
;             IM 1 INTERRUPT JUMP POINT
;----------------------------------------------------
L0038:  JP      L01B1           ; Goto IM 1 Interrupt Routine

;----------------------------------------------------
;         Check if initials are "RDI"
;     HL   = Start of Initials 
;----------------------------------------------------
L003B:  LD      A,'R'           ; Check for "R"
        CP      (HL)            ; Is first initial a "R"?
        RET     NZ              ; No, so return
        INC     HL              ; Point to next initial
        LD      A,'D'           ; Check for "D"
        CP      (HL)            ; Is middle initial a "D"?
        RET     NZ              ; No, so return
        INC     HL              ; Point to next initial
        LD      A,'I'           ; Check for "I"
        CP      (HL)            ; Is last initial a "I"?
        RET                     ; Return

;----------------------------------------------------
;                       Not Used
;----------------------------------------------------
    DB  0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
   
DB  0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
   
DB  0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh
   
DB  0FFh, 0FFh, 0FFh, 0FFh, 0FFh

       
HALT   



;----------------------------------------------------
;              UNKNOWN Check for F5 in BE27         
;----------------------------------------------------
L0067:  CALL    L21B3           ; Check if Programmable Timer expired
        JR      Z,L0067         ; Still running so just loop
        LD      HL,0BE17h
        RES     
7,(HL)
        BIT     
0,(HL)
       
RET     Z
        RES     
0,(HL)
       
CALL    L169E
        LD      HL,
0BE27h
        LD      B,
006h          ; Loop = 6
        LD      A,0F5h          ; Check for an F5
L0080:  CP      (HL)            ; Was there an F5?
        JR      Z,L0087         ; Yes, so erase all bytes       
        INC     HL              ; Check next byte
        DJNZ    L0080           ; Loop until all 6 bytes are checked       
        RET                     ; Not found so return
;----------------------------------------------------
;   F5 is in important bytes so reset them to zero         
;----------------------------------------------------
L0087:  XOR     A               ; Reset to zero
        LD      B,006h          ; Loop = 6
        LD      HL,0BE27h       ;
L008D:  LD      (HL),A          ; Reset to zero
        INC     HL              ;
        DJNZ    L008D           ; Loop until all bytes cleared       
        CALL    L16D8           ;
        RET                     ;





L0095:  LD      DE,
00005h       ; Programmable Timer = 5
        CALL    L21A7           ; Set Programmable Timer
        EI                      ; Enable Interrupts
        CALL    L0067           ; Wait until Timer expires..?
        LD      HL,0BE01h       ; Get GAME STATUS Register
        BIT     1,(HL)          ; Is there a game waiting to be saved?
        CALL    NZ,L0E10        ; Yes, so call Save Game


;----------------------------------------------------
;       Clear out all 10 SAVED GAME Banks.
;----------------------------------------------------
        LD      B,00Ah          ; Loop = 10
        LD      DE,00200h       ; DE = 200h
        LD      IY,0A800h       ; IY = Start of Game Banks
L00B0:  RES     7,(IY+001h)     ; Clear bit 7 of A801
        ADD     IY,DE           ; IY = IY + 200h
        DJNZ    L00B0           ; Loop until all banks marked                       
        JR      L00FD           ; Jump ahead


;----------------------------------------------------
;         Clear Out RAM (A000-BFFF)
;----------------------------------------------------
L00BA:  LD      HL,0A000h       ; Setup loop pointer A000
        LD      DE,0A001h       ; Setup Loop pointer A000+1
        LD      BC,01FFFh       ; Loop size is 2K
        LD      (HL),000h       ; Clear out RAM location
        LDIR                    ; Loop until all locations cleared

;----------------------------------------------------
;         Label SAVED GAME Banks 1-10
;----------------------------------------------------
        LD      DE,00200h       ; DE = 200, Size of Bank
        LD      A,001h          ; A = 1, First label
        LD      B,00Ah          ; Loop = 10, Number of Banks
        LD      IY,0A800h       ; IY = A800,AA00,AC00,etc. Start of Banks
L00D2:  LD      (IY+000h),A     ; Store label
        INC     A               ; A = A + 1, Increment label
        ADD     IY,DE           ; IY = IY + 200h, Point to next Bank
        DJNZ    L00D2           ; Loop until all banks labeled
                         
        LD      A,
0F5h          ;
        OUT     (080h),A        ; Write to Keyboard Interface (COP421L)
        LD      HL,0BE17h
        SET     
7,(HL)
        LD      DE,
00005h       ; Programmable Timer = 5
        CALL    L21A7           ; Set Programmable Timer
        EI                      ; Enable Interrupts

       
CALL    L0067
        LD      HL,
0A782h
        LD      (HL),
0C1h
;----------------------------------------------------
;                Store RDI initials
;----------------------------------------------------
        LD      HL,0BE2Dh       ; Point to initials
        LD      (HL),'R'        ; Store "R" in first spot
        INC     HL              ; Point to next spot
        LD      (HL),'D'        ; Store "D" in next spot
        INC     HL              ; Point to next spot
        LD      (HL),'I'        ; Store "I" in next spot

;----------------------------------------------------
;                 Blank out Scoreboard
;----------------------------------------------------
L00FD:  LD      B,008h          ; Loop = 8
        LD      A,00Fh          ; A = 0F,1F,2F,3F,4F,5F,6F,7F
L0101:  OUT     (0F6h),A        ; Write A to F6
        OUT     (0F7h),A        ; Write A to F7
        ADD     A,010h          ; A = A + 10h
        DJNZ    L0101           ; Loop unit B = 0

;----------------------------------------------------
;         Set Scoreboard Credits to "00"
;----------------------------------------------------
        LD      A,060h          ; Send "0" to Credit Tens
        OUT     (0F7h),A        ; Output to Scoreboard
        LD      A,070h          ; Send "0" to Credit Ones
        OUT     (0F7h),A        ; Output to Scoreboard

;----------------------------------------------------
;            Store DIP Switch reading
;----------------------------------------------------
        IN      A,(0F2h)        ; Get DIP Switch A
        LD      (0BE0Fh),A      ; Store DIP A
;----------------------------------------------------
;              Initialize Variables
;----------------------------------------------------
        XOR     A               ; A = 0
        LD      B,A             ; B = 0
        LD      C,A             ; C = 0
        LD      (0BE04h),A      ; Clear Game Timer Control Register
        LD      (0BE05h),BC     ; Clear Game Timer
        LD      (0BE0Dh),A      ; Clear Number of Credits, Tens/Ones
        LD      (0BE0Eh),A      ; Clear Number of Credits, Hundreds
        LD      (0BE48h),A      ; Clear Timer Register

       
CALL    0C08Bh          ; Wait until System is Initialized

       
IN      A,(0F1h)        ; Get DIP Switch B
        BIT     0,A             ; Test B1, Diagnostic Mode
        JP      Z,L1F9B         ; Diagnostic Mode ON, so begin Diagnostics
        JP      L0136           ; Jump ahead one line

;----------------------------------------------------
;      Main Loop, Start with attract and cycle
;      thru all routines in the table
;----------------------------------------------------
L0136:  CALL    LC07F           ; Start Running the Main Loop
        JR      L0136           ; Just loop here







;----------------------------------------------------
;                Setup the Main Loop
;----------------------------------------------------
L013B:  LD      HL,0BE00h       ; Routine Pointer
        LD      (HL),000h       ; Reset Main loop to 1st routine (attract mode)
;----------------------------------------------------
;            HL = Pointer to Routine Table
;----------------------------------------------------
L0140:  LD      A,(HL)          ; Get A from HL
        SLA     A               ; Multiply A by 2
        LD      HL,0C03Dh       ; Get Pointer to Jump table
        ADD     A,L             ; Add Index
        LD      L,A             ; Create new pointer
        JR      NC,L014B        ; Check if carry is clear
        INC     H               ; Create new pointer
;----------------------------------------------------
;            Get Routine Address from Table A
;----------------------------------------------------
L014B:  LD      E,(HL)          ; E = Jump Address (low byte)
        INC     HL              ; Point to next spot
        LD      D,(HL)          ; D = Routine Address (high byte)
        EX      DE,HL           ; Put Routine Address in HL
;----------------------------------------------------
;                 Execute the Routine
;----------------------------------------------------
        CALL    L01AF           ; Execute Routine
;----------------------------------------------------
;       Check if we need to reset the Main Loop
;----------------------------------------------------
        LD      HL,0BE01h       ; Get GAME STATUS Register
        BIT     0,(HL)          ;
        JR      Z,L0164         ;               
        RES     0,(HL)          ;
        XOR     A               ;
        LD      (0A64Ah),A      ; Clear Length of Full Name
        LD      (0A68Bh),A      ; Clear Length of First Name
        JR      L013B           ; Reset Main Loop
;----------------------------------------------------
;            Loop through all the routines
;----------------------------------------------------
L0164:  LD      HL,0BE00h       ; Get Routine
        INC     (HL)            ; Point to next Routine
        LD      A,008h          ; Total Number of Routines is 8
L016A:  CP      (HL)            ; Have we done all 8 Routines?
        JP      NZ,L0140        ; No, so execute the Routine
        LD      (HL),003h       ; Yes, so start over at Routine #3
        JP      L0140           ; Execute Routine







;----------------------------------------------------
;            Get Jump Address from Table B
;----------------------------------------------------
L0173:  LD      HL,0BE03h       ;
        RES     1,(HL)          ;
        RES     3,(HL)          ; Clear Drop Mode
;----------------------------------------------------
;                Stop DecisionTimer
;----------------------------------------------------
        LD      HL,0BE23h       ; Get DecisionTimer Control Register
        LD      (HL),000h       ; Stop DecisionTimer
        LD      HL,0BE02h       ;
        LD      (HL),000h       ;                               
L0184:  LD      A,(HL)          ; Get Routine B Pointer
        SLA     A               ; Multiply by 2
        LD      HL,0C04Dh       ; Get Jump Table B
        ADD     A,L             ;
        LD      L,A             ;
        JR      NC,L018F        ;       
        INC     H               ;
L018F:  LD      E,(HL)          ;
        INC     HL              ;
        LD      D,(HL)          ;
        EX      DE,HL           ; Put Routine Address in HL
        CALL    L01AF           ; Execute Routine
        LD      HL,0BE03h       ; Get Register
        BIT     0,(HL)          ; Should we leave the main loop?
        JR      Z,L01A0         ; No, continue loop       
        RES     0,(HL)          ; Process request to leave loop
        RET                     ; Leave main loop

L01A0:  LD      HL,
0BE02h       ; Get Routine Index
        INC     (HL)            ; Point to next Routine
        LD      A,019h          ; There are #25 Routines
        CP      (HL)            ; Have we run all 25?
        JP      NZ,L0184        ; No, so keep looping
        LD      (HL),00Bh       ; Yes, so start over at Routine #11
        JP      L0184           ; Loop back




;----------------------------------------------------
;           Jump to Address in HL           
;----------------------------------------------------
L01AF:  JP      (HL)            ; Jump to address in HL
L01B0:  RET                     ; No need to return : Routine #7







;----------------------------------------------------
;             IM 1 Interrupt Routine           
;----------------------------------------------------
;    Save all registers before entering interrupt
;----------------------------------------------------
L01B1:  PUSH    BC              ; Save BC Register
        PUSH    DE              ; Save DE Register
        PUSH    HL              ; Save HL Register
        PUSH    AF              ; Save AF Register
        PUSH    IX              ; Save IX Register
        PUSH    IY              ; Save IY Register
        IN      A,(040h)        ; Get Interrupt Request Status
        BIT     3,A             ; Are there interrupts pending?
        JR      NZ,L01C8        ; Yes, begin Interrupt routines
        XOR     A               ; A = 0
        OUT     (0E0h),A        ; Reset interrupt
        NOP                     ; Pause
        IN      A,(0E0h)        ; Reset interrupt
        JP      L0352           ; Jump to end of interrupt

;----------------------------------------------------
;            Begin Interrupt Functions
;----------------------------------------------------
L01C8:  BIT     4,A             ; Test for timer interrupt
        JP      NZ,L02AE        ; No timer interrupt, so do next check
        CALL    L0416           ; Decrement All Timers
        LD      A,(0BE13h)      ; Get Coin Counter Debounce
        OR      A
        JR      Z,L0213                 
        LD      C,A             
; C
        LD      A,(0BE14h)
        BIT     
7,A
        JR      Z,L01FB                 
L01DE: 
DEC     A
        LD      (
0BE14h),A
       
AND     00Fh
        JR      NZ,L0213               
        LD      A,(
0A783h)
        RES     
4,A             ; Clear Coin Counter
        LD      (0A783h),A
       
OUT     (0F5h),A        ; Write to Coin Counter Hardware
        XOR     A
        LD      (
0BE14h),A
       
DEC     C
        LD      A,C
        LD      (
0BE13h),A
        JR      L0213                   
L01FB: 
OR      A               ; Coin Counter Debounce at zero?
        JR      NZ,L020F        ; No, so skip ahead
        LD      A,083h
        LD      (
0BE14h),A
        LD      A,(
0A783h)      ;
        SET     4,A             ; Increment Coin Counter
        LD      (0A783h),A
       
OUT     (0F5h),A        ; Write to Coin Counter Hardware
        JR      L0213                   

L020F:  LD      C,
001h
        JR      L01DE                   

L0213:  LD      A,(
0BE0Fh)      ; Get DIP Switch A
        AND     007h            ; Test for Free Play
        JR      Z,L0282         ; Free Play set so skip ahead
        LD      HL,0BE04h       ; Get Game Timer Control Register
        BIT     1,(HL)          ; Has Game Timer expired?
        JR      NZ,L0249        ; No, so start new game       
        BIT     0,(HL)
        JR      Z,L0282                 
        LD      A,(
0BE0Eh)
       
OR      A
        JR      NZ,L0282               
        LD      A,(
0BE0Dh)
        CP     
003h
        JR      NC,L0282               
        LD      HL,
0BE12h
       
DEC     (HL)
        BIT     
4,(HL)
        JR      Z,L0244
;----------------------------------------------------
;                Blank out scoreboard
;----------------------------------------------------                         
        LD      A,06Fh          ; Blank in Credit Tens
        OUT     (0F7h),A        ; Output to Scoreboard
        LD      A,07Fh          ; Blank in Credit Ones
        OUT     (0F7h),A        ; Output to Scoreboard
        JR      L0282           ;       

L0244: 
CALL    L0287           ; Update Credits on scoreboard
        JR      L0282             
L0249:  LD      (HL),
001h       ; Start Game Timer
;----------------------------------------------------
;     Get Time Units for Credit per DIP Settings
;----------------------------------------------------
        LD      HL,002A0h       ; Point to Time Units Table
L024E:  DEC     A               ; Check DIP Setting
        JR      Z,L0255         ; Correct DIP Setting so award Time
        INC     HL              ; Increment Table Pointer
        INC     HL              ; Increment Table Pointer
        JR      L024E           ; Loop until DIP Setting found
;----------------------------------------------------
;                 Award Time Units
;----------------------------------------------------
L0255:  LD      A,(HL)          ; Get Time Unit Value
        INC     HL              ; Point to next spot
        LD      H,(HL)          ; Get Time Unit Value
        LD      L,A             ; HL = Time Unit Value
        LD      (0BE05h),HL     ; Update Game Timer
;----------------------------------------------------
;             Subtract 1 Credit         
;----------------------------------------------------
        LD      A,(0BE0Dh)      ; Get Number of Credits, Tens/Ones
        SUB     001h            ; Subtract 1 credit
        DAA                     ; Make into a decimal number
        LD      (0BE0Dh),A      ; Store Number of Credits, Tens/Ones
        LD      C,A             ; C = Number of Credits
        LD      A,(0BE0Eh)      ; Get Number of Credits, Hundreds
        SBC     A,000h          ; Subtract one if carry is set
        DAA                     ; Make into a decimal number
        LD      (0BE0Eh),A      ; Store Number of Credits, Hundreds
        OR      C               ; A = A OR C
        LD      C,A             ; C = A, Store Credits temporarily
        CALL    L0287           ; Update Credits on scoreboard
        LD      A,C             ; A = C, Get Credits
        OR      A               ; Any Credits?
        JR      NZ,L0282        ; Yes, some credits remain, so jump ahead         
;----------------------------------------------------
;                No Credits Left
;----------------------------------------------------
        LD      HL,0BE48h
        SET     
7,(HL)
        LD      HL,
0BE04h
        LD      (HL),
000h       ; Stop Timer3

L0282: 
OUT     (0A0h),A
       
JP      L0352           ; Jump to end of interrupt




;----------------------------------------------------
;        Send Number of Credits to Scoreboard           
;----------------------------------------------------
L0287:  LD      A,(0BE0Dh)      ; Get Number of Credits
        AND     00Fh            ; Get lower nibble
        OR      070h            ; Store in Ones
        OUT     (0F7h),A        ; Output to Scoreboard
        LD      A,(0BE0Dh)      ; Get Number of Credits
        SRL     A               ; Shift byte right
        SRL     A               ; Shift byte right
        SRL     A               ; Shift byte right
        SRL     A               ; Shift byte right
        OR      060h            ; Store in Tens
        OUT     (0F7h),A        ; Output to Scoreboard
        RET                     ; Return




;----------------------------------------------------
;               Time Unit Table   
;----------------------------------------------------
L02A0:  .word   305  ;  30 seconds
        .word   458  ;  45 seconds
        .word   610  ;  60 seconds
        .word   712  ;  70 seconds
        .word   814  ;  80 seconds
        .word   966  ;  95 seconds
        .word  1119  ; 110 seconds
                 

;----------------------------------------------------
;  Check for interrupts from Speech Chip and Keyboard   
;----------------------------------------------------
L02AE:  BIT     2,A             ; Interrupt from Speech Chip?
        JR      NZ,L02B8        ; No, so skip speech stuff
        CALL    L1269           ; Send data to Speech Chip
        JP      L0352           ; Jump to end of interrupt
L02B8:  BIT     5,A             ; Interrupt from Keyboard?
        JR      NZ,L02C2        ; No, so skip keyboard stuff
        CALL    L0384           ; Process Keyboard Input
        JP      L0352           ; Jump to end of Interrupt

;----------------------------------------------------
;              Check Coin Slots
;----------------------------------------------------
L02C2:  IN      A,(0F1h)        ; Get DIP Switch B
        LD      C,A             ; C = DIP Switch B
        LD      HL,0BE10h       ; Coin Slot 1 Debounce Count
        BIT     4,C             ; Test Coin Slot 1
        CALL    L02D9           ; Call Coin Check
        LD      HL,0BE11h       ; Coin Slot 2 Debounce Count
        BIT     5,C             ; Test Coin Slot 2
        CALL    L02D9           ; Call Coin Check
        OUT     (0F3h),A        ; Request External Interrupt?
        JR      L0352           ; Jump to end of Interrupt


;----------------------------------------------------
;          Debounce Coin Slots
;----------------------------------------------------
; Coin Slot must be pressed for 3 consecutive
; readings to register a coin insertion.
;----------------------------------------------------
;      A = BE10, Debounce Coin Slot 1 Count
;      A = BE11, Debounce Coin Slot 2 Count
;----------------------------------------------------
L02D9:  LD      A,(HL)          ; Get Debounce Count
        JR      Z,L0319         ; Coin Slot pressed, so skip ahead
        OR      A               ; Does Debounce Count = 0?
        RET     Z               ; Yes, so return
        CP      002h            ; Debounce = 2?
        JR      NZ,L02E4        ; No, so check if it is 3
L02E2:  INC     (HL)            ; Increment Debounce Count
        RET                     ; Return
L02E4:  CP      003h            ; Debounce = 3?
        JR      NZ,L0316        ; No, so skip ahead
        LD      A,003h          ; Add 3 Credits
        CALL    L0320           ; Award Credits and Time
        IN      A,(0F2h)        ; Get DIP Switch A
        BIT     3,A             ; Test A4, Coins per Credit
        JR      NZ,L030F           
        LD      A,(
0BE0Eh)
       
OR      A
        JR      NZ,L030F
        LD      A,(
0BE0Dh)
        CP     
006h            ; Are there 6 credits left?
        JR      NC,L030F
        LD      A,(
0BE04h)
        BIT     
0,A             ; Timer3 still running?
        JR      NZ,L030F        ; Yes, so skip ahead
        LD      A,060h          ; Send "0" to Credit Tens
        OUT     (0F7h),A        ; Output to Scoreboard
        LD      A,070h          ; Send "0" to Credit Ones
        OUT     (0F7h),A        ; Output to Scoreboard
L030F:  LD      A,(0BE13h)      ; Get Number of Coins
        INC     A               ; Add 1 Coin
        LD      (0BE13h),A      ; Store Number of Coins 
L0316:  LD      (HL),000h       ; Reset Debounce Count to zero