*
*   APF 2K System BIOS
*   Version .009
*   ------------------
*
*   Disassembly and comments by Adam Trionfo
*
*   Revisions
*   ---------
*   Version .009  (July 30, 2010)
*      - No changes made yet
*
*   Version .008  (July 29, 2010)
*      - Completely commented the Write Routine

*   Version .007  (July 28, 2010)
*      - Many Updated to comments through-out code
*      
*   Version .006  (July 26, 2010)
*      - Renamed labels
*      
*   Version .005  (July 23, 2010)
*      - Commented the Left/Right Controller Input
*
*   Version .004  (July 22, 2010)
*      - Updated information about Interrupts (Not Complete)
*      - Added some information about Left and
*        Right Pad controllers
*      - Managed to get most everything that was defined as
*        bytes disassembled.  However, I still don't know what
*        it does.
*
*   Version .003 (August 14, 2009)
*      - Made various descriptive updates through-out
*        complete document.      
*
*   Version .002 (August 7, 2009)
*      - Converted strings for enhanced readability:
*         Menu Messages , "COMPUTER" and "FIRE"
*      -  Followed logic of APF Logo Write routine and
*         comments it.
*
*   Version .001 (August 6, 2009) - First VERY rough draft
*      - Disassembled using DASMx (Version 1.10)
*      - Fixed assembly error from DASM at $40A0-$40A1
*      - Replaced all ; at beginning of lines with *
*      - Replaced all db (define byte) with FCB 
*      - Removed all tabs and replaced with spaces
*      - Changed all opcodes to upper-case
*      - Make sure that source assembles correctly with AS11
*      - Use BINCVT.EXE to convert S19 file to binary file
*      - Make sure that new source matches byte-for-byte
*        with original 2K BIOS ROM in APF MP-1000.
*      - Replaced ships image in hex format with binary
*        format
*      - Commented (VERY loosely)
*      - Labeled interrupt vector area ($47F8-$47FF)
*      - Used DASM to disassemble part of IRQ Interrupt

*  PIA Equates

PIA_DRA   EQU   $2000       ; PIA Data Register A
PIA_CRA   EQU   $2001       ; PIA Control Register A
PIA_DRB   EQU   $2002       ; PIA Data Register B
PIA_CRB   EQU   $2003       ; PIA Control Register B

*  Equates (RAM Locations - Variables)

JOYDATA   EQU   $01F2       ; Joystick Data
TOPLEFT   EQU   $0200       ; Top-Left of Screen

*  Equates for Interrupt Flags and Counters

I60       EQU   $01FC       ; Interrupt Service Flag
I60J      EQU   $01C5       ; Address of Interrupt Service Routine
ISEC      EQU   $01FD       ; Interrupt Seconds Flag
ISECJ     EQU   $01C7       ; Interrupt, JSR Seconds Address
T60       EQU   $01F8       ; Interrupt Counter per Interrupt
TIME      EQU   $01FB       ; 1/60 Seconds Counter
SECOND    EQU   $01F9       ; Seconds Counter
MINUTE    EQU   $01FA       ; Minutes Counter

*  Misc Equates

TOPOFMENU EQU   $02C0       ; Top of Menu (7'th Row Down, Column 1)
CARTRIDGE EQU   $8000       ; First Byte of Cartridge Memory
CARTMENU  EQU   $8001       ; Cartridge Menu Location
MENUCHOIC EQU   $8003       ; Number of Cartridge Menu Choices
NUMPLAY   EQU   $8004       ; Display "Number of Players?"
EXECCART  EQU   $8005       ; Beginning of Code in Cartridge Area
EOS       EQU   $FF         ; End of String


          ORG   $4000       ; Start of APF BIOS Area

          CLRA              ; Clear accum A
          STAA  I60         ; Clear Interrupt Service Flag
          STAA  ISEC        ; Clear Interrupt Second Flag
          LDS   #$01E4      ; Load Stack Pointer with $01E4
          SEI               ; Stop servicing IRQ interrupts
          LDAB  #%00110101  ; Load Accum B with %00110101
          STAB  PIA_CRB     ; Initialize PIA Control Reg. B
          LDAA  #%11111111  ; Load Accum A
          STAA  PIA_DRB     ; Initialize PIA #1
          CLR   PIA_CRB     ; Clear PIA Control Reg. B
          STAA  PIA_DRB     ; Store %11111111 in PIA #1
          STAB  PIA_CRB     ; Store %00110101 in PIA Control Reg. B
          LDAB  #%00110100  ; Load Accum B with %00110100
          STAB  PIA_CRA     ; Store %00110100 in PIA Control Reg. A
          LDAA  #$EF        ; Load Accum A with $EF
          STAA  $01F7       ; Store $EF at $01F7
          CLR   $01F4       ; Clear $01F4 
          CLR   $01F6       ; Clear $01F6
          LDAA  #%00011111  ; Load Accum A with %00011111
          STAA  PIA_DRB     ; Store %00011111 in PIA #1
          CLI               ; Begin servicing IRQ interrupts
          JMP   BIOSSTART   ; Jump to Beginning of BIOS Set-Up

*  Set-Up Write APF Top-of-Menu
MENUTOP
          JSR   FILLSCRN    ; "Fill Screen" with Black
          LDX   #APFTOPROW  ; Load Index Reg with starting byte
*                             of top row of APF Message string
          STX   $01E6       ; Store Index Reg beginning at $01E6
          LDX   #$0208      ; Ninth byte of Screen Row 0.  The is
*                             where the top of 'a' in APF begins
          LDAA  #$06        ; Write six bytes
          JSR   WRITEAPF    ; Jump to Write APF Graphic Logo Routine
          LDX   #TVMICRO    ; Beginning of "TV MICRO-COMPUTER" String
          STX   $0006       ; Store Address of "TV MICRO-COMPUTER" String
          LDX   #$0268      ; Screen Address to write "TV MICRO-COMPUTER" 
          JMP   WRITESTR    ; Use "Write String Routine" to write menu

BIOSSTART
          BSR   MENUTOP    ; Write APF Top-of-Menu

*  Is a Cartridge Inserted?
*  ------------------------
*  If first byte of cartridge area ($8000) is $BB, then a 
*  cart is inserted.

          LDAA  CARTRIDGE   ; Load first byte of cart into Accum A
          CMPA  #$BB        ; Is the first byte of cart a $BB?
          BNE   NOCART      ; No cart inserted, so branch here
          LDX   CARTMENU    ; It IS a cart, get cart menu location 
          STX   $0006       ; Store Cart Menu Location
          LDX   #TOPOFMENU  ; Load Text Mode Screen Location,
*                             $02C0, 7'th Row Down 
          STX   $0004       ; Store Text Mode Screen Location
          JSR   READSTR     ; Use "Write String Routine"
          
*  Get Cartridge Menu Choice
*  -------------------------
*  What choice did the user make from the cartridge menu?
            
GETCHOIC
          BSR   ISJOYUSED   ; Get menu Choice from user          
          CMPA  #'0'        ; Was the choice a zero (not valid)?
          BEQ   GETCHOIC    ; If zero, then get another choice
          CMPA  MENUCHOIC   ; How many menu choices are there?  
          BGT   GETCHOIC    ; Is the choice > number of choices?

*  Valid Choice Made.  Now What?
          ANDA  #%00001111  ; Mask.  Keep LSB 
          STAA  $0000       ; Store the user's choice
          LDAA  NUMPLAY
          BEQ   STARTCART   ; If Players = 0, then start cartridge  
          
*  Display "Number of Players?"
*  ----------------------------
*  No cartridge EVER used this routine.  This is because it does
*  NOT work as it should.  Do NOT use it!
*  Perhaps this is a routine that APF meant to use, but never got 
*  around to fixing.  Make sure that $8004 is ALWAYS zero.  However, 
*  for fun, (and you know that you want to), try putting the number
*  of possible players into byte $8004 and see what happens...

          BSR   MENUTOP     ; Write APF Top-of-Menu  <--- BAD CALL HERE
          LDX   #PLAYERS    ; "HOW`MANY`PLAYERS?" String 
          STX   $0006       ; Store location of string
          LDX   #TOPOFMENU  ; Top of Menu location 
          JSR   WRITESTR    ; Write menu
GETNUMPY
          BSR   ISJOYUSED   ; Get menu Choice from user
          CMPA  #'0'        ; Was the choice a zero (not valid)? 
          BLE   GETNUMPY    ; Less then zero?  Try Again. 
          CMPA  $8004       ; How many possible players?
          BGT   GETNUMPY    ; Too Many Players?  Try Again.
          LDAA  #%00001111  ; Mask
          ANDA  JOYDATA     ; Keep LSB of Joystick Data
          STAA  $0001       ; Store Number of Players

STARTCART
          JSR   FILLSCRN    ; Fill Screen
          JMP   EXECCART    ; Begin executing code in the cart area

*  Branch here after the menu is on the screen and there is no
*  cart present at $8000
NOCART
          BSR   ISJOYUSED   ; Has either joystick been used?
          ANDA  #%00000011  ; Mask.  Keep bits 0 and 1
          STAA  $0000       ; Store choice
          JMP   L4380

* Was Either Joystick Used?
* If Carry is Set, then the Joystick was used in some way
* If Carry is Clear, the the Joystick was NOT used in some way   
ISJOYUSED
          JSR   RIGHTPAD    ; Get Input from Rightpad Controller
          BCS   RJOYUSED    ; Branch here if Right Controller was used       
          JSR   LEFTPAD     ; Get Input from Leftpad Controller
          BCC   ISJOYUSED   ; Loop until there is input from a controller
RJOYUSED
          LDAA  JOYDATA     ; Get Joystick Data is Joystick is used
L40B8:
          RTS               ; Return from Subroutine

PLAYERS   FCC   "HOW`MANY`PLAYERS?"  ; Screen Message
          FCB   EOS                  ; End of String

*  Write APF Graphic Logo to Menu Screen
*  ------------------------------------- 
*  This routine prints the APG logo to the screen.  It loops
*  three times, one for each line of the APF logo, before
*  exiting when hitting a $FF (End of String).
*
*  Important memory locations (still tentitive):
*  $0108,$0109 = Where to write on screen
*  $01EA       = Holds number of bytes to write
*  $01ED       = Holds result of Width of screen - length
*                of string
*  $01EB       = Current byte of string (I think)
*  $0004       = Also current byte of string??
*  $01EE,$01EF = Holds next byte to write to

WRITEAPF
          STAA  $01EA       ; Store how many bytes to write
          STX   $01E8       ; Store Index Reg to $01E8 and $01E9
          LDAA  #32         ; Load Accum A with Width of Screen
          SUBA  $01EA       ; Subtract contents of $01EA
          STAA  $01ED       ; Store new value of Accum A to 01ED
L40D9:
          LDX   $01E6       ; Load Index Reg with String address
          LDAA  $00,X       ; Load Accum A with first byte of string
          CMPA  #EOS        ; Does Accum A hold $FF (End of String)?
          BEQ   L40B8       ; If End of String, branch to RTS 
          STAA  $01EB       ; Current byte of string
          INX               ; Increment position in String
          STX   $01E6       ; Store Index Reg to $01E6 and $01E7
          LDAB  $01EA       ; Store how many bytes to write
L40EC:
          LDAA  $00,X       ; Load Accum A with next byte of string
          INX               ; Point to next byte of string
          STX   $0004       ; Store "Next Byte of String" address
          LDX   $01E8       ; Load where to write string data
          STAA  $00,X       ; Store byte of string to screen
          INX               ; Increment screen memory by one 
          STX   $01E8       ; Store current screen memory location
          LDX   $0004       ; Load "Next Byte of String" address
          DECB              ; Subtract 1 from number of bytes left to write
          BNE   L40EC       ; Finished writing string?  If not, loop
          LDAA  $01ED       ; Load Accum A with string width size
          LDX   $01E8       ; Load current screen write location
          JSR   L411D       ; Jump to Subroutine

          STX   $01E8       ; Store Next Write location
          LDX   $01E6       ; Load first byte of string after $01
          LDAB  $01EA       ; Load number of bytes to write
          DEC   $01EB       ; Decrement current byte of string
          BNE   L40EC       ; Current byte of string <> 0?
          LDX   $0004       ; Load Current byte of string
          STX   $01E6       ; Store current byte of string
          BRA   L40D9       ; Branch always

L411D:
          STX   $01EE       ; Holds next screen byte to write to
          ADDA  $01EF       ; Add A with second byte of next
*                             write byte location
          STAA  $01EF       ; Store added number in $01EF
          BCC   L412B       ; Branch if carry clear (?)
          INC   $01EE       ; Increment next screen byte to
*                             write to (??)
L412B:
          LDX   $01EE       ; After first run, holds location of
*                             next write for 2'nd APF line
          RTS               ; Return to Main APF Logo Write Routine

L412F:
          PSHA
          STX   $01EE
          LDAA  $01EF
          SBA
          STAA  $01EF
          BCC   L413F
          DEC   $01EE
L413F:
          LDX   $01EE
          PULA
          RTS
          
*  Write String
*  ------------
*  This routine will:
*  
*     1) Write a string using any valid "ASCII" characters
*        from $00-$7F.  HOWEVER, the characters from $00-$3F
*        (Light Green character on Dark Green Background) are
*        AUTOMATICALLY changed to ASCII $40-7F (Dark Green
*        character on Light Green Background).  However, this
*        does NOT change what the character is, just the
*        foreground and background color of the character.
*     2) Write consecutive byte(s) of any fill-byte (any "ASCII" 
*        character, 00-$FF) using control codes.
*     3) Write one or more "spaces," $20, (Dark Green) using
*        control codes.
*    
*  This routine will begin printing with the byte found at the 
*  first byte of the string and continue until an $FF (End of
*  String delimiter), Control Byte, or an invalid
*  Control Byte is reached.
*
*  INVALID Control Bytes are Most Significant four Bits are (where
*  x is "don't care"):
*  
*     $8x, $9x, $Ax, $Bx
*     
*  Invalid control bytes are IGNORED and skipped (nothing is
*  written to memory).  The next byte is then read in the string.
*  
*  Valid Control Bytes are Most Significant four Bits.  They are
*  (where x is "don't care"):
*
*     $Cx, $Dx, $Ex, $Fx
*     
*  The Least Significant four Bits can be any value.  These will
*  represent the number of "spaces" (dark green) or "fill-bytes"
*  to write to memory.
*    
*  How to use the Control Bytes (CB):
*     1) If the Control Byte's MSBs are $E or $F, then write
*        "Space," $20, which is the color "Dark Green"
*     2) If the Control Byte's MSBs are $C or $D, then write
*        the next byte in the string (the "fill-byte"). 
*    
*  The Control Byte determines how many "spaces" or "fill-bytes" to
*  write by AND'ing the Control Byte with $1F.
*  
*  An example of using a "Fill-Byte:"
*  
*     Control Byte is $D3 and the next character is $8F
*  
*         $D3 = 1101 0011
*     AND $1F = 0001 1111
*               ---------
*      Result = 0001 0011 = $13 = 19 in decimal
*      
*     So, Control Byte $D3, followed by $8F, will fill nineteen 
*     consecutive bytes with $8F (Light Green).
*     
*  An example of using a "Space:"
*  
*         $F4 = 1111 0100
*     AND $1F = 0001 1111
*               ---------
*               0001 0100 = $14 = 20 in decimal
*               
*     Control Byte $F4 will fill 20 consecutive bytes with
*     "Spaces," ($20), which is the color "Dark Green."
*               
*  The maximum number of "spaces" or "fill-bytes" varies depending on
*  the Control Byte used:
*
*    $F = Max 30 "spaces"     $D = Max 31 spaces of "fill-byte"
*    $E = Max 15 "spaces"     $C = Max 31 spaces of "fill-byte"
*     
*  Keep in mind that $FF can't be used as a Control Byte as it is
*  already an "End of String" delimiter.
*         
*  Memory locations used in this routine:
*  
*     $0004 = Text Mode Memory Screen Location Address
*     $0006 = Current Byte of String Address  

WRITESTR  STX   $0004       ; Store Screen Location Address
READSTR   BSR   LOADCHAR    ; Load Current Byte and Make Checks              
          LDX   $0006       ; Load Current Byte of String Address  
          LDAA  $00,X       ; Get Current Byte of String
          CMPA  #EOS        ; Is Current Byte the "End of String?"
          BNE   READSTR     ; Not "End of String,"" so read next byte
          RTS               ; Reached "End of String" 

*  
LOADCHAR  BSR   CHECKEOS    ; Check if current byte is "End of String"
          BLT   CONTLBYT    ; If MSb is high, (80-$FF), then is 
*                             it a Control Byte?  
          LDX   $0004       ; Load Memory Screen Location Address
          ORAA  #%01000000  ; Mask
          STAA  $00,X       ; Write current byte of string to screen
          INX               ; Increment Memory Screen Location Address
          STX   $0004       ; Store Memory Screen Location Address
          BRA   LOADCHAR    ; Get another byte from string  

*  Check if current byte is "End of String"
*  If not EOS, then update Current Byte of String Address  
CHECKEOS  LDX   $0006       ; Load String Location
          LDAA  $00,X       ; Get Current Byte of String
          CMPA  #EOS        ; Is Current Byte the "End of String?" 
          BEQ   EXITEOS     ; Yes, it IS "End of String," so no Update
          INX               ; Not "EOS," so increment String Address
          STX   $0006       ; Store as Current Byte of String Address 
EXITEOS
          TAB               ; Copy Current Byte of String to Accum B
          RTS 

*  Check if Current Byte is Control Byte
CONTLBYT  CMPA  #EOS        ; Is Current Byte the "End of String?" 
          BEQ   EXITCONTL   ; Yes it is EOS, so exit subroutine
          ANDA  #%00011111  ; Mask $1F.  Get # of Chars to write
          ANDB  #%01100000  ; Mask $60 
          LSRB              ; Logical Shift Right Accum B for
          LSRB              ; a total of five times.
          LSRB
          LSRB
          LSRB
          BEQ   EXITCONTL   ; Bad Input: Is $8x, $9x, $Ax, or $Bx            
          DECB              ; 
          BEQ   LOADCHAR    ; Not a Control Byte
          DECB              ;
          BEQ   GETFILL     ; Valid Control Byte ($Cx or $Dx), Get Fill-Byte
          LDAB  #$20        ; Valid Control Byte ($Ex or $Fx) so use Space 
GOTFILL
          LDX   $0004       ; Get Screen Location Address 

*  Write Character Loop (Fill-Byte or Space)
CHARLOOP  STAB   $00,X      ; Write character to screen
          INX               ; Advance to next Screen Location Address 
          DECA              ; Decrease number of characters left to write
          BNE   CHARLOOP    ; Any more characters left to write?
          STX   $0004       ; No, store Current Screen Location Address 
EXITCONTL
          RTS
          
*  Get Fill-Byte Character to Write for Write Character Loop
GETFILL   LDX   $0006       ; Load Current Byte of String Address  
          LDAB  $00,X       ; Get Fill-byte character to write in loop  
          INX               ; Increment to next Byte of String Address 
          STX   $0006       ; Store as Current Byte of String Address
          BRA   GOTFILL     ; Go loop through memory with this byte 

*  Joystick Column and Row Data Table
*  ----------------------------------
*  This holds the 16 possible locations of
*  the Joystick:
*     South, East, North and West
*     ? = CL
*     ! = First Button / EN
*     Numbers 0-9

JOYTABLE  FCC   "1047"
          FCC   "SENW"
          FCC   "3?69"
          FCC   "2!58"       

L41A8:
          LDAA  #$04
          STAA  $01EB
          STX   $01EC
          LDAA  $01,X
          BNE   L41B8
          LDAA  #$F7
          STAA  $00,X
L41B8:
          LDAA  $00,X
          STAA  $01F7
          RTS

*  Get Input from Leftpad Controller
LEFTPAD
          LDX   #$01F3
          BSR   L41A8
L41C3:
          BSR   L4220
          LDAA  PIA_DRA     ; Read Controller Row
          LSRA
          LSRA
          LSRA
          LSRA
          CMPA  #%00001111  ; Mask $0F 
          BNE   L41F7
          BSR   L424C
          DEC   $01EB
          BNE   L41C3
          BRA   L41F0
 
* This subroutine is run as soon as there is no cart present

*  Get Input from Rightpad Controller
RIGHTPAD
          LDX   #$01F5
          BSR   L41A8
L41DE:
          BSR   L4220
          LDAA  PIA_DRA     ; Read Controller Row
          ANDA  #%00001111  ; Mask $0F
          CMPA  #%00001111  ; Compare to $0F
          BNE   L41F7
          BSR   L424C
          DEC   $01EB
          BNE   L41DE
L41F0:
          LDX   $01EC
          CLR   $01,X
          CLC
          RTS

L41F7:
          LDAB  #$03
          BSR   L425B
          ADDB  $01F1
          STAB  $01F1
          LDX   $01F0
          LDAB  $00,X
          LDX   $01EC
          CMPB  $01,X
          BEQ   L4219
          LDAA  $01F7
          STAA  $00,X
          STAB  $01,X
L4214:
          STAB  JOYDATA     ; Joystick Data
          SEC
          RTS
 
L4219:
          CMPB  #$45
          BGE   L4214
          CLC
          RTS
 
          FCB   $01         ; NOP?

* Has a button been pressed?  (I THINK)
* First time branched here from $41DE
 
L4220:
          LDAA  #%11100000  ; Set-up mask   
          ANDA  PIA_DRB     ; Mask bits 5,6 and 7
*                           ; Bit 5 - A/G
*                           ; Bit 6 - GM0
*                           ; Bit 7 - Int / Ext
          STAA  $01F0       ; Store Mask results
          LDAA  #%00011111  ; Set-up mask
          ANDA  $01F7       ; Mask bits 0-4
*                           ; Bit 4 - Unknown
*                           ; Bit 3 - Unknown
*                           ; Bits 0-2 - Controller
*                                        scan row
          ORAA  $01F0       ; 
          STAA  PIA_DRB     ; PIA Data Register B 
          LDAB  #$04        ; Load Accum B with $04
          BSR   L425B
          LDX   #JOYTABLE   ; First Byte of Joystick Column/Row Table
          STX   $01F0
          CLC               ; Clear the Carry Bit
          ASLB              ; Shift Left Accum B
          ASLB              ; Shift Left Accum B
          ADDB  $01F1
          STAB  $01F1
          BCC   L424B       ; Branch if Carry Clear
          INC   $01F0
L424B:
          RTS
 
L424C:
          LDAB  $01F7
          SEC
          RORB
          BCC   L4257
L4253:
          STAB  $01F7
          RTS
 
L4257:
          LDAB  #$F7
          BRA   L4253
 
L425B:
          CLR   $01E5
          SEC
L425F:
          LSRA
          BCC   L4268
          INC   $01E5
          DECB
          BNE   L425F
L4268:
          LDAB  $01E5
          RTS

*  Sounds
*  ------
*  The newsletters say that sounds to be made:
*
*  $426E - "Beep"
*  $4282 - "Beep" and "Whistle Noise"
*  $428B - "Click" 
  
L426C:
          LDAB  #$05
L426E:                      
          STAB  $01EC       ; "Beep"
          BSR   L428B
L4273:
          DECB
          BNE   L4273
          BSR   L428B
          INC   $01EC
          LDAB  $01EC
L427E:
          DECB
          BNE   L427E
          LDAB  $01EC
          BSR   L428B
          CMPB  #$5F
          BNE   L4273
          RTS
L428B:
          SEI               ; "Click"
          LDAA  PIA_CRB     ; PIA Control Register B
          EORA  #$08
          STAA  PIA_CRB     ; PIA Control Register B
          CLI
          RTS

*  Fill Screen
*  -----------
*  Blank the screen by filling the shape table from
*  ($3FF-$200) with '$80' (Black)
* 
*  If the first line of this rotuine is skipped, then this
*  routine can be used to fill the screen with all one code.
*  Just place the code to-be-filled-with in Accum A before
*  branching to ONECODE. 

FILLSCRN  LDAA  #$80        ; Load Accum A with $80 (black)
ONECODE   LDX   #$0400      ; Load Index Reg with last byte of screen +1
FILLLOOP  DEX               ; Subtract 1 from the Index Reg.  On
*                             first screen write this will be $0399
          STAA  $00,X       ; Store fill-code at screen location
          CPX   #TOPLEFT    ; Compare Index Reg to start of screen
          BNE   FILLLOOP    ; Screen not totally full?  Then loop

          RTS               ; Screen totally blanked.  Return 

*  IRQ Interrupt Servicing Routine
*  -------------------------------
*
*  Information taken from the "APF Programming and Technical
*  Assistance Manual," pages 10-11.  See the manual for
*  additional information and examples on how to use
*  this IRQ routine.
* 
*  The interrupt system is driven by the field sync output of
*  the VDG.  This occurs every 1/60 of a second.  It is fed to
*  the MC6800 IRQ via the MP1000 PIA.
*  
*  This IRQ routine:
*  1) Allows jumps to subroutines whose addresses are set
*     by the user.
*  2) Keeps count of number of interrupts as well as seconds
*     and minutes.
*
*  Flags and Counters:
*    
*  I60    - Interrupt Service Flag - If non-zero, causes an
*           immediate JSR from interrupt routine.  The JSR
*           address is contained in I60J.  Both I60 and I60J
*           are user set.
*  I60J   - Address of Interrupt Service Routine - JSR Address
*           if I60 is non-zero.
*  ISEC   - Interrupt Seconds Flag - If ISEC is non-zero, then
*           every 60 interrupts (1 second) a JSR will occur.
*           The JSR address is contained in ISECJ.  Both ISEC
*           and ISECJ are user set.   
*  ISECJ  - Interrupt, JSR Seconds Address - The JSR address if
*           ISEC is non-zero and 1/60 second counter overflows.
*  T60    - Interrupt Counter per Interrupt - Incremented by
*           each interrupt.  Clears to zero when overflows (at
*           256th interrupt) and starts count again.
*  TIME   - 1/60 Seconds Counter - Keeps count of 1/60 of
*           seconds.  Clears when reaches 60 and then causes
*           SECOND to be incremented. 
*  SECOND - Seconds Counter - Incremented every second.  Clears
*           when reaches 60 and increments MINUTE.
*  MINUTE - Minutes Counter - Increments every 60 seconds.
*           Clears when reaches 60.

L42A4:
          LDAA  PIA_DRB     ; PIA Data Register B
          TST   I60         ; Is there an IRQ Service Request?
          BEQ   NOIRQ       ; If no IRQ request, then branch 
*  Service the IRQ Service Request 
          LDX   I60J        ; Address of Interrupt Service Routine
          JSR   $00,X       ; Jump to Interupt Service Routine

*  No Service Needed for IRQ Service Request
NOIRQ
          INC   T60         ; Increment Interrupt Counter
          BVC   T60OVR      ; Overflow of Interrupt Counter?
          CLR   T60         ; If = 256, Clear Interrupt Counter

*  Overflow of Interrupt Counter 
T60OVR
          INC   TIME        ; Increment 1/60 Seconds Counter
          LDAA  #59D        ; Set-up for TIME compare 
          CMPA  TIME        ; Is 1/60 Seconds Counter = 60?
          BGT   NOT60       ; Branch if TIME > 60
*  TIME is > 60
          TST   ISEC        ; Interrupt, Seconds Flag
          BEQ   NOISEC
*  Service Interrupt Seconds Flag  
          LDX   ISECJ       ; Interrupt, JSR Seconds Address
          JSR   $00,X       ; Service Routine for Seconds Address
*  ISEC Does NOT Need to be serviced, so clear time
*  and update SECOND and MINUTE.
NOISEC
          CLR   TIME        ; Clear 1/60 Seconds Counter
          CLC               ; Clear Carry 
          LDAA  SECOND      ; Seconds Counter
          CMPA  #$59        ; 
          BEQ   L42DF       ;
          ADDA  #$01        ;
          DAA               ; Decimal Adjust Accum A
          STAA  SECOND      ; Seconds Counter
NOT60    
          RTI               ; Return from IRQ Interrupt
         
L42DF:
          CLR   SECOND      ; Clear Seconds Counter
          LDAA  MINUTE      ;
          CMPA  #$99        ;
          BEQ   L4306       ;
          ADDA  #$01        ;
          DAA               ;
          STAA  MINUTE      ; 
          RTI               ; Return from IRQ Interrupt
 
L42F0:
          PSHA
          SEI
          STS   $01E8
          LDS   $01E6
          DES
L42F9:
          PULA
          STAA  $00,X       ; Eventually, this reads the first byte of
*                             the Rocket Patrol ship
          INX
          DECB
          BNE   L42F9
          LDS   $01E8
          CLI
          PULA
          RTS

L4306:
          CLR   MINUTE      ; Clear Minutes Counter 
          RTI               ; Return from IRQ Interrupt

 
*  Large APF graphic used on Menu Screen
*  ------------------------------------- 
* APF Graphic, Line 1
APFTOPROW FCB   $01         ; Start of String (?) 
          FCB   $EC, $EA, $EE, $EA, $EE, $E8
* APF Graphic, Line 2
          FCB   $01         ; Start of String (?)
          FCB   $9E, $9A, $9E, $98, $9E, $98
* APF Graphic, Line 3
          FCB   $01         ; Start of String (?)
          FCB   $DC, $D8, $D8, $80, $D8, $80
          FCB   EOS         ; End of String

*  Rocket Patrol Menu String
*  -------------------------
          
TVMICRO   FCC   "TV MICRO-COMPUTER"
          FCB   $CF         ; Control Byte - Fill 15 spaces with next byte 
          FCB   $80         ; Fill-Byte - ASCII $80, (Black)                       
          FCC   "COPYRIGHT APF1978"
          FCB   $DB         ; Control Byte - Fill 27 spaces with next byte 
          FCB   $80         ; Fill-Byte - ASCII $80, (Black)  
          FCB   $CC         ; Control Byte - Fill 12 spaces with next byte 
          FCB   $80         ; Fill-Byte - ASCII $80, (Black) 
          FCB   $E8         ; Control Byte - Fill 8 spaces with
*                                            ASCII $20, "Space" (Dark Green)                                                       
          FCC   "ROCKET PATROL"
          FCB   $F4         ; Control Byte - Fill 20 spaces with  
*                                            ASCII $20, "Space" (Dark Green) 
          FCB   $F7         ; Control Byte - Fill 23 spaces with
*                                            ASCII $20, "Space" (Dark Green)                 
          FCC   "1. TWO PLAYER"
          FCB   $D3         ; Control Byte - Fill 19 spaces with next byte  
          FCB   $8F         ; Fill-Byte - ASCII $8F, (Light Green)                   
          FCC   "2. PLAYER AND COMPUTER"   
          FCB   $CA         ; Control Byte - Fill 10 spaces with next byte
          FCB   $8F         ; Fill-Byte - ASCII $8F, (Light Green)                 
          FCB   EOS         ; Control Byte - End of String


*  Run after Menu Choice is selected
*  Is this the beginning of Rocket Patrol?
L4380:
          LDAA  PIA_DRB     ; PIA Data Register B
          ANDA  #%00111111  ; Mask $3F
          ORAA  #%11000000  ; Mask $C0
          STAA  PIA_DRB     ; PIA Data Register B
          LDAA  PIA_CRA     ; PIA Control Register A
          ANDA  #%11000111  ; Mask $C7
          ORAA  #%00111000  ; Mask $38
          STAA  PIA_CRA     ; PIA Control Register A
*  Fill screen with zeros
          CLRA              ; Prepare to fill Screen with '0'
          JSR   ONECODE     ; Fill Screen with Zeros
*  Write Rocket Patrol Score Area   
          LDX   #SCOREAREA  ; Top four rows of Rocket Patrol Score Area
          STX   $0006
          LDX   #TOPLEFT    ; Top-Left Corner of Screen
          JSR   WRITESTR    ; Use Write String Routine
*          
          LDX   #GETRIGHT   ; Address of JSR for Input from Rightpad Controller
          LDAA  $0000
          DECA
          BEQ   L43B8
          LDX   #COMPUTER   ; Location of "COMPUTER" message
          LDAB  #$08
          LDAA  #$31
          JSR   L447F
          LDX   #L4545
L43B8:
          STX   $0190
*  Fill from $0000-$0180 with $54
          LDX   #$0000      ; Start fill of memory at $0000 
          LDAA  #$54        ; Place a $54 into Accum A
FILL54    STAA  $00,X       ; Store $54
          INX               ; Increment to next area of memory for fill
          CPX   #$0180      ; Has $0000-$0180 been filled with $54?
          BNE   FILL54      ; If not, then loop until done
*  Set-up to set zero to 30 Consecutive Bytes at $0142 
          CLRA              ; Setup to Store Zero
          LDAB  #30         ; Setup to write for 30 consecutive bytes 
          LDX   #$0142      ; Setup to Start Address in memory
          JSR   SETSAME     ; Set zero to 30 Consecutive Bytes at $0142
          LDX   #$4551
          STX   I60J        ; Interrupt JSR Service Address
          LDX   #$012F
          LDAA  #$02
          STAA  $0192
          STX   $015D
          BSR   L444B
          LDAA  #$C0
          LDX   #$0350
          STAA  $07,X
          LDX   #$47A0      ; This is a "unknown" byte - Data?
          STX   $01E6
          LDX   #$0181
          LDAB  #$0C
          JSR   L42F0
          JSR   L4652
          LDX   #$47AC
          STX   $01E6
          LDX   #$0142
          LDAB  #$0A
          JSR   L42F0
          INC   I60         ; Increment Interrupt Service Flag
          CLR   MINUTE      ; Clear Minutes Counter
          CLR   SECOND      ; Clear Seconds Counter
          CLR   $018E
          CLR   $018F
          LDX   #$0142
          STX   $0140
          JSR   L469B
L4422:
          LDAA  MINUTE      ; Minutes Counter
          CMPA  #$02
          BLT   L4433
          CMPA  #$03
          BGT   L4463
          LDX   #$44BC
          STX   $0190
L4433:
          LDAB  $015F
          BEQ   L4442
          JSR   L428B
          LDAB  #$DF
L443D:
          DECB
          BNE   L443D
          BRA   L4433
 
L4442:
          BSR   L444B
          LDX   $0190
          JSR   $00,X                 ;INFO: INDEX JUMP
          BRA   L4422
 
L444B:
          LDX   #$0770
          JSR   L4779
          LDAA  #$18
          STAA  $077C
          LDAA  #$7E
          STAA  $077D
          LDX   $015D
          LDAA  #$57
          STAA  $00,X
          RTS
 
L4463:
          CLR   MINUTE      ; Minutes Counter
L4466:
          LDAA  #$07
          CMPA  MINUTE      ; Minutes Counter
          BNE   L4466
          CLR   I60         ; Clear Interrupt Service Flag
          LDAA  PIA_DRB     ; PIA Data Register B
          ANDA  #$7F
          STAA  PIA_DRB     ; PIA Data Register B
          LDAA  #$80        ; Prepare to fill Screen with '$80' (Black)
          JSR   ONECODE     ; Fill Screen with $80 (Black)
L447D:
          BRA   L447D
 
L447F:
          STAA  $01E9
          LDAA  #$02
          STAA  $01E8
          STX   $01E6
          LDX   $01E8
          JMP   L42F0

L4490:
          STAA  $01E8
          LSRA
          LSRA
          LSRA
          LSRA
          BEQ   L44A5
          ABA
          
L449A:
          STAA  $00,X
          LDAA  $01E8
          ANDA  #$0F
          ABA
          STAA  $01,X
          RTS
L44A5:
          LDAA  #$60
          BRA   L449A
L44A9:
          RTS

GETRIGHT  JSR   RIGHTPAD    ; Get Input from Rightpad Controller
L44AD:
          LDAA  #$8F
          LDAB  #$CF
          BSR   L44EF
          LDAB  #$3D
          LDX   #$018E
          BCS   L44F7
          BRA   L44CC
          JSR   LEFTPAD
          LDAA  #$CF
          LDAB  #$8F
          BSR   L44EF
          LDAB  #$21
          LDX   #$018F
          BCS   L44F7
L44CC:
          LDAA  $015C
          BEQ   L44A9
L44D1:
          JSR   L428B
          LDAA  #$70
L44D6:
          DECA
          BNE   L44D6
          DEC   $015C
          BNE   L44D1
          LDAA  $00,X
          ADDA  #$01
          DAA
          STAA  $00,X
          STAB  $0193
          LDX   $0192
          LDAB  #$70
          BRA   L4490
L44EF:
          LDX   #TOPLEFT    ; Top-Left Corner of Screen
          STAA  $20,X
          STAB  $3C,X
          RTS
L44F7:
          LDX   $015D
          LDAA  JOYDATA     ; Load Direction of Joystick
          CMPA  #$45        ; Is the direction East?
          BEQ   L4520
          CMPA  #$21
          BEQ   L452C
          CMPA  #$57        ; Is the direction West?
          BNE   L44A9
          DEX
          CPX   #$0125
          BEQ   L44A9
          LDAA  #$54
          STAA  $01,X
L4513:
          STX   $015D
          LDAA  #$57
          STAA  $00,X
          LDAB  #$50
          JSR   L426E
L451F:
          RTS
L4520:
          CPX   #$013A
          BEQ   L451F
          LDAA  #$54
          STAA  $00,X
          INX
          BRA   L4513
L452C:
          LDAA  #$C5
          STAA  $015F
          LDX   $015D
          STX   $0158
          LDAA  #$57
          STAA  $00,X
          LDX   #FIRE       ; Location of "Fire" String
          LDAA  #$2C
          LDAB  #$04
          JMP   L447F
L4545:    LDAA  #$06
          BITA  $01F8
          BEQ   L454E
          BSR   L452C
L454E:
          JMP   L44AD

          LDAA  PIA_CRB     ; PIA Control Register B
          ANDA  #%11111100  ; Mask $FC
          ORAA  #%00000011  ; Mask $03
          STAA  PIA_CRB     ; PIA Control Register B
          LDX   #$4566
          STX   $01C5
          JSR   L4627
          BRA   L45A0

          LDX   #$4551
          STX   $01C5
          LDAA  PIA_CRB     ; PIA Control Register B
          ANDA  #%11111100  ; Mask $FC
          ORAA  #%00000001  ; Mask $01
          STAA  PIA_CRB     ; PIA Control Register B
          LDX   #$0064
L4579:
          DEX
          BNE   L4579
          LDAA  PIA_DRB     ; PIA Data Register B
          ANDA  #%01111111  ; Mask $7F
          STAA  PIA_DRB     ; PIA Data Register B
          LDX   #$01A0
L4587:
          DEX
          BNE   L4587
          LDAA  PIA_DRB     ; PIA Data Register B
          ORAA  #%10000000  ; Mask $80
          STAA  PIA_DRB     ; PIA Data Register B
          JSR   L467C
          LDAA  #$01
          BITA  $01FA
          BEQ   L459F
          JSR   L467C
L459F:
          RTS

L45A0:
          LDAA  $015F
          BEQ   L459F
          DEC   $015F
          BNE   L45B3
          LDX   $0158
          LDAB  #$54
          STAB  $00,X
          BRA   L461D
L45B3
          LDX   #$0142
          BSR   L45DA
          LDX   #$014C
          BSR   L45DA
          LDX   #$0152
          BSR   L45DA
          ANDA  #$03
          BNE   L4626
          LDX   #$0770
          LDAA  $00,X
          BNE   L45EC
L45CD:
          LDAA  $02,X
          STAA  $00,X
          CLR   $02,X
          INX
          CPX   #$077E
          BNE   L45CD
          RTS
L45DA:          
          STX   $015A
          LDX   $00,X
          INX
          LDAB  #$04
L45E2:
          CPX   $0158
          BEQ   L460C
          INX
          DECB
          BNE   L45E2
          RTS
L45EC:
          LDAA  $00,X
          STAA  $0E,X
          LDAA  $01,X
          STAA  $0F,X
          CLR   $00,X
          CLR   $01,X
          LDX   $0158
          LDAA  #$54
          STAA  $00,X
          LDAB  #$20
          JSR   L412F
          STX   $0158
          LDAA  #$57
          STAA  $00,X
          RTS
L460C:
          LDX   $015A
          LDAB  #$BF
          STAB  $015C
          LDAB  #$20
          STAB  $04,X
          CLR   $05,X
          CLR   $015F
L461D:
          LDX   #$8F8F
          STX   $022C
          STX   $022E
L4626:
          RTS

L4627:
          LDX   #$0350
          CLC
          ROR   $07,X
          BCS   L4630
          RTS

L4630:
          LDAA  #$C0
          STAA  $07,X
          LDAA  #$54
          BSR   L4654
          LDX   #$0181
          LDAB  #$06
L463D:
          LDAA  $01,X
          ANDA  #$1F
          CMPA  #$1F
          BNE   L464B
          LDAA  $01,X
          ANDA  #$E0
          STAA  $01,X
L464B:
          INC   $01,X
          INX
          INX
          DECB
          BNE   L463D
L4652:
          LDAA  #$55
L4654:
          LDAB  #$06
          LDX   #$0181
          STX   $01C9
          STAA  $015A
L465F:
          LDX   $00,X
          LDAA  $00,X
          CMPA  #$55
          BEQ   L466B
          CMPA  #$54
          BNE   L4670
L466B:
          LDAA  $015A
          STAA  $00,X
L4670:
          LDX   $01C9
          INX
          INX
          STX   $01C9
          DECB
          BNE   L465F
          RTS
 
L467C:
          LDX   #$0142
          STX   $0140
          LDX   $08,X
          LDAB  #$10
L4686:
          CLC
          ROL   $40,X
          ROL   $30,X
          ROL   $20,X
          ROL   $10,X
          ROL   $00,X
          BCS   L4698
          INX
          DECB
          BNE   L4686
 
L4697:
          RTS
L4698:
 
          LDX   $0140
 
L469B:
          LDX   $08,X
          JSR   L4779
          LDX   $0140
          LDX   $06,X
          STX   $01E6
          LDX   $0140
          LDX   $08,X
          LDAA  #$10
          JSR   L411D
          LDAB  #$40
          JSR   L42F0
          LDX   #$0142
          STX   $0140
          BSR   L4706
          LDX   #$014C
          LDAA  $00,X
          ADDA  $01,X
          BEQ   L46CD
          STX   $0140
          BSR   L4706
L46CD:
          LDX   #$0152
          TST   $01,X
          BEQ   L46D9
          STX   $0140
          BRA   L4706
 
L46D9:
          LDX   #$0142
          LDAA  $04,X
          CMPA  #$08
          BNE   L46F0
          LDX   #$00DF
          STX   $014C
          STX   $014E
          LDX   #$014C
          BRA   L4700
 
L46F0:
          CMPA  #$0C
          BNE   L4697
          LDX   #$00BF
          STX   $0152
          STX   $0154
          LDX   #$0152
L4700:
          LDAA  #$48
          STAA  $05,X
          BRA   L471C
 
L4706:
          LDX   $00,X
          DEX
          STX   $015A
          LDX   $0140
          LDAA  $015A
          STAA  $00,X
          LDAA  $015B
          STAA  $01,X
L4719:
          LDX   $0140
L471C:
          LDAA  $05,X
          LDAB  $04,X
          INC   $04,X
          CMPB  #$1F
          BGT   L4745
          DECB
          BLT   L4735
          BEQ   L4734
          DECB
          BEQ   L4733
          DECB
          BEQ   L4732
          INCA
L4732:
          INCA
L4733:
          INCA
L4734:
          INCA
L4735:
          LDAB  $05,X
          LDX   $00,X
L4739:
          STAB  $00,X
          INX
          INCB
          CBA
          BGE   L4739
          LDAA  #$54
          STAA  $00,X
          RTS
 
L4745:
          SUBB  #$1F
          CMPB  #$05
          BEQ   L4760
          ABA
          LDAB  $05,X
          ADDB  #$04
          PSHB
          LDX   $00,X
          LDAB  #$54
          STAB  $05,X
          PULB
L4758:
          STAB  $04,X
          DEX
          DECB
          CBA
          BLE   L4758
          RTS
 
L4760:
          LDX   $00,X
          LDAA  #$54
          STAA  $05,X
          LDX   $0140
          LDAA  #$48
          STAA  $05,X
          CLR   $04,X
          LDAA  $02,X
          STAA  $00,X
          LDAA  $03,X
          STAA  $01,X
          BRA   L4719
 
L4779:
          CLRA
          LDAB  #$10

*  Set Same Value to a Consecutive Group of addresses
*  --------------------------------------------------
*  (Details in Tech Manual in chapter 8, Page 8)
*
*  Enter Routine with:
*     X Reg - Start Address in memory to get set
*     B Reg - Number of Consecutive Bytes
*     A Reg - Value to be Stored
 
SETSAME   STAA  $00,X       ; Store Value
          INX               ; Increment to next address to store value 
          DECB              ; Decrement number of times through loop 
          BNE   SETSAME     ; If not done, then keep setting to same value 
          RTS
 
* Rocket Patrol Score Area
* ------------------------
* Data for Top Four Rows of Rocket Patrol Game Screen
* This data is referred to from $4398.

SCOREAREA
*  Row 0 ($0200-$021F)
          FCB   $DF  ; Control Byte - Fill 31 fill-bytes of next byte  
          FCB   $83  ; Fill-Byte - (Top-Half Black, Bottom-Half Light Green) 
          FCB   $C1  ; Control Byte - Fill 1 fill-byte of next byte 
          FCB   $83  ; Fill-Byte - (Top-Half Black, Bottom-Half Light Green)
*  Row 1 ($0220-$023F)
          FCB   $DF  ; Control Byte - Fill 31 fill-bytes of next byte
          FCB   $8F  ; Fill-Byte - (Solid Light Green Block)
          FCB   $C1  ; Control Byte - Fill 1 fill-byte of next byte
          FCB   $8F  ; Fill-Byte - (Solid Light Green Block)
*  Row 2 ($0240-$025F) 
          FCB   $DF  ; Control Byte - Fill 31 fill-bytes of next byte
          FCB   $8C  ; Fill-Byte - (Top-Half Light Green, Bottom-Half Black)
          FCB   $C1  ; Control Byte - Fill 1 fill-byte of next byte
          FCB   $8C  ; Fill-Byte - (Top-Half Light Green, Bottom-Half Black)
*  Row 3 ($0260-$027F)
          FCB   $DF  ; Control Byte - Fill 31 fill-bytes of next byte
          FCB   $80  ; Fill-Byte - (Solid Black)
          FCB   $C1  ; Control Byte - Fill 1 fill-byte of next byte
          FCB   $80  ; Fill-Byte - (Solid Black)
          FCB   EOS  ; End of String

*  Strings
COMPUTER  FCC   "COMPUTER"
FIRE      FCC   "FIRE"

* This unknown area is referenced from $43EB
          FCB   $00, $45, $00
          FCB   $74, $00, $89, $00
          FCB   $D9, $00, $E7, $00
          FCB   $F2, $01, $00, $00
          FCB   $FF, $00, $48, $47
          FCB   $B6, $02, $80
          
* The Rocket Patrol ship is made up of four parts.
* Each part of the ship is 8 bits wide by 16 tall.
ROCKET:

* Rocket Patrol Ship - 1 of 4
SHIP01:   FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000011
          FCB   %00001111
          FCB   %11111111
          FCB   %00001111
          FCB   %00000111
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000
          FCB   %00000000

* Rocket Patrol Ship - 2 of 4
SHIP02:   FCB   %11111111
          FCB   %11000000
          FCB   %00000000
          FCB   %00000001
          FCB   %00000011
          FCB   %00000111
          FCB   %00111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %00111111
          FCB   %00000001
          FCB   %11000000
          FCB   %11111111

* Rocket Patrol Ship - 3 of 4
SHIP03:   FCB   %11111111
          FCB   %00111111
          FCB   %01111111
          FCB   %11111110
          FCB   %11111011
          FCB   %11111110
          FCB   %11111011
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111111
          FCB   %11111110
          FCB   %00111011
          FCB   %11111111

* Rocket Patrol Ship - 4 of 4
SHIP04:   FCB   %11110000
          FCB   %11000000
          FCB   %11000000
          FCB   %10000000
          FCB   %01000000
          FCB   %10000000
          FCB   %01000000
          FCB   %11000111
          FCB   %10001111
          FCB   %11111111
          FCB   %11111000
          FCB   %11001000
          FCB   %11000011
          FCB   %10000000
          FCB   %10000000
          FCB   %11110000

          FCB   $FF, $00    ; BYTES STILL UNKNOWN

* Interrupt Vectors
          FDB   $42A4       ; IRQ Interrupt Vector
          FDB   $4000       ; SWI Interrupt Vector
          FDB   $4000       ; NMI Interrupt Vector 
          FDB   $4000       ; Reset Interrupt Vector
