Difference between revisions of "7800 NTSC BIOS"

From 8BitDev.org - Atari 7800 Development Wiki
Jump to: navigation, search
 
Line 5: Line 5:
  
 
<pre>
 
<pre>
; Disassembly of bios7800.bin
+
; Disassembly of the Atari 7800 NTSC BIOS (bios7800.bin)
; Disassembled Sun Mar 08 20:30:38 1998
+
; Originally disassembled by DiStella v2.0 on Sun Mar 08 20:30:38 1998
; Using DiStella v2.0
 
 
;
 
;
; Comments added by Keith Henrickson <flipper@phin.com>
+
; This version has been heavily commented and refactored for maximum clarity,
; Further commented by Daniel Boris <dboris@home.com>
+
; with generic labels (e.g., LF400) renamed to descriptive ones.
; Fixed to compile correctly with dasm, and additional comments by
+
; The goal is to explain the inner workings of the BIOS for educational
; Mike Saarna. You can't have my email!
+
; and development purposes.
 +
;
 +
; Original comments by:
 +
;  - Keith Henrickson <flipper@phin.com>
 +
;   - Daniel Boris <dboris@home.com>
 +
;   - Mike Saarna (dasm fixups, additional comments)
 +
;  - Gemini 2.5 Pro (semantic meaningful label names, comments galore)
 +
;
 +
; The code must be assembled with DASM.
 
;
 
;
  
 
  processor 6502
 
  processor 6502
  
; some misc equates
+
;=============================================================================
 +
;
 +
; I. HARDWARE AND MEMORY EQUATES
 +
;
 +
;=============================================================================
 +
 
 +
; --- Misc System Equates ---
 
LFD80 = $FD80
 
LFD80 = $FD80
CartKey          = $FF80
+
CartKey          = $FF80   ; Start address of the 8-byte cartridge security key
CartRegion        = $FFF8
+
CartRegion        = $FFF8   ; Cartridge region/signature byte
CartKeyStartPage  = $FFF9
+
CartKeyStartPage  = $FFF9   ; Cartridge ROM start page and signature byte
CartResetVectorHi = $FFFD
+
CartResetVectorHi = $FFFD   ; High byte of the cartridge's RESET vector address
LF112 = $F112
+
LF112             = $F112
LF118 = $F118
+
LF118             = $F118
LF460   =   $F460
+
LF460             = $F460
LF700   =   $F700
+
LF700             = $F700
LF800   =   $F800
+
LF800             = $F800
  
 +
; --- 7800 System Control ---
 +
INPTCTRL = $01              ; Input Control Register. Controls memory mapping (BIOS, RAM, Cart) and TIA access.
  
; 7800 system
+
; --- TIA (Television Interface Adapter) Registers (for 2600 Mode) ---
 +
VSYNC  =  $00              ; Vertical Sync
 +
VBLANK  =  $01              ; Vertical Blank
 +
WSYNC  =  $02              ; Wait for Horizontal Sync
 +
RSYNC  =  $03              ; Reset Horizontal Sync Counter
 +
COLUP0  =  $06              ; Color-Luminance for Player 0
 +
COLUPF  =  $08              ; Color-Luminance for Playfield
 +
COLUBK  =  $09              ; Color-Luminance for Background
 +
PF2    =  $0F              ; Playfield Register 2
 +
RESP1  =  $11              ; Reset Player 1
 +
GRP0    =  $1B              ; Player 0 Graphics
 +
GRP1    =  $1C              ; Player 1 Graphics
  
INPTCTRL = $01
+
; --- Maria (Custom Graphics Chip) Registers ---
 +
BACKGRND = $20            ; Background Color
 +
POC1    =  $21            ; Palette 0, Color 1
 +
P0C2    =  $22            ; Palette 0, Color 2
 +
POC3    =  $23            ; Palette 0, Color 3
 +
MWSYNC  =  $24            ; Maria Wait for Sync
 +
P1C1    =  $25            ; Palette 1, Color 1
 +
P1C2    =  $26            ; Palette 1, Color 2
 +
P1C3    =  $27            ; Palette 1, Color 3
 +
MSTAT    =  $28            ; Maria Status Register (VBLANK, etc.)
 +
DPPH    =  $2C            ; Display List Pointer High Byte
 +
DPPL    =  $30            ; Display List Pointer Low Byte
 +
CTRL    =  $3C            ; Maria Control Register (DMA, graphics mode)
  
; TIA
+
; --- Zero Page RAM Vectors/Variables ---
 +
DLIAddr      =  $F4        ; RAM vector for Display List Interrupts (NMI)
 +
ConsoleRegion =  $FE        ; Console region byte (used in cart verification)
  
VSYNC  = $00
+
;=============================================================================
VBLANK  = $01
+
;
WSYNC  = $02
+
; II. CARTRIDGE AUTHENTICATION & MODE SWITCHING LOGIC
RSYNC  = $03
+
;
COLUP0  = $06
+
; This entire block of code from $F000 to $F880 is not executed from ROM.
COLUPF  = $08
+
; Instead, it is copied to RAM ($2300-$2700) by the main BIOS init routine
COLUBK  = $09
+
; at Bios_InitSystem. The jump to $2306 then begins execution from RAM.
PF2    = $0F
+
;
RESP1  = $11
+
;=============================================================================
GRP0    = $1B
 
GRP1    = $1C
 
 
 
;Maria
 
 
 
BACKGRND =  $20
 
POC1    =  $21
 
P0C2    =  $22
 
POC3    = $23
 
MWSYNC  = $24
 
P1C1    = $25
 
P1C2    = $26
 
P1C3    = $27
 
MSTAT    = $28
 
DPPH    = $2C
 
DPPL    = $30
 
CTRL    = $3C
 
 
 
DLIAddr      = $F4
 
ConsoleRegion = $FE
 
  
 
       ORG $F000
 
       ORG $F000
  
LF000: pha                ; This is the NMI routine.
+
; --- NMI Vector (ROM) ---
       jmp (DLIAddr)      ; RAM NMI vector
+
; This is the hardware NMI vector. It immediately jumps to a RAM vector at $F4,
 +
; which allows the running program (including the BIOS itself) to define its
 +
; own NMI handler.
 +
NmiVector_Rom:
 +
      pha                ; This is the NMI routine.
 +
       jmp (DLIAddr)      ; Jump to RAM NMI vector.
  
  
 
       ORG $F400
 
       ORG $F400
  
; this code is designed to be executed while stored in ram at 2300.
+
; --- RAM Routine: Cartridge Detection and Authentication ---
LF400
+
; This code is designed to be executed from RAM starting at address $2300.
SwitchTo2600Mode1
+
; Its primary job is to determine if a valid, signed 7800 cartridge is
      jmp    $26C2                  ; Enter 2600 mode.
+
; present. If it is, the system boots in 7800 mode. If not, it attempts
SwitchTo2600Mode2
+
; to boot in 2600 mode.
      jmp    $26C2                  ; Enter 2600 mode.
 
  
CartTest
+
RamExec_Start:
       lda   #$16                    ; ($2306)
+
SwitchTo2600Mode1:
       sta   INPTCTRL                ; Switch in cart + enable Maria
+
       jmp   Enter2600Mode          ; Branch to the 2600 mode initialization routine.
 +
SwitchTo2600Mode2:
 +
       jmp   Enter2600Mode          ; Branch to the 2600 mode initialization routine.
  
       ldy    #$FF                    ;
+
CartTest:
       ldx    #$7F                    ;
+
      lda    #$16                    ; Value to enable Maria and map in the cartridge ROM.
CartTestLoop
+
      sta    INPTCTRL                ; Switch in cart + enable Maria.
       lda    LFE00,X                ; Compare same FE7F+ ROM with differing opcodes,
+
 
       cmp    LFD80,Y                ;   to avoid false positives from a floating bus.
+
       ldy    #$FF                    ; Initialize Y to $FF.
       bne    SwitchTo2600Mode1      ; Switch to 2600 mode
+
       ldx    #$7F                    ; Initialize X to $7F.
 +
; --- Cartridge Presence Test ---
 +
; This loop compares two different ROM regions ($FD80-$FDFF and $FE00-$FE7F).
 +
; If a cartridge is not present, the data bus "floats", and reading any address
 +
; might return the last value seen on the bus (or garbage). By comparing two
 +
; regions that should contain different data, the BIOS can detect this state.
 +
; If the data is the same, it's likely a floating bus, so no cart is present.
 +
CartPresenceCheck_Loop:
 +
       lda    LFE00,X                ; Read from the $FExx range.
 +
       cmp    LFD80,Y                ; Compare with the $FDxx range.
 +
       bne    SwitchTo2600Mode1      ; If they differ, the test passes (so far). Branch if they are the same (fail).
 
       dey                            ;
 
       dey                            ;
 
       dex                            ;
 
       dex                            ;
       bpl    CartTestLoop
+
       bpl    CartPresenceCheck_Loop  ; Loop for 128 bytes.
  
 +
; --- Cartridge Reset Vector Test ---
 +
; A valid 7800 or 2600 cart must have a valid reset vector. A vector of $FFFF
 +
; or $0000 typically indicates an empty socket or a problem.
 
       lda    CartResetVectorLo      ;
 
       lda    CartResetVectorLo      ;
 
       and    CartResetVectorHi      ;
 
       and    CartResetVectorHi      ;
 
       cmp    #$FF                    ;
 
       cmp    #$FF                    ;
       beq    SwitchTo2600Mode1      ; If RESET vector is FFFF, then go 2600.
+
       beq    SwitchTo2600Mode1      ; If RESET vector is $FFFF, then go 2600.
 
       lda    CartResetVectorLo      ;
 
       lda    CartResetVectorLo      ;
 
       ora    CartResetVectorHi      ;
 
       ora    CartResetVectorHi      ;
       beq    SwitchTo2600Mode1      ; If RESET vector is 0000, then go 2600.
+
       beq    SwitchTo2600Mode1      ; If RESET vector is $0000, then go 2600.
       lda    CartRegion              ; "Region verification"
+
 
       ora    #ConsoleRegion
+
; --- Cartridge Signature/Region Verification ---
       cmp    #$FF                    ;  
+
; This is a series of simple, quick checks on bytes in the $FFF8-$FFF9 region
 +
; of the cartridge ROM to see if it looks like an official 7800 cart.
 +
       lda    CartRegion              ; Read signature byte at $FFF8.
 +
       ora    #ConsoleRegion         ; OR with the console's region byte ($FE).
 +
       cmp    #$FF                    ;
 
       bne    SwitchTo2600Mode2      ; If low-bit of CartRegion=0, then go 2600.
 
       bne    SwitchTo2600Mode2      ; If low-bit of CartRegion=0, then go 2600.
 
       lda    CartRegion              ;
 
       lda    CartRegion              ;
       eor    #$F0                    ; Invert high nibble
+
       eor    #$F0                    ; Invert high nibble.
       and    #$F0                    ; Extract high nibble
+
       and    #$F0                    ; Isolate the high nibble.
       bne    SwitchTo2600Mode2      ; If high nibble was not F, then go 2600.
+
       bne    SwitchTo2600Mode2      ; If high nibble was not originally $F, then go 2600.
       lda    CartKeyStartPage        ;
+
       lda    CartKeyStartPage        ; Read signature byte at $FFF9.
       and    #$0B                    ;  
+
       and    #$0B                    ;
       cmp    #$03                    ;  
+
       cmp    #$03                    ;
       bne    SwitchTo2600Mode2      ; If low nibble FFF9 was not 3 or 7, go 2600.
+
       bne    SwitchTo2600Mode2      ; If low nibble of $FFF9 was not 3 or 7, go 2600.
 +
 
 +
; --- Cartridge Header Processing ---
 +
; If the quick checks pass, the BIOS proceeds with the full authentication.
 
       lda    CartKeyStartPage        ;
 
       lda    CartKeyStartPage        ;
       and    #$F0                    ; Extract ROM start from high nibble
+
       and    #$F0                    ; Extract ROM start page from high nibble of $FFF9.
       sta    $EE                    ; Store it  
+
       sta    $EE                    ; Store it in zero page.
       sta    $2406                  ; Store it a couple of places for auth. (whocares)
+
       sta    $2406                  ; Store it in RAM for the authentication routine.
 
       cmp    #$40                    ;
 
       cmp    #$40                    ;
       bcc    SwitchTo2600Mode2      ; If ROM start < than 4, then go 2600
+
       bcc    SwitchTo2600Mode2      ; If ROM start page < $40 (i.e., address < $4000), fail.
       sbc    #$01                    ; Subtract 1.
+
       sbc    #$01                    ;
       cmp    CartResetVectorHi      ; High byte of reset vector
+
       cmp    CartResetVectorHi      ; Compare ROM start page with high byte of reset vector.
       bcs    SwitchTo2600Mode2      ; If high-byte of start is >=, go 2600
+
       bcs    SwitchTo2600Mode2      ; If start page is >= reset vector high byte, fail.
       jsr    $2536                  ; Start the authentication process.
+
       jsr    $2536                  ; If all checks pass, start the full authentication process.
 +
 
 +
; --- Obfuscated Authentication Code ---
 +
; The following code is part of the digital signature verification. It involves
 +
; complex mixing, rotating, and lookup operations on the cartridge's security
 +
; key and internal BIOS data tables. Its purpose is to be difficult to analyze
 +
; and replicate. The high-level goal is to compute a hash from the cart key
 +
; and compare it against an expected result.
  
 
       lda    #$00
 
       lda    #$00
       sta    $F0    
+
       sta    $F0
       jsr    $241B  
+
       jsr    $241B
       lda    #$16  
+
       lda    #$16
       sta    INPTCTRL
+
       sta    INPTCTRL
       ldx    #$00  
+
       ldx    #$00
       txa          
+
       txa
LF46D: sta    $1800,X  
+
Auth_RamFillLoop1:
       dex          
+
      sta    $1800,X
       bne    LF46D 
+
       dex
       pha          
+
       bne    Auth_RamFillLoop1
       ldy    #$7F  
+
       pha
LF476: lda    LFF00,Y  
+
       ldy    #$7F
       sta    $1800,Y  
+
Auth_CopyRomToRamLoop:
       dey          
+
      lda    LFF00,Y
       cpy    #$F8  
+
       sta    $1800,Y
       bne    LF476 
+
       dey
       lda    #$2E  
+
       cpy    #$F8
       sta    $2409  
+
       bne    Auth_CopyRomToRamLoop
       lda    #$24  
+
       lda    #$2E
       sta    $240A  
+
       sta    $2409
 +
       lda    #$24
 +
       sta    $240A
  
LF48B
+
Auth_MainLoop1:
       jsr    $241B  
+
       jsr    $241B
       pla          
+
       pla
       jsr    $23FF  
+
       jsr    $23FF
       pha          
+
       pha
       inc    $2406  
+
       inc    $2406
       lda    $2406  
+
       lda    $2406
       cmp    #$FF     
+
       cmp    #$FF
       bne   LF48B 
+
      bne    Auth_MainLoop1
 +
 
 +
      jsr    $241B
 +
      jsr    $2412
 +
      jsr    $2412
 +
      lda    #$36
 +
      sta    $2409
 +
      lda    #$24
 +
      sta    $240A
 +
      dec    $2406
 +
Auth_MainLoop2:
 +
      jsr    $241B
 +
      pla
 +
      jsr   $23FF
 +
      pha
 +
       dec    $2406
 +
      lda    $2406
 +
      cmp    $EE
 +
      bcs    Auth_MainLoop2
 +
      lda    #$60
 +
      sta    CTRL
 +
      ldx    #$77
 +
Auth_XorAndStoreLoop:
 +
      lda    $1800,X
 +
      eor    $1850,X
 +
      eor    $1888,X
 +
      sta    $1A00,X
 +
      dex
 +
      bpl    Auth_XorAndStoreLoop
 +
      lda    $1A00
 +
      and    #$07
 +
      sta    $1A00
 +
      lda    #$00
 +
      ldx    #$04
 +
      sta    $1A00,X
 +
      sta   $2000,X
  
      jsr    $241B 
+
; --- Final Authentication Check ---
      jsr    $2412 
+
; After all the cryptographic hashing, this is the final comparison.
      jsr    $2412 
+
; It compares two blocks of memory in RAM. If they match, the cart is authentic.
      lda    #$36   
+
       ldx    #$77
      sta    $2409 
+
Auth_FinalCompareLoop:
      lda    #$24   
+
       lda    $2000,X                 ; Read from one workspace area.
      sta    $240A 
+
       cmp    $1A00,X                 ; Compare with the computed hash.
      dec    $2406 
+
       bne    Auth_FailAndSwitchTo2600; If they don't match, authentication fails.
LF4B3: jsr    $241B 
+
       dex
      pla           
+
       bpl    Auth_FinalCompareLoop  ; Loop until all bytes are compared.
      jsr    $23FF 
+
       jmp    Enter7800Mode          ; AUTHENTICATION PASSED: Jump to 7800 mode init.
      pha           
+
Auth_FailAndSwitchTo2600:
      dec    $2406 
+
      jmp    Enter2600Mode          ; AUTHENTICATION FAILED: Jump to 2600 mode init.
      lda    $2406 
 
      cmp    $EE   
 
      bcs    LF4B3 
 
      lda    #$60   
 
      sta    CTRL 
 
       ldx    #$77  
 
LF4CB: lda    $1800,X
 
      eor    $1850,X
 
      eor    $1888,X
 
      sta    $1A00,X
 
      dex           
 
      bpl    LF4CB 
 
      lda    $1A00 
 
      and    #$07   
 
      sta    $1A00 
 
       lda   #$00   
 
      ldx    #$04   
 
      sta    $1A00,X
 
      sta   $2000,X  
 
      ldx    #$77        ; That was a lot, but we end up here, comparing
 
LF4EE: lda    $2000,X      ; two parts of memory. If they match, then
 
       cmp    $1A00,X     ; go to 7800 mode....
 
       bne    LF4FC        ; otherwise go to 2600 mode.
 
       dex                 ; nop out above branch to allow user-written
 
       bpl    LF4EE        ; carts to run -- I think.
 
       jmp    $26B9        ; 7800 mode init
 
LF4FC: jmp    $26C2        ; 2600 mode init.
 
  
  
LF500 =  $F500             ; F500 is partway through the next opcode
+
; --- Authentication Subroutines ---
       ldx    #$00         ; more authentication stuff all the way through
+
; More opaque subroutines used by the main authentication algorithm.
LF501: adc    $1800,X
+
Auth_Sub_MixAndLookup_Equate =  $F500
       adc    LFF00,X  
+
       ldx    #$00
       tay          
+
Auth_Sub_MixAndLookup_Loop:
       lda    $2DD5,Y  
+
      adc    $1800,X
       sta    $1800,X  
+
       adc    LFF00,X
       inx          
+
       tay
       bne    LF501 
+
       lda    $2DD5,Y
       rts          
+
       sta    $1800,X
 +
       inx
 +
       bne    Auth_Sub_MixAndLookup_Loop
 +
       rts
  
       ldx    #$00  
+
       ldx    #$00
LF514: rol    $1800,X  
+
Auth_Sub_RotateRam_Loop:
       inx          
+
      rol    $1800,X
       bne    LF514 
+
       inx
       rts          
+
       bne    Auth_Sub_RotateRam_Loop
 +
       rts
  
;$241B
+
; Subroutine at $241B - This routine briefly disables the cartridge to access BIOS ROM/RAM.
       php          
+
       php
       dec    $F0    
+
       dec    $F0
       bpl    LF52C 
+
       bpl    Auth_Sub_AccessBios_Done
       lda    #$02  
+
       lda    #$02
       sta    INPTCTRL
+
       sta    INPTCTRL
LF524: lda    $F0    
+
Auth_Sub_AccessBios_WaitLoop:
       bmi    LF524 
+
      lda    $F0
       lda    #$16  
+
       bmi    Auth_Sub_AccessBios_WaitLoop
       sta    INPTCTRL
+
       lda    #$16
LF52C: plp          
+
       sta    INPTCTRL
       rts          
+
Auth_Sub_AccessBios_Done:
 +
      plp
 +
       rts
  
LF52E: .byte $C7,$65,$AB,$CA,$EE,$F7,$83,$09
+
; --- Authentication Signature Data Tables ---
LF536: .byte $E1,$D0,$92,$67,$62,$B6,$72,$55,$8E,$91,$DC,$C5,$81,$BE,$78,$20
+
; These large blocks of byte data are part of the digital signature scheme.
 +
; They are used as lookup tables and keys during the verification process.
 +
AuthData_Table1: .byte $C7,$65,$AB,$CA,$EE,$F7,$83,$09
 +
AuthData_Table2: .byte $E1,$D0,$92,$67,$62,$B6,$72,$55,$8E,$91,$DC,$C5,$81,$BE,$78,$20
 
       .byte $59,$B7,$E6,$3D,$06,$45,$AF,$C8,$08,$31,$38,$D1,$FB,$73,$84,$A9
 
       .byte $59,$B7,$E6,$3D,$06,$45,$AF,$C8,$08,$31,$38,$D1,$FB,$73,$84,$A9
 
       .byte $17,$FC,$34,$87,$A3,$94,$FA,$90,$B8,$ED,$CE,$3B,$5B,$0A,$43,$D9
 
       .byte $17,$FC,$34,$87,$A3,$94,$FA,$90,$B8,$ED,$CE,$3B,$5B,$0A,$43,$D9
 
       .byte $F3,$53,$82,$B3,$0D,$6D,$5A,$60,$9D,$51,$A7,$B9
 
       .byte $F3,$53,$82,$B3,$0D,$6D,$5A,$60,$9D,$51,$A7,$B9
LF572: .byte $11,$10,$BC,$E4,$7F,$80,$41,$E7,$E3
+
AuthData_Table3: .byte $11,$10,$BC,$E4,$7F,$80,$41,$E7,$E3
LF57B: .byte $F6,$56,$26,$35,$EC,$D6,$DF,$0C,$7F,$F4,$9E,$AC,$52,$46,$EF,$CF
+
AuthData_Table4: .byte $F6,$56,$26,$35,$EC,$D6,$DF,$0C,$7F,$F4,$9E,$AC,$52,$46,$EF,$CF
 
       .byte $BF,$A2,$3F,$A4,$13,$15,$97,$4A,$1C,$B0,$42,$8C,$B1,$05,$58,$80
 
       .byte $BF,$A2,$3F,$A4,$13,$15,$97,$4A,$1C,$B0,$42,$8C,$B1,$05,$58,$80
 
       .byte $18,$77,$2B,$02,$3E,$A8,$49,$1A,$6A
 
       .byte $18,$77,$2B,$02,$3E,$A8,$49,$1A,$6A
LF5A4: .byte $CB,$6E,$0B,$8A,$EB,$F1,$4F,$14,$79,$8B,$D8,$9F,$9B,$57,$19,$F8
+
AuthData_Table5: .byte $CB,$6E,$0B,$8A,$EB,$F1,$4F,$14,$79,$8B,$D8,$9F,$9B,$57,$19,$F8
 
       .byte $2A,$2D,$76,$0E,$E8,$2E,$4B,$F9,$07,$03,$DE,$93,$16,$7E,$D4,$E5
 
       .byte $2A,$2D,$76,$0E,$E8,$2E,$4B,$F9,$07,$03,$DE,$93,$16,$7E,$D4,$E5
 
       .byte $B2,$F0,$7D,$7A,$DA,$D2,$A1,$CC,$1D,$E0,$5E,$23,$A0,$95,$22,$1E
 
       .byte $B2,$F0,$7D,$7A,$DA,$D2,$A1,$CC,$1D,$E0,$5E,$23,$A0,$95,$22,$1E
 
       .byte $36,$85,$FE,$1F,$39
 
       .byte $36,$85,$FE,$1F,$39
LF5D9: .byte $AA,$89,$96,$AD,$0F,$2F,$C0,$47
+
AuthData_Table6: .byte $AA,$89,$96,$AD,$0F,$2F,$C0,$47
LF5E1: .byte $27,$5D,$24,$EA,$C3,$A5,$F5,$21,$5F,$1B,$40,$8F,$AE,$74,$25,$DD
+
AuthData_Table7: .byte $27,$5D,$24,$EA,$C3,$A5,$F5,$21,$5F,$1B,$40,$8F,$AE,$74,$25,$DD
 
       .byte $C1,$7C,$CD,$A6,$70,$D7,$33,$7B,$2C,$75,$BB,$86,$99,$BD,$54
 
       .byte $C1,$7C,$CD,$A6,$70,$D7,$33,$7B,$2C,$75,$BB,$86,$99,$BD,$54
LF600: .byte $9A,$6C,$63,$32,$48,$4C,$8D,$BA
+
AuthData_Table8: .byte $9A,$6C,$63,$32,$48,$4C,$8D,$BA
LF608: .byte $5C,$61,$C4,$4E,$29,$37,$12,$C6,$98,$9C,$D5,$69,$6B,$E2,$04,$4D
+
AuthData_Table9: .byte $5C,$61,$C4,$4E,$29,$37,$12,$C6,$98,$9C,$D5,$69,$6B,$E2,$04,$4D
 
       .byte $E9,$C2,$88,$3A,$DB,$64,$01,$44,$6F,$B5,$F2,$30,$28,$FD,$50,$71
 
       .byte $E9,$C2,$88,$3A,$DB,$64,$01,$44,$6F,$B5,$F2,$30,$28,$FD,$50,$71
 
       .byte $3C,$B4,$66,$68,$C9,$D3,$CA,$83,$C7,$AB,$F7,$65,$09,$EE
 
       .byte $3C,$B4,$66,$68,$C9,$D3,$CA,$83,$C7,$AB,$F7,$65,$09,$EE
  
       ldx    #$77      ;($2536)
+
; --- Main Authentication Routine ($2536) ---
       stx    $E4    
+
; This routine is the entry point for the signature verification process.
       stx    $E5    
+
; It copies the 128-byte security key from the cartridge ROM into RAM.
LF63C: lda    CartKey,X  ;Read Key
+
       ldx    #$77      ; ($2536) Start of routine, X=119
       sta    $1901,X          ;Store it
+
       stx    $E4
       sta    $2000,X          ;Store it again
+
       stx    $E5
       dex                      ;next byte of key
+
Auth_CopyCartKey_Loop:
       bpl    LF63C            ;Continue
+
      lda    CartKey,X  ; Read a byte from the cart security key area ($FF80-FFFF).
 +
       sta    $1901,X          ; Store it in RAM work area 1.
 +
       sta    $2000,X          ; Store it in RAM work area 2.
 +
       dex                      ; next byte of key
 +
       bpl    Auth_CopyCartKey_Loop ; Loop until all 128 bytes are copied.
  
 
       lda    #$02      ;
 
       lda    #$02      ;
       sta    INPTCTRL  ;Disable cart  
+
       sta    INPTCTRL  ; Disable cart ROM to access BIOS routines.
       jsr    LFB84    ;Init display
+
       jsr    Display_InitLogo ; Initialize Maria for the Fuji logo display.
       jsr    $257B  
+
       jsr    $257B
       dec    $F2    
+
       dec    $F2
       ldx    #$77  
+
       ldx    #$77
       stx    $E4    
+
       stx    $E4
LF658: lda    LFED5,X  
+
Auth_CopyInternalKey_Loop:
       sta    $1901,X  
+
      lda    LFED5,X
       dex          
+
       sta    $1901,X
       bpl    LF658 
+
       dex
       lda    $E1    
+
       bpl    Auth_CopyInternalKey_Loop
       sta    $E3    
+
       lda    $E1
       jsr    $25E1  
+
       sta    $E3
       dec    $F2    
+
       jsr    $25E1
LF66A: lda    $E0    
+
       dec    $F2
       sta    $2572  
+
Auth_CopyWorkspace_Start:
       ldx    #$77  
+
      lda    $E0
LF671: lda    $1800,X  
+
       sta    $2572
LF674: sta    $2000,X  
+
       ldx    #$77
       dex          
+
Auth_CopyWorkspace_Loop:
       bpl    LF671 
+
      lda    $1800,X
       rts          
+
Auth_CopyWorkspace_Store:
   
+
      sta    $2000,X
       jsr    $2639  ;($257B)
+
       dex
       ldy    $E5    
+
       bpl    Auth_CopyWorkspace_Loop
       iny          
+
       rts
LF681: STY    $E1    
+
 
       TYA          
+
; --- More Authentication Subroutines ---
       clc          
+
       jsr    $2639  ; ($257B)
       adc    $E2    
+
       ldy    $E5
       pha          
+
       iny
LF688: tax          
+
Auth_Sub_KeyProcess_OuterLoop:
       lda    #$00  
+
      STY    $E1
       sta    $2671  
+
       TYA
LF68E: sta    $1800,X  
+
       clc
       dex          
+
       adc    $E2
LF692: bne    LF68E 
+
       pha
       sta    $1800  
+
Auth_Sub_KeyProcess_ClearRam:
LF697: iny          
+
      tax
       STY    $266E  
+
       lda    #$00
       STY    $2674  
+
       sta    $2671
       STY    $267C  
+
Auth_Sub_KeyProcess_ClearRam_Loop:
       STY    $2681  
+
      sta    $1800,X
       ldx    #$00  
+
       dex
LF6A6: dec    $266E  
+
Auth_Sub_KeyProcess_ClearRam_Check:
LF6A9: dec    $2674  
+
      bne    Auth_Sub_KeyProcess_ClearRam_Loop
LF6AC: dec    $267C  
+
       sta    $1800
       dec    $2681  
+
Auth_Sub_KeyProcess_SetupCounters:
       dec    $E1    
+
      iny
       bmi    LF6D1 
+
       STY    $266E
LF6B6: ldy    $E1    
+
       STY    $2674
       lda    $2000,Y  
+
       STY    $267C
       and    $25D9,X  
+
       STY    $2681
       beq    LF6C9 
+
       ldx    #$00
       lda    $2662,X  
+
Auth_Sub_KeyProcess_InnerLoop:
       sta    $2672  
+
      dec    $266E
       jsr    $266A  
+
      dec    $2674
LF6C9: inx          
+
      dec    $267C
       cpx    #$08  
+
       dec    $2681
       bmi    LF6B6 
+
       dec    $E1
       jmp    $25A4  
+
       bmi    Auth_Sub_KeyProcess_Done
LF6D1: pla          
+
Auth_Sub_KeyProcess_BitCheck:
       sta    $E1    
+
      ldy    $E1
       lda    #$01  
+
       lda    $2000,Y
       sta    $E0    
+
       and    $25D9,X
       rts          
+
       beq    Auth_Sub_KeyProcess_NextBit
 +
       lda    $2662,X
 +
       sta    $2672
 +
       jsr    $266A
 +
Auth_Sub_KeyProcess_NextBit:
 +
      inx
 +
       cpx    #$08
 +
       bmi    Auth_Sub_KeyProcess_BitCheck
 +
       jmp    $25A4
 +
Auth_Sub_KeyProcess_Done:
 +
      pla
 +
       sta    $E1
 +
       lda    #$01
 +
       sta    $E0
 +
       rts
  
LF6D9: .byte $01,$02,$04,$08,$10,$20,$40,$80
+
AuthData_Bitmasks: .byte $01,$02,$04,$08,$10,$20,$40,$80
  
 
       jsr    $2639
 
       jsr    $2639
       lda    $E3    
+
       lda    $E3
       sec          
+
       sec
       sbc    $E4    
+
       sbc    $E4
       sta    $E0    
+
       sta    $E0
       sta    $E1    
+
       sta    $E1
       ldx    #$00  
+
       ldx    #$00
       stx    $1800  
+
       stx    $1800
       stx    $268F  
+
       stx    $268F
       stx    $26AC  
+
       stx    $26AC
       dex          
+
       dex
       stx    $26A9  
+
       stx    $26A9
       stx    $268C  
+
       stx    $268C
       stx    $2692  
+
       stx    $2692
       stx    $269A  
+
       stx    $269A
       stx    $269F  
+
       stx    $269F
       ldx    #$07  
+
       ldx    #$07
       inc    $26A9  
+
       inc    $26A9
       inc    $268C  
+
       inc    $268C
       inc    $2692  
+
       inc    $2692
       inc    $269A  
+
       inc    $269A
       inc    $269F  
+
       inc    $269F
       dec    $E1    
+
       dec    $E1
       bmi    LF734 
+
       bmi    Auth_Sub_Op_Done
LF71D: lda    $2662,X  
+
Auth_Sub_Op_Loop:
       sta    $2690  
+
      lda    $2662,X
       sta    $26AD  
+
       sta    $2690
       jsr    $26A6  
+
       sta    $26AD
       bcc    LF72E 
+
       jsr    $26A6
       jsr    $2688  
+
       bcc    Auth_Sub_Op_Next
LF72E: dex          
+
       jsr    $2688
       bpl    LF71D 
+
Auth_Sub_Op_Next:
       jmp    $2608  
+
      dex
LF734: lda    $E3    
+
       bpl    Auth_Sub_Op_Loop
       sta    $E1    
+
       jmp    $2608
       rts          
+
Auth_Sub_Op_Done:
 +
      lda    $E3
 +
       sta    $E1
 +
       rts
  
       ldx    $E4  ;($2639)
+
       ldx    $E4  ; ($2639)
       inx          
+
       inx
       stx    $E2    
+
       stx    $E2
       ldy    #$00  
+
       ldy    #$00
       STY    $1900  
+
       STY    $1900
LF743: lda    $2662,Y  
+
Auth_Sub_Rotate_OuterLoop:
       sta    $2655  
+
      lda    $2662,Y
       iny          
+
       sta    $2655
       lda    $2662,Y  
+
       iny
       sta    $2659  
+
       lda    $2662,Y
       ldx    $E2    
+
       sta    $2659
       clc          
+
       ldx    $E2
LF753: lda    $1900,X  
+
       clc
 +
Auth_Sub_Rotate_InnerLoop:
 +
      lda    $1900,X
 
       rol
 
       rol
       sta    $1900,X  
+
       sta    $1900,X
       dex          
+
       dex
       bpl    LF753 
+
       bpl    Auth_Sub_Rotate_InnerLoop
       cpy    #$07  
+
       cpy    #$07
       bmi    LF743 
+
       bmi    Auth_Sub_Rotate_OuterLoop
       rts          
+
       rts
  
LF762: .byte $19,$1A,$1B,$1C,$1D,$1E,$1F,$21
+
AuthData_Indices: .byte $19,$1A,$1B,$1C,$1D,$1E,$1F,$21
  
 
       ldy    $E2
 
       ldy    $E2
       clc          
+
       clc
LF76D: lda    $1800,Y  
+
Auth_Sub_Add_Loop:
       adc    $1900,Y  
+
      lda    $1800,Y
       sta    $1800,Y  
+
       adc    $1900,Y
       dey          
+
       sta    $1800,Y
       bpl    LF76D 
+
       dey
       bcc    LF787 
+
       bpl    Auth_Sub_Add_Loop
       lda    $1700,Y  
+
       bcc    Auth_Sub_Add_NoCarry
       adc    #$00  
+
       lda    $1700,Y
       sta    $1700,Y  
+
       adc    #$00
       dey          
+
       sta    $1700,Y
       jmp    $2679  
+
       dey
LF787: rts          
+
       jmp    $2679
 +
Auth_Sub_Add_NoCarry:
 +
      rts
  
       ldy    $E2    
+
       ldy    $E2
       sec          
+
       sec
LF78B: lda    $1800,Y  
+
Auth_Sub_Subtract_Loop:
       sbc    $1900,Y  
+
      lda    $1800,Y
       sta    $1800,Y  
+
       sbc    $1900,Y
       dey          
+
       sta    $1800,Y
       bpl    LF78B 
+
       dey
       bcs    LF7A5 
+
       bpl    Auth_Sub_Subtract_Loop
       lda    $1700,Y  
+
       bcs    Auth_Sub_Subtract_NoBorrow
       sbc    #$00  
+
       lda    $1700,Y
       sta    $1700,Y  
+
       sbc    #$00
       dey          
+
       sta    $1700,Y
       jmp    $2697  
+
       dey
LF7A5: rts          
+
       jmp    $2697
 +
Auth_Sub_Subtract_NoBorrow:
 +
      rts
  
       ldy    #$00  
+
       ldy    #$00
       lda    $1800,Y  
+
       lda    $1800,Y
       cmp    $1900,Y  
+
       cmp    $1900,Y
       beq    LF7B1 
+
       beq    Auth_Sub_Compare_Equal
LF7B0: rts          
+
Auth_Sub_Compare_NotEqual:
 +
      rts
  
LF7B1: cpy    $E2    
+
Auth_Sub_Compare_Equal:
       beq    LF7B0 
+
      cpy    $E2
       iny          
+
       beq    Auth_Sub_Compare_NotEqual
       jmp    $26A8  
+
       iny
 +
       jmp    $26A8
  
LF7B9:                    ; ($26B9) 7800 mode init
+
; --- 7800 Mode Initialization ---
       ldx    #$16        ; finally, back to something important
+
      ORG $F7B9
       stx    INPTCTRL    ; switch out bios and use reset vector
+
; This label is an equate, not a location. It calculates the correct RAM address
       txs                ; on cart to start the game.
+
; for the routine, which is needed by the code executing from RAM.
       SED          
+
; ROM address $F7B9 -> RAM address $26B9. Offset is $D100.
       jmp (CartResetVectorLo)    
+
Enter7800Mode = . - $D100
 +
Routine_Enter7800Mode:
 +
       ldx    #$16        ; Enable Maria and Cartridge ROM.
 +
       stx    INPTCTRL    ; Lock out BIOS, enable cartridge.
 +
       txs                ; Set up stack pointer.
 +
       SED               ; Set Decimal Mode (a 7800 convention, often cleared by games).
 +
       jmp (CartResetVectorLo) ; Jump to the game's starting address on the cartridge.
  
; Enable 2600 mode
+
; --- 2600 Mode Initialization ---
LF7C2:                    ; ($26C2) 2600 mode init
+
      ORG $F7C2
       lda    #$02        ; Enable memory/bios
+
; This label is also an equate to calculate the correct RAM address.
       sta    INPTCTRL    ;  
+
; ROM address $F7C2 -> RAM address $26C2. Offset is $D100.
 +
Enter2600Mode = . - $D100
 +
Routine_Enter2600Mode:
 +
       lda    #$02        ; Enable 7800 RAM and BIOS ROM.
 +
       sta    INPTCTRL    ;
 
       ldx    #$7F
 
       ldx    #$7F
LF7C8: lda    LF7D4,X     ; again, copy code to ram....
+
; Copy the 2600 TIA setup code from BIOS ROM into RIOT RAM ($0480).
       sta    $0480,X  
+
CopyTiaInitToRam_Loop:
       dex          
+
      lda    TiaInitCode,X
       bpl    LF7C8 
+
       sta    $0480,X
       jmp    $0480      ; execute it
+
       dex
 +
       bpl    CopyTiaInitToRam_Loop
 +
       jmp    $0480      ; Jump to the newly copied code in RIOT RAM to execute it.
  
; code executed at $0480 (RIOT RAM)
+
; --- 2600 TIA Setup Code (Executed from RIOT RAM at $0480) ---
 
+
TiaInitCode:
LF7D4: lda    #$00        ;  
+
      lda    #$00        ;
       tax                ;  
+
       tax                ;
       sta    INPTCTRL    ; Disable 7800 RAM
+
       sta    INPTCTRL    ; Disable 7800 RAM/BIOS, giving full control to cart.
LF7D9: sta    RSYNC,X     ; Clear the TIA
+
; Clear all TIA registers to put it in a known state.
 +
TiaInit_ClearLoop:
 +
      sta    RSYNC,X
 
       inx                ;
 
       inx                ;
 
       cpx    #$2A        ;
 
       cpx    #$2A        ;
       bne    LF7D9      ;
+
       bne    TiaInit_ClearLoop
       sta    WSYNC      ; wait for sync
+
       sta    WSYNC      ; Wait for horizontal sync.
 
       lda    #$04        ;
 
       lda    #$04        ;
 
       nop                ;
 
       nop                ;
       bmi    LF80A 
+
       bmi    TiaInit_SetColors1
       ldx    #$04  
+
       ldx    #$04
LF7E9: dex          
+
TiaInit_DelayLoop:
       bpl    LF7E9 
+
      dex
       txs          
+
       bpl    TiaInit_DelayLoop
       sta    $0110  
+
       txs
       jsr    $04CB  
+
       sta    $0110
       jsr    $04CB  
+
       jsr    $04CB
       sta    RESP1  
+
       jsr    $04CB
       sta    GRP0  
+
       sta    RESP1
       sta    GRP1  
+
       sta    GRP0
       sta    PF2    
+
       sta    GRP1
       nop          
+
       sta    PF2
       sta    WSYNC  
+
       nop
       lda    #$00  
+
       sta    WSYNC
       nop          
+
       lda    #$00
       bmi    LF80A 
+
       nop
       bit    RSYNC  
+
       bmi    TiaInit_SetColors1
       bmi    LF813 
+
       bit    RSYNC
LF80A: lda    #$02  
+
       bmi    TiaInit_SetColors2
       sta    COLUBK
+
TiaInit_SetColors1:
       sta    LF112  
+
      lda    #$02
       bne    LF831 
+
       sta    COLUBK
LF813: bit    WSYNC  
+
       sta    LF112
       bmi    LF823 
+
       bne    TiaInit_Finalize
       lda    #$02  
+
TiaInit_SetColors2:
       sta    COLUP0
+
      bit    WSYNC
       sta    LF118  
+
       bmi    TiaInit_SetColors3
       sta    LF460  
+
       lda    #$02
       bne    LF831 
+
       sta    COLUP0
LF823: sta    DPPH  
+
       sta    LF118
       lda    #$08  
+
       sta    LF460
       sta    GRP0  
+
       bne    TiaInit_Finalize
       jsr    $04CB  
+
TiaInit_SetColors3:
       nop          
+
      sta    DPPH
       bit    WSYNC  
+
       lda    #$08
       bmi    LF80A 
+
       sta    GRP0
LF831: lda    #$FD  
+
       jsr    $04CB
       sta    COLUPF
+
       nop
       jmp (CartResetVectorLo)       ; And use the reset vector on the cart to start
+
       bit    WSYNC
       nop                           ; the 2600 game.
+
       bmi    TiaInit_SetColors1
 +
TiaInit_Finalize:
 +
      lda    #$FD
 +
       sta    COLUPF
 +
       jmp (CartResetVectorLo) ; Jump to the 2600 game's starting address on the cartridge.
 +
       nop
 +
 
 +
;=============================================================================
 +
;
 +
; III. BIOS ENTRY, POWER-ON SELF TEST (POST), AND SYSTEM INIT
 +
;
 +
;=============================================================================
  
 
       ORG $F880
 
       ORG $F880
  
LF880: lda    #$1D       ; this is called any time the self-test fails.
+
; --- Self-Test Failure Handler ---
       sta    INPTCTRL    ; Eanble TIA/Cart/lock out INPTCTRL
+
; This code is jumped to whenever a POST routine fails. It writes an error
 +
; code to INPTCTRL, which can be read by external diagnostic hardware.
 +
Post_FailHandler:
 +
      lda    #$1D
 +
       sta    INPTCTRL    ; Enable TIA/Cart/lock out INPTCTRL.
  
START:                    ; $F884  
+
; --- BIOS Entry Point / Cold Start ---
       SEI                ; BIOS entry point.  Disable interrupts
+
START:                    ; $F884
       CLD                ; Clear decimal flag
+
       SEI                ; Disable interrupts on power-on.
 +
       CLD                ; Clear decimal flag.
 
       lda    #$02        ;
 
       lda    #$02        ;
LF888: sta    INPTCTRL    ; Enable 7800 RAM
+
Bios_SetRamAndBios:
       lda    #$FB        ;
+
      sta    INPTCTRL    ; Enable 7800 RAM and map BIOS into memory.
 +
       lda    #$FB        ; Set high byte of NMI vector to $FB.
 
       sta    $F5        ;
 
       sta    $F5        ;
       lda    #$12        ;
+
       lda    #$12        ; Set low byte of NMI vector to $12.
       sta    $F4        ; set nmi vector to FB12. (shares cleanup of irq)
+
       sta    $F4        ; NMI vector is now $FB12 (points to IRQ cleanup).
 
       lda    #$7F        ;
 
       lda    #$7F        ;
       sta    CTRL        ; Turn off DMA
+
       sta    CTRL        ; Turn off Maria DMA.
 
       lda    #$00        ;
 
       lda    #$00        ;
       sta    BACKGRND    ; Background color
+
       sta    BACKGRND    ; Set background color to black.
       ldx    #$05        ;
+
 
LF89C: lda    LF91D,X     ; looks icky, but it's just a ram test
+
; --- POST: RAM Test 1 (Basic) ---
       ldy    #$00        ;
+
; This is a quick test of the two 2KB RAM chips ($2000-$27FF).
LF8A1: sta    $2000,Y    ;
+
; It writes several patterns to each byte and reads them back.
       cmp    $2000,Y    ;
+
       ldx    #$05        ; Loop counter for the 6 test patterns.
       bne    LF8D0      ; Test failed
+
Post_RamTest1_PatternLoop:
       sta    $2100,Y    ;
+
      lda    Post_RamTest_Data,X ; Load a test pattern ($00, $FF, $55, $AA, $69, $0F).
       cmp    $2100,Y    ;
+
       ldy    #$00        ; Inner loop counter for 256 bytes.
       bne    LF8D0      ; Test failed
+
Post_RamTest1_PageLoop:
 +
      sta    $2000,Y    ; Write pattern to first RAM chip.
 +
       cmp    $2000,Y    ; Read it back and compare.
 +
       bne    Post_RamTest_Fail1 ; If it fails, branch to error handler.
 +
       sta    $2100,Y    ; Write pattern to second RAM chip.
 +
       cmp    $2100,Y    ; Read it back and compare.
 +
       bne    Post_RamTest_Fail1 ; If it fails, branch to error handler.
 
       dey                ;
 
       dey                ;
       bne    LF8A1      ;
+
       bne    Post_RamTest1_PageLoop ; Loop through all 256 bytes of a page.
 
       dex                ;
 
       dex                ;
       bpl    LF89C      ; and right down here, it passes
+
       bpl    Post_RamTest1_PatternLoop ; Loop to the next test pattern.
       lda    #$43        ; Check RAM 0 mirror
+
 
       sta    $2080      ;  
+
; --- POST: RAM Mirror Test ---
       cmp    $80        ;  
+
; Checks that the RAM is correctly mirrored every 256 bytes.
       bne    LF8CB      ; make sure they match. If not, fail selftest.
+
       lda    #$43        ; Check RAM 0 mirror.
 +
       sta    $2080      ; Write to $2080.
 +
       cmp    $80        ; Compare with $0080 (a mirror).
 +
       bne    Post_RamMirror_Fail ; make sure they match. If not, fail selftest.
 
       sta    $2180      ; Check RAM 1 mirror
 
       sta    $2180      ; Check RAM 1 mirror
       cmp    $0180      ;  
+
       cmp    $0180      ;
       bne    LF8CB      ; make sure they match. If not, fail selftest.
+
       bne    Post_RamMirror_Fail ; make sure they match. If not, fail selftest.
       jmp    LF938      ; continue selftest
+
       jmp    Post_CpuTest_Start ; continue selftest
LF8CB: ldy    #$04        ;
+
Post_RamMirror_Fail:
       jmp    LF880      ; selftest fail.
+
      ldy    #$04        ;
 +
       jmp    Post_FailHandler ; selftest fail.
  
LF8D0: sta    $1800      ; test store and compare
+
; --- POST: RAM Failure Handlers ---
       cmp    $1800  
+
; These routines are jumped to from the RAM tests to indicate failure.
       bne    LF8E2      ; some kind of error code is being determined
+
Post_RamTest_Fail1:
LF8D8: ldy    #$01  
+
      sta    $1800      ; test store and compare
       jmp    LF880 
+
       cmp    $1800
 +
       bne    Post_RamTest_Fail3 ; some kind of error code is being determined
 +
Post_RamTest_Fail2:
 +
      ldy    #$01
 +
       jmp    Post_FailHandler
  
LF8DD: ldy    #$02
+
Post_RamTest_Fail_Indirect:
 +
      ldy    #$02
 
       jmp    $F880
 
       jmp    $F880
  
LF8E2: ldy    #$03
+
Post_RamTest_Fail3:
       jmp    LF880 
+
      ldy    #$03
 +
       jmp    Post_FailHandler
  
LF8E7: lda    #$00       ; this is a more comprehensive ram test than
+
; --- POST: RAM Test 2 (Comprehensive) ---
       sta    $F0        ; the first routine, and it is called after
+
; This is a more thorough RAM test called later in the boot process. It uses
       sta    $F2        ; more of the selftest has completed.
+
; indirect addressing to test all 8 pages of the 4KB RAM.
       ldy    #$07  
+
Post_RamTest2_Start:
       STY    $F4    
+
      lda    #$00
LF8F1: lda    LF923,Y  
+
       sta    $F0        ; Base address low byte pointer.
       sta    $F1    
+
       sta    $F2        ;
       lda    LF92B,Y  
+
       ldy    #$07       ; Loop counter for 8 pages.
       sta    $F3    
+
       STY    $F4
       ldx    #$05  
+
Post_RamTest2_OuterLoop:
LF8FD: lda    LF91D,X  
+
      lda    Post_RamTest_AddrHi1,Y ; Load high byte of address for RAM chip 1.
LF900: ldy    #$00  
+
       sta    $F1
LF902: sta    ($F0),Y  
+
       lda    Post_RamTest_AddrHi2,Y ; Load high byte of address for RAM chip 2.
       cmp    ($F0),Y  
+
       sta    $F3
       bne    LF8D8 
+
       ldx    #$05       ; Loop counter for 6 test patterns.
       sta    ($F2),Y  
+
Post_RamTest2_PatternLoop:
       cmp    ($F2),Y  
+
      lda    Post_RamTest_Data,X ; Load a test pattern.
       bne    LF8DD 
+
Post_RamTest2_InnerLoop:
       dey          
+
      ldy    #$00       ; Inner loop counter for 256 bytes.
       bne    LF902 
+
Post_RamTest2_ByteLoop:
       dex          
+
      sta    ($F0),Y     ; Write to RAM 1 via indirect pointer ($F0/$F1).
       bpl    LF8FD 
+
       cmp    ($F0),Y     ; Read back and compare.
       dec    $F4    
+
       bne    Post_RamTest_Fail2 ; Fail.
       ldy    $F4    
+
       sta    ($F2),Y     ; Write to RAM 2 via indirect pointer ($F2/$F3).
       bpl    LF8F1 
+
       cmp    ($F2),Y     ; Read back and compare.
       jmp    LFB17      ; ram test passed, so jump in here.
+
       bne    Post_RamTest_Fail_Indirect ; Fail.
 
+
       dey
; ram test data
+
       bne    Post_RamTest2_ByteLoop ; Loop through page.
LF91D: .byte $00,$FF,$55,$AA,$69,$0F
+
       dex
LF923: .byte $22,$23,$24,$25,$26,$27,$22,$23
+
       bpl    Post_RamTest2_PatternLoop ; Loop through patterns.
LF92B: .byte $18,$19,$1A,$1B,$1C,$1D,$1E,$1F
+
       dec    $F4
 +
       ldy    $F4
 +
       bpl    Post_RamTest2_OuterLoop ; Loop through pages.
 +
       jmp    Bios_InitSystem ; ram test passed, so jump in here.
  
LF933: ldy    #$00       ; local place for selftest fail branch target
+
; --- RAM Test Data ---
      jmp    LF880 
+
Post_RamTest_Data: .byte $00,$FF,$55,$AA,$69,$0F
 +
Post_RamTest_AddrHi1: .byte $22,$23,$24,$25,$26,$27,$22,$23
 +
Post_RamTest_AddrHi2: .byte $18,$19,$1A,$1B,$1C,$1D,$1E,$1F
  
; 6502 CPU test
+
Post_CpuTest_Fail:
 +
      ldy    #$00      ; local place for selftest fail branch target
 +
      jmp    Post_FailHandler
  
LF938: lda    #$AA      ; test some flags and branches
+
; --- POST: 6502 CPU Test ---
       beq    LF933      ; test failed
+
; This section exhaustively tests the 6502's instruction set, flags,
       bpl    LF933      ; test failed
+
; and addressing modes to ensure the CPU is functioning correctly.
       bmi    LF943      ; test passed
+
Post_CpuTest_Start:
       jmp    LF933      ; test failed
+
      lda    #$AA      ; test some flags and branches
LF943: bne    LF948      ; test passed
+
       beq    Post_CpuTest_Fail ; test failed
       jmp    LF933      ; test failed
+
       bpl    Post_CpuTest_Fail ; test failed
LF948: sta    $AA        ; store AA to 00AA
+
       bmi    CpuTest_CheckBne ; test passed
 +
       jmp    Post_CpuTest_Fail ; test failed
 +
CpuTest_CheckBne:
 +
      bne    CpuTest_CheckStore ; test passed
 +
       jmp    Post_CpuTest_Fail ; test failed
 +
CpuTest_CheckStore:
 +
      sta    $AA        ; store AA to 00AA
 
       cmp    $AA        ; compare it back
 
       cmp    $AA        ; compare it back
       bne    LF933      ; if it doesn't match, selftest fail
+
       bne    Post_CpuTest_Fail ; if it doesn't match, selftest fail
 
       lda    #$00      ; do some more flag tests
 
       lda    #$00      ; do some more flag tests
       bne    LF933      ;
+
       bne    Post_CpuTest_Fail ;
       bmi    LF933      ;
+
       bmi    Post_CpuTest_Fail ;
       bpl    LF959      ; test passed
+
       bpl    CpuTest_CheckBeq ; test passed
       jmp    LF933      ;
+
       jmp    Post_CpuTest_Fail ;
LF959: beq    LF95E      ; test passed
+
CpuTest_CheckBeq:
       jmp    LF933      ;
+
      beq    CpuTest_CheckCmp ; test passed
LF95E: cmp    #$00      ; test the compare instruction
+
       jmp    Post_CpuTest_Fail ;
       bne    LF933      ;
+
CpuTest_CheckCmp:
       bcc    LF933      ;
+
      cmp    #$00      ; test the compare instruction
       bcs    LF969      ; test passed, since they're equal
+
       bne    Post_CpuTest_Fail ;
       jmp    LF933      ;
+
       bcc    Post_CpuTest_Fail ;
LF969: cmp    #$01      ; compare it to 01
+
       bcs    CpuTest_CheckCmpBcs ; test passed, since they're equal
       bcs    LF933      ;
+
       jmp    Post_CpuTest_Fail ;
       bcc    LF972      ; A < 01, so carry is clear
+
CpuTest_CheckCmpBcs:
       jmp    LF933      ;
+
      cmp    #$01      ; compare it to 01
LF972: ldx    #$55      ; test comparisons with the X register
+
       bcs    Post_CpuTest_Fail ;
 +
       bcc    CpuTest_CheckCpx ; A < 01, so carry is clear
 +
       jmp    Post_CpuTest_Fail ;
 +
CpuTest_CheckCpx:
 +
      ldx    #$55      ; test comparisons with the X register
 
       cpx    #$56      ;
 
       cpx    #$56      ;
       beq    LF933      ;
+
       beq    Post_CpuTest_Fail ;
 
       stx    $01AA      ;
 
       stx    $01AA      ;
 
       cpx    $01AA      ;
 
       cpx    $01AA      ;
       bne    LF933      ;
+
       bne    Post_CpuTest_Fail ;
 
       ldy    $AA        ; and with the Y register.
 
       ldy    $AA        ; and with the Y register.
 
       cpy    #$AB      ;
 
       cpy    #$AB      ;
LF984: beq    LF933      ;
+
CpuTest_CheckCpy:
 +
      beq    Post_CpuTest_Fail ;
 
       STY    $0155      ; put some stuff in the stack area to test stack
 
       STY    $0155      ; put some stuff in the stack area to test stack
       cpy    $0155      ; and then access this data in many diffeent ways
+
       cpy    $0155      ; and then access this data in many different ways
       bne    LF933      ;
+
       bne    Post_CpuTest_Fail ;
 
       dex              ;
 
       dex              ;
 
       txs              ;
 
       txs              ;
Line 636: Line 802:
 
       pla              ;
 
       pla              ;
 
       cmp    #$AA      ;
 
       cmp    #$AA      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       txa              ;
 
       txa              ;
 
       pha              ;
 
       pha              ;
 
       cpx    $0155      ;
 
       cpx    $0155      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       TYA              ;
 
       TYA              ;
 
       cmp    #$AA      ;
 
       cmp    #$AA      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       tax              ;
 
       tax              ;
 
       lda    $0100,X    ;
 
       lda    $0100,X    ;
 
       tay              ;
 
       tay              ;
 
       cpy    #$55      ;
 
       cpy    #$55      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       lda    VSYNC,X    ;
 
       lda    VSYNC,X    ;
 
       cmp    $AA        ;
 
       cmp    $AA        ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       cmp    #$AA      ;
 
       cmp    #$AA      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       eor    #$FF      ;
 
       eor    #$FF      ;
 
       sta    $0000,Y    ;
 
       sta    $0000,Y    ;
 
       cmp    $55        ;
 
       cmp    $55        ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       cmp    $0100,Y    ;
 
       cmp    $0100,Y    ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       cmp    $20AB,X    ;
 
       cmp    $20AB,X    ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       lda    #$20      ;
 
       lda    #$20      ;
 
       sta    $F1        ;
 
       sta    $F1        ;
Line 668: Line 834:
 
       sta    ($46,X)    ;
 
       sta    ($46,X)    ;
 
       cmp    $CC        ;
 
       cmp    $CC        ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       sta    ($F0),Y    ;
 
       sta    ($F0),Y    ;
 
       cmp    $2121      ;
 
       cmp    $2121      ;
       bne    LF9EB      ;
+
       bne    Post_CpuTest_Fail_Central ;
 
       lda    #$EE      ; test the indirect jump by setting up a jump
 
       lda    #$EE      ; test the indirect jump by setting up a jump
       sta    $F0        ; to F9EE
+
       sta    $F0        ; to Post_CpuMath_Start
 
       lda    #$F9      ;
 
       lda    #$F9      ;
 
       sta    $F1        ;
 
       sta    $F1        ;
 
       jmp ($00F0)        ; and do it.
 
       jmp ($00F0)        ; and do it.
  
LF9E8: jmp    $F9EB
+
CpuTest_ShouldNotBeReached:
 +
      jmp    Post_CpuTest_Fail_Central
  
LF9EB: jmp    LF933
+
Post_CpuTest_Fail_Central:
 +
      jmp    Post_CpuTest_Fail
  
  
LF9EE: lda    #$55      ; now test out the math functions.
+
; --- POST: CPU Math and Logic Tests ---
       clc          
+
Post_CpuMath_Start:
       adc    #$55  
+
      lda    #$55      ; now test out the math functions.
       nop          
+
       clc
       bcs    LF9EB      ; test addition.
+
       adc    #$55
       bpl    LF9EB 
+
       nop
       beq    LF9EB 
+
       bcs    Post_CpuTest_Fail_Central ; test addition.
 +
       bpl    Post_CpuTest_Fail_Central
 +
       beq    Post_CpuTest_Fail_Central
 
       cmp    #$AA      ; make sure it worked
 
       cmp    #$AA      ; make sure it worked
       bne    LF9EB 
+
       bne    Post_CpuTest_Fail_Central
 
       adc    #$55      ; test addition again.
 
       adc    #$55      ; test addition again.
LFA00: nop          
+
CpuMath_TestAdcCarry:
       bcc    LF9EB 
+
      nop
       bmi    LF9EB 
+
       bcc    Post_CpuTest_Fail_Central
       bne    LF9EB 
+
       bmi    Post_CpuTest_Fail_Central
 +
       bne    Post_CpuTest_Fail_Central
 
       sbc    #$55      ; test subtraction
 
       sbc    #$55      ; test subtraction
       bcs    LF9EB 
+
       bcs    Post_CpuTest_Fail_Central
       bpl    LF9EB 
+
       bpl    Post_CpuTest_Fail_Central
       beq    LF9EB 
+
       beq    Post_CpuTest_Fail_Central
 
       cmp    #$AB      ; make sure it worked
 
       cmp    #$AB      ; make sure it worked
       bne    LF9EB 
+
       bne    Post_CpuTest_Fail_Central
       clc          
+
       clc
 
       sbc    #$AA      ; test subtraction again
 
       sbc    #$AA      ; test subtraction again
       bcc    LF9EB 
+
       bcc    Post_CpuTest_Fail_Central
       bmi    LF9EB 
+
       bmi    Post_CpuTest_Fail_Central
       bne    LF9EB 
+
       bne    Post_CpuTest_Fail_Central
 
       lda    #$FF      ; set up a stack
 
       lda    #$FF      ; set up a stack
 
       tax              ; and do all kinds of stuff in it for tests
 
       tax              ; and do all kinds of stuff in it for tests
       inx          
+
       inx
       bne    LFA58 
+
       bne    CpuMath_Fail
       dex          
+
       dex
       beq    LFA58 
+
       beq    CpuMath_Fail
       bpl    LFA58 
+
       bpl    CpuMath_Fail
       cpx    #$FF  
+
       cpx    #$FF
       bne    LFA58 
+
       bne    CpuMath_Fail
       tay          
+
       tay
       iny          
+
       iny
       bne    LFA58 
+
       bne    CpuMath_Fail
       dey          
+
       dey
       beq    LFA58     
+
       beq    CpuMath_Fail
       iny          
+
       iny
       bne    LFA58 
+
       bne    CpuMath_Fail
       sta    $F0    
+
       sta    $F0
       inc    $F0    
+
       inc    $F0
       bne    LFA58 
+
       bne    CpuMath_Fail
       cpy    $F0    
+
       cpy    $F0
       bne    LFA58 
+
       bne    CpuMath_Fail
       dec    $F0    
+
       dec    $F0
       beq    LFA58 
+
       beq    CpuMath_Fail
       cmp    $F0    
+
       cmp    $F0
       bne    LFA58 
+
       bne    CpuMath_Fail
       lda    #$AA  
+
       lda    #$AA
       clc          
+
       clc
 
       rol              ; now we get onto the more complex math instrs
 
       rol              ; now we get onto the more complex math instrs
 
       rol
 
       rol
 
       rol
 
       rol
       cmp    #$52  
+
       cmp    #$52
       bne    LFA58      ; make sure rotate left works.
+
       bne    CpuMath_Fail ; make sure rotate left works.
 
       ror
 
       ror
 
       ror
 
       ror
 
       ror
 
       ror
       cmp    #$AA  
+
       cmp    #$AA
       beq    LFA5B      ; test rotate right
+
       beq    CpuMath_TestAsl ; test rotate right
LFA58: jmp    LF933      ; fail!
+
CpuMath_Fail:
 +
      jmp    Post_CpuTest_Fail ; fail!
  
LFA5B: asl              ; test arithmetic shift left
+
CpuMath_TestAsl:
       bcc    LFA58 
+
      asl              ; test arithmetic shift left
       asl          
+
       bcc    CpuMath_Fail
       bcs    LFA58 
+
       asl
       asl          
+
       bcs    CpuMath_Fail
       cmp    #$50  
+
       asl
       bne    LFA58 
+
       cmp    #$50
       eor    #$05  
+
       bne    CpuMath_Fail
 +
       eor    #$05
 
       lsr              ; and logical shift right
 
       lsr              ; and logical shift right
       bcc    LFA58 
+
       bcc    CpuMath_Fail
       lsr          
+
       lsr
       bcs    LFA58 
+
       bcs    CpuMath_Fail
       lsr          
+
       lsr
       cmp    #$0A  
+
       cmp    #$0A
       bne    LFA58 
+
       bne    CpuMath_Fail
 
       lda    #$55      ; now test the ands and ors.
 
       lda    #$55      ; now test the ands and ors.
       ora    #$1B  
+
       ora    #$1B
       cmp    #$5F  
+
       cmp    #$5F
       bne    LFA58 
+
       bne    CpuMath_Fail
       and    #$55  
+
       and    #$55
       and    #$1B  
+
       and    #$1B
       cmp    #$11  
+
       cmp    #$11
       bne    LFA58 
+
       bne    CpuMath_Fail
       ora    #$55  
+
       ora    #$55
 
       eor    #$1B      ; and the eors
 
       eor    #$1B      ; and the eors
       cmp    #$4E  
+
       cmp    #$4E
       bne    LFA58 
+
       bne    CpuMath_Fail
       jsr    LFA91      ; test jump subroutine instruction
+
       jsr    Cpu_TestJsr ; test jump subroutine instruction
       jmp    LFA58      ; if we return, fail
+
       jmp    CpuMath_Fail ; if we return, fail
  
LFA91: tsx              
+
Cpu_TestJsr:
 +
      tsx
 
       cpx    #$52      ; check stack pointer
 
       cpx    #$52      ; check stack pointer
       bne    LFA58      ; fail if not right
+
       bne    CpuMath_Fail ; fail if not right
       pla          
+
       pla
       cmp    #$8D  
+
       cmp    #$8D
       bne    LFA58 
+
       bne    CpuMath_Fail
       pla          
+
       pla
       cmp    #$FA  
+
       cmp    #$FA
       bne    LFA58      ; get the old return address off the stack
+
       bne    CpuMath_Fail ; get the old return address off the stack
       lda    #$F8  
+
       lda    #$F8
       pha          
+
       pha
       lda    #$E6  
+
       lda    #$E6
 
       pha              ; and make our own
 
       pha              ; and make our own
       rts              ; and 'return' to F8E7
+
       rts              ; and 'return' to Post_RamTest2_Start
  
       jmp    LFA58      ; another jump to catch a failure
+
       jmp    CpuMath_Fail ; another jump to catch a failure
 +
 
 +
;=============================================================================
 +
;
 +
; IV. NMI HANDLER (FUJI LOGO DISPLAY)
 +
;
 +
;=============================================================================
  
; Interrupt routine NMI.  
+
; This NMI routine is responsible for drawing the "Fuji" mountain logo and
 +
; the "ATARI" text on the screen during the boot-up/authentication process.
 +
; It is called on every VBLANK. Its main job is to manipulate Maria's palette
 +
; registers to create the signature color-cycling effect on the Fuji logo.
  
LFAAA: txa          ;Save A
+
Nmi_DrawFujiAndAtari:
       pha          ;
+
      txa          ;Save A
       lda    #$43  ;Setup control register
+
       pha          ;
       sta    CTRL  ;  
+
       lda    #$43  ;Setup control register
       ldx    #$0F  ; Handle the color scrolling in the FUJI  
+
       sta    CTRL  ;
       lda    $EF    
+
       ldx    #$0F  ; Handle the color scrolling in the FUJI
 +
       lda    $EF
 
       sta    P0C2
 
       sta    P0C2
       bit    $F3    
+
       bit    $F3
       bvc    LFAC0 
+
       bvc    Nmi_Sync3
       bpl    LFABE 
+
       bpl    Nmi_Sync2
LFABC: sta    MWSYNC ;Wait for 3 scanlines  
+
Nmi_Sync1:
LFABE: sta    MWSYNC ;  
+
      sta    MWSYNC ;Wait for 3 scanlines
LFAC0: sta    MWSYNC ;  
+
Nmi_Sync2:
       sec          
+
      sta    MWSYNC ;
       sbc    #$10
+
Nmi_Sync3:
       cmp    #$10  
+
      sta    MWSYNC ;
       bcs    LFACB 
+
       sec
       sbc    #$0F  
+
       sbc    #$10
LFACB: sta    P0C2
+
       cmp    #$10
       dex          
+
       bcs    Nmi_StoreColor
       bpl    LFABC  ;Branch to do next section of fuji
+
       sbc    #$0F
 +
Nmi_StoreColor:
 +
      sta    P0C2
 +
       dex
 +
       bpl    Nmi_Sync1 ;Branch to do next section of fuji
 
       ldx    #$40    ;set 160x2/160x4 mode
 
       ldx    #$40    ;set 160x2/160x4 mode
       stx    CTRL    ;
+
       stx    CTRL    ;
 
       and    #$F0    ;
 
       and    #$F0    ;
 
       ora    #$0E    ;set Palette 1 color 3
 
       ora    #$0E    ;set Palette 1 color 3
Line 826: Line 1,014:
 
       ora    #$06    ;set Palette 1 color 1
 
       ora    #$06    ;set Palette 1 color 1
 
       sta    P1C1    ;
 
       sta    P1C1    ;
       and    #$F0  
+
       and    #$F0
       clc          
+
       clc
       adc    #$40  
+
       adc    #$40
       bcc    LFAEB 
+
       bcc    Nmi_SetPalette1Color2
       adc    #$0F  
+
       adc    #$0F
LFAEB: ora    #$03  ;set Palette 1 color 2
+
Nmi_SetPalette1Color2:
       sta    P1C2
+
      ora    #$03  ;set Palette 1 color 2
       dec    $F1    
+
       sta    P1C2
       bpl    LFB0C 
+
       dec    $F1
       lda    $F3    
+
       bpl    Nmi_RestoreRegs
       adc    #$60  
+
       lda    $F3
       bcc    LFB0A 
+
       adc    #$60
       lda    $EF    
+
       bcc    Nmi_UpdateFrameCounter
       clc          
+
       lda    $EF
       adc    #$10  
+
       clc
       bcc    LFB02 
+
       adc    #$10
       adc    #$0F  
+
       bcc    Nmi_StoreNewBaseColor
LFB02: sta    $EF    
+
       adc    #$0F
       lda    $F2    
+
Nmi_StoreNewBaseColor:
       sta    $F1    
+
      sta    $EF
       lda    #$00  
+
       lda    $F2
LFB0A: sta    $F3    
+
       sta    $F1
LFB0C: lda    #$02  
+
       lda    #$00
       sta    $F0    
+
Nmi_UpdateFrameCounter:
       pla          
+
      sta    $F3
       tax          
+
Nmi_RestoreRegs:
       pla          
+
      lda    #$02
       rti          
+
       sta    $F0
 +
       pla
 +
       tax
 +
       pla
 +
       rti
 +
 
 +
Trap_InfiniteLoop:
 +
      jmp    Trap_InfiniteLoop
  
LFB14: jmp    LFB14 
+
;=============================================================================
 +
;
 +
; V. SYSTEM INITIALIZATION (POST-TEST)
 +
;
 +
;=============================================================================
  
LFB17: ldx    #$FF      ; selftest has passed, start system init
+
; This routine is executed after all Power-On Self Tests have passed.
 +
Bios_InitSystem:
 +
      ldx    #$FF      ; selftest has passed, start system init
 
       txs              ; set up a stack
 
       txs              ; set up a stack
 
       lda    #$00      ; Clear TIA/Maria registers
 
       lda    #$00      ; Clear TIA/Maria registers
 
       tax              ;
 
       tax              ;
LFB1D: sta    $01,X ;    ;
+
Bios_ClearRegsLoop:
 +
      sta    $01,X ;
 
       inx              ;
 
       inx              ;
 
       cpx    #$2C      ;
 
       cpx    #$2C      ;
       bne    LFB1D      ;
+
       bne    Bios_ClearRegsLoop
 
       lda    #$02      ;
 
       lda    #$02      ;
       sta    INPTCTRL  ; Enable 7800 RAM  
+
       sta    INPTCTRL  ; Enable 7800 RAM
 
       ldx    #$00      ;
 
       ldx    #$00      ;
       stx    BACKGRND  ; Set background color  
+
       stx    BACKGRND  ; Set background color
LFB2C: lda    LF400,X   ; copy the authentication and title screen to  
+
 
 +
; --- Copy BIOS Routines and Data to RAM ---
 +
; This is a critical step. It copies the cartridge authentication code,
 +
; graphics display routines, and associated data from the BIOS ROM
 +
; into the main system RAM. This allows the BIOS to run its complex
 +
; authentication logic from RAM, freeing up the cartridge bus.
 +
Bios_CopyCodeToRam_Loop:
 +
      lda    RamExec_Start,X ; copy the authentication and title screen to
 
       sta    $2300,X    ; ram
 
       sta    $2300,X    ; ram
       lda    LF500,X   ;
+
       lda    Auth_Sub_MixAndLookup_Equate,X ;
 
       sta    $2400,X    ;
 
       sta    $2400,X    ;
       lda    LF600,X   ;
+
       lda    AuthData_Table8,X ;
 
       sta    $2500,X    ;
 
       sta    $2500,X    ;
 
       lda    LF700,X    ;
 
       lda    LF700,X    ;
Line 879: Line 1,088:
 
       lda    LF800,X    ;
 
       lda    LF800,X    ;
 
       sta    $2700,X    ;
 
       sta    $2700,X    ;
       lda    LFBBE,X   ;
+
       lda    DisplayList_Defs,X ;
 
       sta    $2200,X    ;
 
       sta    $2200,X    ;
 
       cpx    #$00      ;
 
       cpx    #$00      ;
       bmi    LFB7E      ;
+
       bmi    Bios_CopyCodeToRam_Done ;
       lda    LFC4B,X     ;
+
       lda    DisplayList_Master,X ;
 
       sta    $1F84,X    ;
 
       sta    $1F84,X    ;
       lda    LFCC6,X     ;
+
       lda    GraphicsData_FujiAtari_1,X ;
 
       sta    $1984,X    ;
 
       sta    $1984,X    ;
 
       lda    LFD3D,X    ;
 
       lda    LFD3D,X    ;
Line 897: Line 1,106:
 
       lda    LFE96,X    ;
 
       lda    LFE96,X    ;
 
       sta    $1E84,X    ;
 
       sta    $1E84,X    ;
LFB7E: dex                ;
+
Bios_CopyCodeToRam_Done:
       bne    LFB2C      ;
+
      dex                ;
       jmp    $2306      ; and execute it
+
       bne    Bios_CopyCodeToRam_Loop ;
 +
       jmp    $2306      ; and execute it (CartTest)
  
 
;Start display of Atari logo
 
;Start display of Atari logo
 
+
Display_InitLogo:
LFB84: lda    CartKeyStartPage      ; Read ROM start byte from cart
+
      lda    CartKeyStartPage      ; Read ROM start byte from cart
 
       and    #$04      ; Is rom start greater then $4000?
 
       and    #$04      ; Is rom start greater then $4000?
       beq    LFBBD      ; Branch if not
+
       beq    Display_InitLogo_Done ; Branch if not
       lda    #$03    
+
       lda    #$03
       sta    $F1    
+
       sta    $F1
       sta    $F2    
+
       sta    $F2
       lda    #$49  
+
       lda    #$49
       sta    $EF    
+
       sta    $EF
 
       lda    #$66      ;Palette 1 Color 1
 
       lda    #$66      ;Palette 1 Color 1
 
       sta    P1C1      ;
 
       sta    P1C1      ;
Line 917: Line 1,127:
 
       lda    #$2E      ;Palette 1 Color 3
 
       lda    #$2E      ;Palette 1 Color 3
 
       sta    P1C3      ;
 
       sta    P1C3      ;
       lda    #$AA      ;Set NMI vector to FAAA
+
       lda    #$AA      ;Set NMI vector to Nmi_DrawFujiAndAtari
 
       sta    $F4        ;
 
       sta    $F4        ;
 
       lda    #$FA      ;
 
       lda    #$FA      ;
 
       sta    $F5        ;
 
       sta    $F5        ;
LFBA9: bit    MSTAT      ;Check VBLANK status
+
Display_WaitForVblankEnd:
       bmi    LFBA9      ;Wait till end of VBLANK
+
      bit    MSTAT      ;Check VBLANK status
LFBAD: bit    MSTAT      ;Check BLANK status
+
       bmi    Display_WaitForVblankEnd ;Wait till end of VBLANK
       bpl    LFBAD      ;Wait for start of next VBLANK
+
Display_WaitForVblankStart:
 +
      bit    MSTAT      ;Check BLANK status
 +
       bpl    Display_WaitForVblankStart ;Wait for start of next VBLANK
 
       lda    #$84      ;Set Display list pointer to $1f84
 
       lda    #$84      ;Set Display list pointer to $1f84
 
       sta    DPPL      ;
 
       sta    DPPL      ;
Line 931: Line 1,143:
 
       lda    #$43      ;Maria mode = DMA on/320A or 320C
 
       lda    #$43      ;Maria mode = DMA on/320A or 320C
 
       sta    CTRL      ;
 
       sta    CTRL      ;
LFBBD: rts              ;
+
Display_InitLogo_Done:
 +
      rts              ;
  
; Graphics and Display List Data
+
;=============================================================================
 +
;
 +
; VI. GRAPHICS DATA AND DISPLAY LISTS
 +
;
 +
;=============================================================================
  
LFBBE:                                 ;$2200   Display Lists
+
; --- Display List Definitions for Fuji/Atari Logo ---
 +
; Each entry defines a block of scanlines, pointing to the graphics data
 +
; to be displayed. Copied to $2200 in RAM.
 +
DisplayList_Defs:                       ;$2200
  
 
       .byte $84,$1F,$19,$BB            ;$2200  Blank space
 
       .byte $84,$1F,$19,$BB            ;$2200  Blank space
Line 969: Line 1,189:
  
 
       .byte $AF,$2C,$1D,$00            ;$2241  End of Atari
 
       .byte $AF,$2C,$1D,$00            ;$2241  End of Atari
       .byte $AF,$2C,$1D,$50  
+
       .byte $AF,$2C,$1D,$50
 
       .byte $00,$00
 
       .byte $00,$00
  
Line 980: Line 1,200:
 
       .byte $D5,$2D,$19,$28            ;$2257    Atari line 3
 
       .byte $D5,$2D,$19,$28            ;$2257    Atari line 3
 
       .byte $00,$00
 
       .byte $00,$00
                                                 
+
 
 
       .byte $E8,$2D,$19,$28            ;$225D    Atari line 4
 
       .byte $E8,$2D,$19,$28            ;$225D    Atari line 4
 
       .byte $00,$00
 
       .byte $00,$00
Line 1,005: Line 1,225:
 
       .byte $00,$00
 
       .byte $00,$00
  
; $1F84  Display List List
+
; --- Master Display List for Boot Screen ---
 
+
; This is the main display list that Maria reads. It is a list of pointers
LFC4B: .byte $0F,$22,$06      ;Blank space
+
; to the display list definitions above. Copied to $1F84 in RAM.
 +
DisplayList_Master:
 +
      .byte $0F,$22,$06      ;Blank space
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
 
       .byte $03,$22,$00      ;
 
       .byte $03,$22,$00      ;
       .byte $85,$22,$0D      ;DLI
+
       .byte $85,$22,$0D      ;DLI - Triggers NMI for color cycling
 
       .byte $05,$22,$13      ;Draw Fuji
 
       .byte $05,$22,$13      ;Draw Fuji
 
       .byte $05,$22,$19      ;
 
       .byte $05,$22,$19      ;
Line 1,021: Line 1,243:
 
       .byte $0F,$22,$00      ;Blank area
 
       .byte $0F,$22,$00      ;Blank area
 
       .byte $01,$22,$37      ;Draw "ATARI"
 
       .byte $01,$22,$37      ;Draw "ATARI"
       .byte $00,$22,$4B      ;Line 1  
+
       .byte $00,$22,$4B      ;Line 1
 
       .byte $02,$22,$37
 
       .byte $02,$22,$37
 
       .byte $00,$22,$51      ;Line 2
 
       .byte $00,$22,$51      ;Line 2
Line 1,049: Line 1,271:
 
       .byte $0F,$22,$00      ;
 
       .byte $0F,$22,$00      ;
  
LFCC6
+
; --- Fuji/Atari Logo Graphics Data ---
 +
; These are the raw bitmap graphics for the logo, copied to RAM.
 +
GraphicsData_FujiAtari_1:
 
     .byte $00,$7c,$7f,$8f,$80,$fc,$7f,$8f,$c0,$1f,$87,$f8,$7e,$0f,$e0,$7f
 
     .byte $00,$7c,$7f,$8f,$80,$fc,$7f,$8f,$c0,$1f,$87,$f8,$7e,$0f,$e0,$7f
LFCD6
+
GraphicsData_FujiAtari_2:
 
     .byte $81,$fc,$07,$ff,$80,$7f,$80,$7f,$f8,$1f,$ff,$f0,$00,$7f,$80,$03
 
     .byte $81,$fc,$07,$ff,$80,$7f,$80,$7f,$f8,$1f,$ff,$f0,$00,$7f,$80,$03
LFCE6
+
GraphicsData_FujiAtari_3:
 
     .byte $ff,$fe,$1f,$00,$00,$00,$7f,$80,$00,$00,$3e,$00,$00,$0c,$00,$3f
 
     .byte $ff,$fe,$1f,$00,$00,$00,$7f,$80,$00,$00,$3e,$00,$00,$0c,$00,$3f
LFCF6
+
GraphicsData_FujiAtari_4:
 
     .byte $ff,$ff,$ff,$f0,$00,$c0,$00,$00,$3f,$ff,$ff,$00,$03,$fc,$00,$00
 
     .byte $ff,$ff,$ff,$f0,$00,$c0,$00,$00,$3f,$ff,$ff,$00,$03,$fc,$00,$00
LFD06
+
GraphicsData_FujiAtari_5:
 
     .byte $3f,$00,$3f,$ff,$ff,$ff,$f0,$03,$f0,$00,$00,$3f,$ff,$ff,$fc,$03
 
     .byte $3f,$00,$3f,$ff,$ff,$ff,$f0,$03,$f0,$00,$00,$3f,$ff,$ff,$fc,$03
LFD16
+
GraphicsData_FujiAtari_6:
 
     .byte $fc,$00,$00,$ff,$c0,$00,$03,$ff,$00,$00,$0f,$fc,$00,$00,$3f,$f0
 
     .byte $fc,$00,$00,$ff,$c0,$00,$03,$ff,$00,$00,$0f,$fc,$00,$00,$3f,$f0
LFD26
+
GraphicsData_FujiAtari_7:
 
     .byte $03,$ff,$c3,$fc,$00,$03,$ff,$f0,$00,$03,$ff,$00,$00,$3f,$ff,$00
 
     .byte $03,$ff,$c3,$fc,$00,$03,$ff,$f0,$00,$03,$ff,$00,$00,$3f,$ff,$00
LFD36
+
LFD36:
 
     .byte $00,$3f,$f0,$00,$3f,$c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80
 
     .byte $00,$3f,$f0,$00,$3f,$c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80
LFD46
+
LFD46:
 
     .byte $1f,$87,$f8,$7e,$0f,$f0,$7f,$83,$fc,$01,$ff,$80,$7f,$80,$7f,$e0
 
     .byte $1f,$87,$f8,$7e,$0f,$f0,$7f,$83,$fc,$01,$ff,$80,$7f,$80,$7f,$e0
LFD56
+
LFD56:
 
     .byte $1f,$ff,$f8,$00,$7f,$80,$07,$ff,$fe,$1f,$f0,$00,$00,$7f,$80,$00
 
     .byte $1f,$ff,$f8,$00,$7f,$80,$07,$ff,$fe,$1f,$f0,$00,$00,$7f,$80,$00
LFD66
+
LFD66:
 
     .byte $03,$fe,$00,$0f,$f3,$fc,$00,$03,$ff,$00,$00,$ff,$3f,$c0,$00,$3f
 
     .byte $03,$fe,$00,$0f,$f3,$fc,$00,$03,$ff,$00,$00,$ff,$3f,$c0,$00,$3f
LFD76
+
LFD76:
 
     .byte $f0,$00,$ff,$c3,$fc,$00,$3f,$c0,$ff,$00,$03,$ff,$00,$03,$fc,$0f
 
     .byte $f0,$00,$ff,$c3,$fc,$00,$3f,$c0,$ff,$00,$03,$ff,$00,$03,$fc,$0f
LFD86
+
LFD86:
 
     .byte $f0,$00,$3f,$f0,$3f,$fc,$03,$fc,$00,$ff,$00,$3f,$c0,$03,$ff,$00
 
     .byte $f0,$00,$3f,$f0,$3f,$fc,$03,$fc,$00,$ff,$00,$3f,$c0,$03,$ff,$00
LFD96
+
LFD96:
 
     .byte $0f,$f0,$03,$fc,$00,$3f,$f0,$ff,$c0,$03,$fc,$03,$ff,$ff,$ff,$f0
 
     .byte $0f,$f0,$03,$fc,$00,$3f,$f0,$ff,$c0,$03,$fc,$03,$ff,$ff,$ff,$f0
LFDA6
+
LFDA6:
 
     .byte $03,$ff,$00,$3f,$ff,$ff,$ff,$00,$3f,$f0,$3f,$f0,$03,$fc,$00,$7c
 
     .byte $03,$ff,$00,$3f,$ff,$ff,$ff,$00,$3f,$f0,$3f,$f0,$03,$fc,$00,$7c
LFDB6
+
LFDB6:
 
     .byte $7f,$8f,$80,$7c,$7f,$8f,$80,$1f,$87,$f8,$7e,$07,$f0,$7f,$83,$f8
 
     .byte $7f,$8f,$80,$7c,$7f,$8f,$80,$1f,$87,$f8,$7e,$07,$f0,$7f,$83,$f8
LFDC6
+
LFDC6:
 
     .byte $00,$ff,$c0,$7f,$80,$ff,$c0,$1f,$ff,$fc,$00,$7f,$80,$0f,$ff,$fe
 
     .byte $00,$ff,$c0,$7f,$80,$ff,$c0,$1f,$ff,$fc,$00,$7f,$80,$0f,$ff,$fe
LFDD6
+
LFDD6:
 
     .byte $1f,$fc,$00,$00,$7f,$80,$00,$0f,$fe,$0f,$ff,$ff,$ff,$fc,$03,$ff
 
     .byte $1f,$fc,$00,$00,$7f,$80,$00,$0f,$fe,$0f,$ff,$ff,$ff,$fc,$03,$ff
LFDE6
+
LFDE6:
 
     .byte $00,$ff,$ff,$ff,$ff,$c0,$3f,$f0,$0f,$fc,$03,$fc,$3f,$f0,$00,$03
 
     .byte $00,$ff,$ff,$ff,$ff,$c0,$3f,$f0,$0f,$fc,$03,$fc,$3f,$f0,$00,$03
LFDF6
+
LFDF6:
 
     .byte $ff,$03,$ff,$03,$ff,$00,$00,$3f,$f0,$3f
 
     .byte $ff,$03,$ff,$03,$ff,$00,$00,$3f,$f0,$3f
LFE00
+
LFE00:
 
     .byte $f0,$03,$ff,$03,$fc,$ff
 
     .byte $f0,$03,$ff,$03,$fc,$ff
LFE06
+
LFE06:
 
     .byte $c0,$00,$00,$ff,$c3,$ff,$0f,$fc,$00,$00,$0f,$fc,$3f,$f0,$00,$ff
 
     .byte $c0,$00,$00,$ff,$c3,$ff,$0f,$fc,$00,$00,$0f,$fc,$3f,$f0,$00,$ff
LFE16
+
LFE16:
 
     .byte $c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$87,$f8,$7c,$07
 
     .byte $c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$87,$f8,$7c,$07
LFE26
+
LFE26:
 
     .byte $f0,$7f,$83,$f8,$00,$7f,$c0,$7f,$80,$ff,$80,$1f,$ff,$fe,$00,$7f
 
     .byte $f0,$7f,$83,$f8,$00,$7f,$c0,$7f,$80,$ff,$80,$1f,$ff,$fe,$00,$7f
LFE36
+
LFE36:
 
     .byte $80,$1f,$ff,$fe,$1f,$ff,$00,$00,$7f,$80,$00,$3f,$fe,$55,$55,$55
 
     .byte $80,$1f,$ff,$fe,$1f,$ff,$00,$00,$7f,$80,$00,$3f,$fe,$55,$55,$55
LFE46
+
LFE46:
 
     .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
 
     .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
LFE56
+
LFE56:
 
     .byte $55,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f0
 
     .byte $55,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f0
LFE66
+
LFE66:
 
     .byte $7f,$83,$f0,$00,$3f,$e0,$7f,$81,$ff,$00,$01,$ff,$fe,$00,$7f,$80
 
     .byte $7f,$83,$f0,$00,$3f,$e0,$7f,$81,$ff,$00,$01,$ff,$fe,$00,$7f,$80
LFE76
+
LFE76:
 
     .byte $1f,$ff,$e0,$1f,$ff,$c0,$00,$7f,$80,$00,$ff,$fe,$aa,$aa,$aa,$aa
 
     .byte $1f,$ff,$e0,$1f,$ff,$c0,$00,$7f,$80,$00,$ff,$fe,$aa,$aa,$aa,$aa
LFE86
+
LFE86:
 
     .byte $aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
 
     .byte $aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
LFE96
+
LFE96:
 
     .byte $00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f8,$7f
 
     .byte $00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f8,$7f
LFEA6
+
LFEA6:
 
     .byte $87,$f0,$00,$1f,$e0,$7f,$81,$fe,$00,$00,$1f,$ff,$00,$7f,$80,$3f
 
     .byte $87,$f0,$00,$1f,$e0,$7f,$81,$fe,$00,$00,$1f,$ff,$00,$7f,$80,$3f
LFEB6
+
LFEB6:
 
     .byte $fe,$00,$1f,$ff,$e0,$00,$7f,$80,$01,$ff,$fe,$55,$55,$55,$55,$55
 
     .byte $fe,$00,$1f,$ff,$e0,$00,$7f,$80,$01,$ff,$fe,$55,$55,$55,$55,$55
LFEC6
+
LFEC6:
 
     .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$09
 
     .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$09
LFED6
+
LFED6:
 
     .byte $ca,$c9,$c6,$b4,$12,$08,$1b,$60,$58,$81,$4b,$86,$01,$d8,$bf,$d9
 
     .byte $ca,$c9,$c6,$b4,$12,$08,$1b,$60,$58,$81,$4b,$86,$01,$d8,$bf,$d9
LFEE6
+
LFEE6:
 
     .byte $25,$a0,$7b,$dc,$32,$79,$84,$3b,$7c,$bc,$2f,$e2,$e2,$fa,$8d,$0a
 
     .byte $25,$a0,$7b,$dc,$32,$79,$84,$3b,$7c,$bc,$2f,$e2,$e2,$fa,$8d,$0a
LFEF6
+
LFEF6:
 
     .byte $00,$3b,$c5,$ec,$af,$2d,$8a,$cd,$06,$93
 
     .byte $00,$3b,$c5,$ec,$af,$2d,$8a,$cd,$06,$93
LFF00
+
LFF00:
 
     .byte $6a,$a5,$14,$46,$77,$c4
 
     .byte $6a,$a5,$14,$46,$77,$c4
LFF06
+
LFF06:
 
     .byte $6a,$b2,$53,$36,$ef,$8c,$ce,$0c,$a2,$68,$71,$d3,$73,$e8,$f7,$6d
 
     .byte $6a,$b2,$53,$36,$ef,$8c,$ce,$0c,$a2,$68,$71,$d3,$73,$e8,$f7,$6d
LFF16
+
LFF16:
 
     .byte $06,$b5,$20,$ef,$23,$47,$0c,$51,$55,$c8,$fe,$f4,$58,$c4,$3f,$20
 
     .byte $06,$b5,$20,$ef,$23,$47,$0c,$51,$55,$c8,$fe,$f4,$58,$c4,$3f,$20
LFF26
+
LFF26:
 
     .byte $a7,$67,$38,$b0,$76,$e2,$c4,$d8,$05,$63,$f8,$3c,$58,$3b,$2d,$22
 
     .byte $a7,$67,$38,$b0,$76,$e2,$c4,$d8,$05,$63,$f8,$3c,$58,$3b,$2d,$22
LFF36
+
LFF36:
 
     .byte $cc,$88,$b3,$71,$8f,$1d,$80,$0a,$87,$bd,$a1,$59,$23,$e9,$70,$e2
 
     .byte $cc,$88,$b3,$71,$8f,$1d,$80,$0a,$87,$bd,$a1,$59,$23,$e9,$70,$e2
LFF46
+
LFF46:
 
     .byte $d3,$ec,$46,$68,$80,$42,$39,$ea,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $d3,$ec,$46,$68,$80,$42,$39,$ea,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF56
+
LFF56:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF66
+
LFF66:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF76
+
LFF76:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF86
+
LFF86:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF96
+
LFF96:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFA6
+
LFFA6:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFB6
+
LFFB6:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFC6
+
LFFC6:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFD6
+
LFFD6:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFE6
+
LFFE6:
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
 
     .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  
Line 1,162: Line 1,386:
 
LFDD5 = $FDD5
 
LFDD5 = $FDD5
 
LFE18 = $FE18
 
LFE18 = $FE18
LFE57 = $FE57
+
LFE57 = $FE57
 
LFE84 = $FE84
 
LFE84 = $FE84
 
LFE96 = $FE96
 
LFE96 = $FE96
Line 1,168: Line 1,392:
 
LFF00 = $FF00
 
LFF00 = $FF00
  
GccCopyright
+
GccCopyright:
 
       .byte $47,$43,$43,$28,$43,$29 ; 'GCC(C)'
 
       .byte $47,$43,$43,$28,$43,$29 ; 'GCC(C)'
 
       .byte $31,$39,$38,$34,$2D,$F7 ; '1984-'
 
       .byte $31,$39,$38,$34,$2D,$F7 ; '1984-'
  
; Classic 6502 vectors. Called Cart* because they often
+
;=============================================================================
; are referenced when the game cart is switched in.
+
;
 +
; VII. 6502 HARDWARE VECTORS
 +
;
 +
;=============================================================================
  
CartNMIVectorLo
+
; These are the processor's hard-wired vectors at the top of memory.
      .byte $00,$F0 ; system vector - nmi
+
; The BIOS uses these to direct the CPU on NMI, Reset, and IRQ events.
CartResetVectorLo
+
; When a cartridge is mapped in, its own vectors at these locations are used.
      .word START  ; F884
 
CartIRQVectorLo
 
      .byte $33,$F9 ; system vector - irq
 
  
 +
CartNMIVectorLo:
 +
      .byte $00,$F0 ; System NMI vector points to NmiVector_Rom.
 +
CartResetVectorLo:
 +
      .word START  ; System RESET vector points to $F884.
 +
CartIRQVectorLo:
 +
      .byte $33,$F9 ; System IRQ vector.
  
 
</pre>
 
</pre>

Latest revision as of 20:27, 20 July 2025

7800 NTSC BIOS

This reverse engineered 7800 NTSC BIOS code contains helpful context-comments and builds a 1:1 with the official BIOS ROM. In DASM syntax.


; Disassembly of the Atari 7800 NTSC BIOS (bios7800.bin)
; Originally disassembled by DiStella v2.0 on Sun Mar 08 20:30:38 1998
;
; This version has been heavily commented and refactored for maximum clarity,
; with generic labels (e.g., LF400) renamed to descriptive ones.
; The goal is to explain the inner workings of the BIOS for educational
; and development purposes.
;
; Original comments by:
;   - Keith Henrickson <flipper@phin.com>
;   - Daniel Boris <dboris@home.com>
;   - Mike Saarna (dasm fixups, additional comments)
;   - Gemini 2.5 Pro (semantic meaningful label names, comments galore)
;
; The code must be assembled with DASM.
;

 processor 6502

;=============================================================================
;
; I. HARDWARE AND MEMORY EQUATES
;
;=============================================================================

; --- Misc System Equates ---
LFD80 = $FD80
CartKey           = $FF80   ; Start address of the 8-byte cartridge security key
CartRegion        = $FFF8   ; Cartridge region/signature byte
CartKeyStartPage  = $FFF9   ; Cartridge ROM start page and signature byte
CartResetVectorHi = $FFFD   ; High byte of the cartridge's RESET vector address
LF112             = $F112
LF118             = $F118
LF460             = $F460
LF700             = $F700
LF800             = $F800

; --- 7800 System Control ---
INPTCTRL = $01              ; Input Control Register. Controls memory mapping (BIOS, RAM, Cart) and TIA access.

; --- TIA (Television Interface Adapter) Registers (for 2600 Mode) ---
VSYNC   =  $00              ; Vertical Sync
VBLANK  =  $01              ; Vertical Blank
WSYNC   =  $02              ; Wait for Horizontal Sync
RSYNC   =  $03              ; Reset Horizontal Sync Counter
COLUP0  =  $06              ; Color-Luminance for Player 0
COLUPF  =  $08              ; Color-Luminance for Playfield
COLUBK  =  $09              ; Color-Luminance for Background
PF2     =  $0F              ; Playfield Register 2
RESP1   =  $11              ; Reset Player 1
GRP0    =  $1B              ; Player 0 Graphics
GRP1    =  $1C              ; Player 1 Graphics

; --- Maria (Custom Graphics Chip) Registers ---
BACKGRND =  $20             ; Background Color
POC1     =  $21             ; Palette 0, Color 1
P0C2     =  $22             ; Palette 0, Color 2
POC3     =  $23             ; Palette 0, Color 3
MWSYNC   =  $24             ; Maria Wait for Sync
P1C1     =  $25             ; Palette 1, Color 1
P1C2     =  $26             ; Palette 1, Color 2
P1C3     =  $27             ; Palette 1, Color 3
MSTAT    =  $28             ; Maria Status Register (VBLANK, etc.)
DPPH     =  $2C             ; Display List Pointer High Byte
DPPL     =  $30             ; Display List Pointer Low Byte
CTRL     =  $3C             ; Maria Control Register (DMA, graphics mode)

; --- Zero Page RAM Vectors/Variables ---
DLIAddr       =  $F4        ; RAM vector for Display List Interrupts (NMI)
ConsoleRegion =  $FE        ; Console region byte (used in cart verification)

;=============================================================================
;
; II. CARTRIDGE AUTHENTICATION & MODE SWITCHING LOGIC
;
; This entire block of code from $F000 to $F880 is not executed from ROM.
; Instead, it is copied to RAM ($2300-$2700) by the main BIOS init routine
; at Bios_InitSystem. The jump to $2306 then begins execution from RAM.
;
;=============================================================================

       ORG $F000

; --- NMI Vector (ROM) ---
; This is the hardware NMI vector. It immediately jumps to a RAM vector at $F4,
; which allows the running program (including the BIOS itself) to define its
; own NMI handler.
NmiVector_Rom:
       pha                ; This is the NMI routine.
       jmp (DLIAddr)      ; Jump to RAM NMI vector.


       ORG $F400

; --- RAM Routine: Cartridge Detection and Authentication ---
; This code is designed to be executed from RAM starting at address $2300.
; Its primary job is to determine if a valid, signed 7800 cartridge is
; present. If it is, the system boots in 7800 mode. If not, it attempts
; to boot in 2600 mode.

RamExec_Start:
SwitchTo2600Mode1:
       jmp    Enter2600Mode           ; Branch to the 2600 mode initialization routine.
SwitchTo2600Mode2:
       jmp    Enter2600Mode           ; Branch to the 2600 mode initialization routine.

CartTest:
       lda    #$16                    ; Value to enable Maria and map in the cartridge ROM.
       sta    INPTCTRL                ; Switch in cart + enable Maria.

       ldy    #$FF                    ; Initialize Y to $FF.
       ldx    #$7F                    ; Initialize X to $7F.
; --- Cartridge Presence Test ---
; This loop compares two different ROM regions ($FD80-$FDFF and $FE00-$FE7F).
; If a cartridge is not present, the data bus "floats", and reading any address
; might return the last value seen on the bus (or garbage). By comparing two
; regions that should contain different data, the BIOS can detect this state.
; If the data is the same, it's likely a floating bus, so no cart is present.
CartPresenceCheck_Loop:
       lda    LFE00,X                 ; Read from the $FExx range.
       cmp    LFD80,Y                 ; Compare with the $FDxx range.
       bne    SwitchTo2600Mode1       ; If they differ, the test passes (so far). Branch if they are the same (fail).
       dey                            ;
       dex                            ;
       bpl    CartPresenceCheck_Loop  ; Loop for 128 bytes.

; --- Cartridge Reset Vector Test ---
; A valid 7800 or 2600 cart must have a valid reset vector. A vector of $FFFF
; or $0000 typically indicates an empty socket or a problem.
       lda    CartResetVectorLo       ;
       and    CartResetVectorHi       ;
       cmp    #$FF                    ;
       beq    SwitchTo2600Mode1       ; If RESET vector is $FFFF, then go 2600.
       lda    CartResetVectorLo       ;
       ora    CartResetVectorHi       ;
       beq    SwitchTo2600Mode1       ; If RESET vector is $0000, then go 2600.

; --- Cartridge Signature/Region Verification ---
; This is a series of simple, quick checks on bytes in the $FFF8-$FFF9 region
; of the cartridge ROM to see if it looks like an official 7800 cart.
       lda    CartRegion              ; Read signature byte at $FFF8.
       ora    #ConsoleRegion          ; OR with the console's region byte ($FE).
       cmp    #$FF                    ;
       bne    SwitchTo2600Mode2       ; If low-bit of CartRegion=0, then go 2600.
       lda    CartRegion              ;
       eor    #$F0                    ; Invert high nibble.
       and    #$F0                    ; Isolate the high nibble.
       bne    SwitchTo2600Mode2       ; If high nibble was not originally $F, then go 2600.
       lda    CartKeyStartPage        ; Read signature byte at $FFF9.
       and    #$0B                    ;
       cmp    #$03                    ;
       bne    SwitchTo2600Mode2       ; If low nibble of $FFF9 was not 3 or 7, go 2600.

; --- Cartridge Header Processing ---
; If the quick checks pass, the BIOS proceeds with the full authentication.
       lda    CartKeyStartPage        ;
       and    #$F0                    ; Extract ROM start page from high nibble of $FFF9.
       sta    $EE                     ; Store it in zero page.
       sta    $2406                   ; Store it in RAM for the authentication routine.
       cmp    #$40                    ;
       bcc    SwitchTo2600Mode2       ; If ROM start page < $40 (i.e., address < $4000), fail.
       sbc    #$01                    ;
       cmp    CartResetVectorHi       ; Compare ROM start page with high byte of reset vector.
       bcs    SwitchTo2600Mode2       ; If start page is >= reset vector high byte, fail.
       jsr    $2536                   ; If all checks pass, start the full authentication process.

; --- Obfuscated Authentication Code ---
; The following code is part of the digital signature verification. It involves
; complex mixing, rotating, and lookup operations on the cartridge's security
; key and internal BIOS data tables. Its purpose is to be difficult to analyze
; and replicate. The high-level goal is to compute a hash from the cart key
; and compare it against an expected result.

       lda    #$00
       sta    $F0
       jsr    $241B
       lda    #$16
       sta    INPTCTRL
       ldx    #$00
       txa
Auth_RamFillLoop1:
       sta    $1800,X
       dex
       bne    Auth_RamFillLoop1
       pha
       ldy    #$7F
Auth_CopyRomToRamLoop:
       lda    LFF00,Y
       sta    $1800,Y
       dey
       cpy    #$F8
       bne    Auth_CopyRomToRamLoop
       lda    #$2E
       sta    $2409
       lda    #$24
       sta    $240A

Auth_MainLoop1:
       jsr    $241B
       pla
       jsr    $23FF
       pha
       inc    $2406
       lda    $2406
       cmp    #$FF
       bne    Auth_MainLoop1

       jsr    $241B
       jsr    $2412
       jsr    $2412
       lda    #$36
       sta    $2409
       lda    #$24
       sta    $240A
       dec    $2406
Auth_MainLoop2:
       jsr    $241B
       pla
       jsr    $23FF
       pha
       dec    $2406
       lda    $2406
       cmp    $EE
       bcs    Auth_MainLoop2
       lda    #$60
       sta    CTRL
       ldx    #$77
Auth_XorAndStoreLoop:
       lda    $1800,X
       eor    $1850,X
       eor    $1888,X
       sta    $1A00,X
       dex
       bpl    Auth_XorAndStoreLoop
       lda    $1A00
       and    #$07
       sta    $1A00
       lda    #$00
       ldx    #$04
       sta    $1A00,X
       sta    $2000,X

; --- Final Authentication Check ---
; After all the cryptographic hashing, this is the final comparison.
; It compares two blocks of memory in RAM. If they match, the cart is authentic.
       ldx    #$77
Auth_FinalCompareLoop:
       lda    $2000,X                 ; Read from one workspace area.
       cmp    $1A00,X                 ; Compare with the computed hash.
       bne    Auth_FailAndSwitchTo2600; If they don't match, authentication fails.
       dex
       bpl    Auth_FinalCompareLoop   ; Loop until all bytes are compared.
       jmp    Enter7800Mode           ; AUTHENTICATION PASSED: Jump to 7800 mode init.
Auth_FailAndSwitchTo2600:
       jmp    Enter2600Mode           ; AUTHENTICATION FAILED: Jump to 2600 mode init.


; --- Authentication Subroutines ---
; More opaque subroutines used by the main authentication algorithm.
Auth_Sub_MixAndLookup_Equate =  $F500
       ldx    #$00
Auth_Sub_MixAndLookup_Loop:
       adc    $1800,X
       adc    LFF00,X
       tay
       lda    $2DD5,Y
       sta    $1800,X
       inx
       bne    Auth_Sub_MixAndLookup_Loop
       rts

       ldx    #$00
Auth_Sub_RotateRam_Loop:
       rol    $1800,X
       inx
       bne    Auth_Sub_RotateRam_Loop
       rts

; Subroutine at $241B - This routine briefly disables the cartridge to access BIOS ROM/RAM.
       php
       dec    $F0
       bpl    Auth_Sub_AccessBios_Done
       lda    #$02
       sta    INPTCTRL
Auth_Sub_AccessBios_WaitLoop:
       lda    $F0
       bmi    Auth_Sub_AccessBios_WaitLoop
       lda    #$16
       sta    INPTCTRL
Auth_Sub_AccessBios_Done:
       plp
       rts

; --- Authentication Signature Data Tables ---
; These large blocks of byte data are part of the digital signature scheme.
; They are used as lookup tables and keys during the verification process.
AuthData_Table1: .byte $C7,$65,$AB,$CA,$EE,$F7,$83,$09
AuthData_Table2: .byte $E1,$D0,$92,$67,$62,$B6,$72,$55,$8E,$91,$DC,$C5,$81,$BE,$78,$20
       .byte $59,$B7,$E6,$3D,$06,$45,$AF,$C8,$08,$31,$38,$D1,$FB,$73,$84,$A9
       .byte $17,$FC,$34,$87,$A3,$94,$FA,$90,$B8,$ED,$CE,$3B,$5B,$0A,$43,$D9
       .byte $F3,$53,$82,$B3,$0D,$6D,$5A,$60,$9D,$51,$A7,$B9
AuthData_Table3: .byte $11,$10,$BC,$E4,$7F,$80,$41,$E7,$E3
AuthData_Table4: .byte $F6,$56,$26,$35,$EC,$D6,$DF,$0C,$7F,$F4,$9E,$AC,$52,$46,$EF,$CF
       .byte $BF,$A2,$3F,$A4,$13,$15,$97,$4A,$1C,$B0,$42,$8C,$B1,$05,$58,$80
       .byte $18,$77,$2B,$02,$3E,$A8,$49,$1A,$6A
AuthData_Table5: .byte $CB,$6E,$0B,$8A,$EB,$F1,$4F,$14,$79,$8B,$D8,$9F,$9B,$57,$19,$F8
       .byte $2A,$2D,$76,$0E,$E8,$2E,$4B,$F9,$07,$03,$DE,$93,$16,$7E,$D4,$E5
       .byte $B2,$F0,$7D,$7A,$DA,$D2,$A1,$CC,$1D,$E0,$5E,$23,$A0,$95,$22,$1E
       .byte $36,$85,$FE,$1F,$39
AuthData_Table6: .byte $AA,$89,$96,$AD,$0F,$2F,$C0,$47
AuthData_Table7: .byte $27,$5D,$24,$EA,$C3,$A5,$F5,$21,$5F,$1B,$40,$8F,$AE,$74,$25,$DD
       .byte $C1,$7C,$CD,$A6,$70,$D7,$33,$7B,$2C,$75,$BB,$86,$99,$BD,$54
AuthData_Table8: .byte $9A,$6C,$63,$32,$48,$4C,$8D,$BA
AuthData_Table9: .byte $5C,$61,$C4,$4E,$29,$37,$12,$C6,$98,$9C,$D5,$69,$6B,$E2,$04,$4D
       .byte $E9,$C2,$88,$3A,$DB,$64,$01,$44,$6F,$B5,$F2,$30,$28,$FD,$50,$71
       .byte $3C,$B4,$66,$68,$C9,$D3,$CA,$83,$C7,$AB,$F7,$65,$09,$EE

; --- Main Authentication Routine ($2536) ---
; This routine is the entry point for the signature verification process.
; It copies the 128-byte security key from the cartridge ROM into RAM.
       ldx    #$77      ; ($2536) Start of routine, X=119
       stx    $E4
       stx    $E5
Auth_CopyCartKey_Loop:
       lda    CartKey,X   ; Read a byte from the cart security key area ($FF80-FFFF).
       sta    $1901,X           ; Store it in RAM work area 1.
       sta    $2000,X           ; Store it in RAM work area 2.
       dex                      ; next byte of key
       bpl    Auth_CopyCartKey_Loop ; Loop until all 128 bytes are copied.

       lda    #$02      ;
       sta    INPTCTRL  ; Disable cart ROM to access BIOS routines.
       jsr    Display_InitLogo ; Initialize Maria for the Fuji logo display.
       jsr    $257B
       dec    $F2
       ldx    #$77
       stx    $E4
Auth_CopyInternalKey_Loop:
       lda    LFED5,X
       sta    $1901,X
       dex
       bpl    Auth_CopyInternalKey_Loop
       lda    $E1
       sta    $E3
       jsr    $25E1
       dec    $F2
Auth_CopyWorkspace_Start:
       lda    $E0
       sta    $2572
       ldx    #$77
Auth_CopyWorkspace_Loop:
       lda    $1800,X
Auth_CopyWorkspace_Store:
       sta    $2000,X
       dex
       bpl    Auth_CopyWorkspace_Loop
       rts

; --- More Authentication Subroutines ---
       jsr    $2639   ; ($257B)
       ldy    $E5
       iny
Auth_Sub_KeyProcess_OuterLoop:
       STY    $E1
       TYA
       clc
       adc    $E2
       pha
Auth_Sub_KeyProcess_ClearRam:
       tax
       lda    #$00
       sta    $2671
Auth_Sub_KeyProcess_ClearRam_Loop:
       sta    $1800,X
       dex
Auth_Sub_KeyProcess_ClearRam_Check:
       bne    Auth_Sub_KeyProcess_ClearRam_Loop
       sta    $1800
Auth_Sub_KeyProcess_SetupCounters:
       iny
       STY    $266E
       STY    $2674
       STY    $267C
       STY    $2681
       ldx    #$00
Auth_Sub_KeyProcess_InnerLoop:
       dec    $266E
       dec    $2674
       dec    $267C
       dec    $2681
       dec    $E1
       bmi    Auth_Sub_KeyProcess_Done
Auth_Sub_KeyProcess_BitCheck:
       ldy    $E1
       lda    $2000,Y
       and    $25D9,X
       beq    Auth_Sub_KeyProcess_NextBit
       lda    $2662,X
       sta    $2672
       jsr    $266A
Auth_Sub_KeyProcess_NextBit:
       inx
       cpx    #$08
       bmi    Auth_Sub_KeyProcess_BitCheck
       jmp    $25A4
Auth_Sub_KeyProcess_Done:
       pla
       sta    $E1
       lda    #$01
       sta    $E0
       rts

AuthData_Bitmasks: .byte $01,$02,$04,$08,$10,$20,$40,$80

       jsr    $2639
       lda    $E3
       sec
       sbc    $E4
       sta    $E0
       sta    $E1
       ldx    #$00
       stx    $1800
       stx    $268F
       stx    $26AC
       dex
       stx    $26A9
       stx    $268C
       stx    $2692
       stx    $269A
       stx    $269F
       ldx    #$07
       inc    $26A9
       inc    $268C
       inc    $2692
       inc    $269A
       inc    $269F
       dec    $E1
       bmi    Auth_Sub_Op_Done
Auth_Sub_Op_Loop:
       lda    $2662,X
       sta    $2690
       sta    $26AD
       jsr    $26A6
       bcc    Auth_Sub_Op_Next
       jsr    $2688
Auth_Sub_Op_Next:
       dex
       bpl    Auth_Sub_Op_Loop
       jmp    $2608
Auth_Sub_Op_Done:
       lda    $E3
       sta    $E1
       rts

       ldx    $E4   ; ($2639)
       inx
       stx    $E2
       ldy    #$00
       STY    $1900
Auth_Sub_Rotate_OuterLoop:
       lda    $2662,Y
       sta    $2655
       iny
       lda    $2662,Y
       sta    $2659
       ldx    $E2
       clc
Auth_Sub_Rotate_InnerLoop:
       lda    $1900,X
       rol
       sta    $1900,X
       dex
       bpl    Auth_Sub_Rotate_InnerLoop
       cpy    #$07
       bmi    Auth_Sub_Rotate_OuterLoop
       rts

AuthData_Indices: .byte $19,$1A,$1B,$1C,$1D,$1E,$1F,$21

       ldy    $E2
       clc
Auth_Sub_Add_Loop:
       lda    $1800,Y
       adc    $1900,Y
       sta    $1800,Y
       dey
       bpl    Auth_Sub_Add_Loop
       bcc    Auth_Sub_Add_NoCarry
       lda    $1700,Y
       adc    #$00
       sta    $1700,Y
       dey
       jmp    $2679
Auth_Sub_Add_NoCarry:
       rts

       ldy    $E2
       sec
Auth_Sub_Subtract_Loop:
       lda    $1800,Y
       sbc    $1900,Y
       sta    $1800,Y
       dey
       bpl    Auth_Sub_Subtract_Loop
       bcs    Auth_Sub_Subtract_NoBorrow
       lda    $1700,Y
       sbc    #$00
       sta    $1700,Y
       dey
       jmp    $2697
Auth_Sub_Subtract_NoBorrow:
       rts

       ldy    #$00
       lda    $1800,Y
       cmp    $1900,Y
       beq    Auth_Sub_Compare_Equal
Auth_Sub_Compare_NotEqual:
       rts

Auth_Sub_Compare_Equal:
       cpy    $E2
       beq    Auth_Sub_Compare_NotEqual
       iny
       jmp    $26A8

; --- 7800 Mode Initialization ---
       ORG $F7B9
; This label is an equate, not a location. It calculates the correct RAM address
; for the routine, which is needed by the code executing from RAM.
; ROM address $F7B9 -> RAM address $26B9. Offset is $D100.
Enter7800Mode = . - $D100
Routine_Enter7800Mode:
       ldx    #$16        ; Enable Maria and Cartridge ROM.
       stx    INPTCTRL    ; Lock out BIOS, enable cartridge.
       txs                ; Set up stack pointer.
       SED                ; Set Decimal Mode (a 7800 convention, often cleared by games).
       jmp (CartResetVectorLo) ; Jump to the game's starting address on the cartridge.

; --- 2600 Mode Initialization ---
       ORG $F7C2
; This label is also an equate to calculate the correct RAM address.
; ROM address $F7C2 -> RAM address $26C2. Offset is $D100.
Enter2600Mode = . - $D100
Routine_Enter2600Mode:
       lda    #$02        ; Enable 7800 RAM and BIOS ROM.
       sta    INPTCTRL    ;
       ldx    #$7F
; Copy the 2600 TIA setup code from BIOS ROM into RIOT RAM ($0480).
CopyTiaInitToRam_Loop:
       lda    TiaInitCode,X
       sta    $0480,X
       dex
       bpl    CopyTiaInitToRam_Loop
       jmp    $0480       ; Jump to the newly copied code in RIOT RAM to execute it.

; --- 2600 TIA Setup Code (Executed from RIOT RAM at $0480) ---
TiaInitCode:
       lda    #$00        ;
       tax                ;
       sta    INPTCTRL    ; Disable 7800 RAM/BIOS, giving full control to cart.
; Clear all TIA registers to put it in a known state.
TiaInit_ClearLoop:
       sta    RSYNC,X
       inx                ;
       cpx    #$2A        ;
       bne    TiaInit_ClearLoop
       sta    WSYNC       ; Wait for horizontal sync.
       lda    #$04        ;
       nop                ;
       bmi    TiaInit_SetColors1
       ldx    #$04
TiaInit_DelayLoop:
       dex
       bpl    TiaInit_DelayLoop
       txs
       sta    $0110
       jsr    $04CB
       jsr    $04CB
       sta    RESP1
       sta    GRP0
       sta    GRP1
       sta    PF2
       nop
       sta    WSYNC
       lda    #$00
       nop
       bmi    TiaInit_SetColors1
       bit    RSYNC
       bmi    TiaInit_SetColors2
TiaInit_SetColors1:
       lda    #$02
       sta    COLUBK
       sta    LF112
       bne    TiaInit_Finalize
TiaInit_SetColors2:
       bit    WSYNC
       bmi    TiaInit_SetColors3
       lda    #$02
       sta    COLUP0
       sta    LF118
       sta    LF460
       bne    TiaInit_Finalize
TiaInit_SetColors3:
       sta    DPPH
       lda    #$08
       sta    GRP0
       jsr    $04CB
       nop
       bit    WSYNC
       bmi    TiaInit_SetColors1
TiaInit_Finalize:
       lda    #$FD
       sta    COLUPF
       jmp (CartResetVectorLo) ; Jump to the 2600 game's starting address on the cartridge.
       nop

;=============================================================================
;
; III. BIOS ENTRY, POWER-ON SELF TEST (POST), AND SYSTEM INIT
;
;=============================================================================

       ORG $F880

; --- Self-Test Failure Handler ---
; This code is jumped to whenever a POST routine fails. It writes an error
; code to INPTCTRL, which can be read by external diagnostic hardware.
Post_FailHandler:
       lda    #$1D
       sta    INPTCTRL    ; Enable TIA/Cart/lock out INPTCTRL.

; --- BIOS Entry Point / Cold Start ---
START:                    ; $F884
       SEI                ; Disable interrupts on power-on.
       CLD                ; Clear decimal flag.
       lda    #$02        ;
Bios_SetRamAndBios:
       sta    INPTCTRL    ; Enable 7800 RAM and map BIOS into memory.
       lda    #$FB        ; Set high byte of NMI vector to $FB.
       sta    $F5         ;
       lda    #$12        ; Set low byte of NMI vector to $12.
       sta    $F4         ; NMI vector is now $FB12 (points to IRQ cleanup).
       lda    #$7F        ;
       sta    CTRL        ; Turn off Maria DMA.
       lda    #$00        ;
       sta    BACKGRND    ; Set background color to black.

; --- POST: RAM Test 1 (Basic) ---
; This is a quick test of the two 2KB RAM chips ($2000-$27FF).
; It writes several patterns to each byte and reads them back.
       ldx    #$05        ; Loop counter for the 6 test patterns.
Post_RamTest1_PatternLoop:
       lda    Post_RamTest_Data,X ; Load a test pattern ($00, $FF, $55, $AA, $69, $0F).
       ldy    #$00        ; Inner loop counter for 256 bytes.
Post_RamTest1_PageLoop:
       sta    $2000,Y     ; Write pattern to first RAM chip.
       cmp    $2000,Y     ; Read it back and compare.
       bne    Post_RamTest_Fail1 ; If it fails, branch to error handler.
       sta    $2100,Y     ; Write pattern to second RAM chip.
       cmp    $2100,Y     ; Read it back and compare.
       bne    Post_RamTest_Fail1 ; If it fails, branch to error handler.
       dey                ;
       bne    Post_RamTest1_PageLoop ; Loop through all 256 bytes of a page.
       dex                ;
       bpl    Post_RamTest1_PatternLoop ; Loop to the next test pattern.

; --- POST: RAM Mirror Test ---
; Checks that the RAM is correctly mirrored every 256 bytes.
       lda    #$43        ; Check RAM 0 mirror.
       sta    $2080       ; Write to $2080.
       cmp    $80         ; Compare with $0080 (a mirror).
       bne    Post_RamMirror_Fail ; make sure they match. If not, fail selftest.
       sta    $2180       ; Check RAM 1 mirror
       cmp    $0180       ;
       bne    Post_RamMirror_Fail ; make sure they match. If not, fail selftest.
       jmp    Post_CpuTest_Start ; continue selftest
Post_RamMirror_Fail:
       ldy    #$04        ;
       jmp    Post_FailHandler ; selftest fail.

; --- POST: RAM Failure Handlers ---
; These routines are jumped to from the RAM tests to indicate failure.
Post_RamTest_Fail1:
       sta    $1800       ; test store and compare
       cmp    $1800
       bne    Post_RamTest_Fail3 ; some kind of error code is being determined
Post_RamTest_Fail2:
       ldy    #$01
       jmp    Post_FailHandler

Post_RamTest_Fail_Indirect:
       ldy    #$02
       jmp    $F880

Post_RamTest_Fail3:
       ldy    #$03
       jmp    Post_FailHandler

; --- POST: RAM Test 2 (Comprehensive) ---
; This is a more thorough RAM test called later in the boot process. It uses
; indirect addressing to test all 8 pages of the 4KB RAM.
Post_RamTest2_Start:
       lda    #$00
       sta    $F0         ; Base address low byte pointer.
       sta    $F2         ;
       ldy    #$07        ; Loop counter for 8 pages.
       STY    $F4
Post_RamTest2_OuterLoop:
       lda    Post_RamTest_AddrHi1,Y ; Load high byte of address for RAM chip 1.
       sta    $F1
       lda    Post_RamTest_AddrHi2,Y ; Load high byte of address for RAM chip 2.
       sta    $F3
       ldx    #$05        ; Loop counter for 6 test patterns.
Post_RamTest2_PatternLoop:
       lda    Post_RamTest_Data,X ; Load a test pattern.
Post_RamTest2_InnerLoop:
       ldy    #$00        ; Inner loop counter for 256 bytes.
Post_RamTest2_ByteLoop:
       sta    ($F0),Y     ; Write to RAM 1 via indirect pointer ($F0/$F1).
       cmp    ($F0),Y     ; Read back and compare.
       bne    Post_RamTest_Fail2 ; Fail.
       sta    ($F2),Y     ; Write to RAM 2 via indirect pointer ($F2/$F3).
       cmp    ($F2),Y     ; Read back and compare.
       bne    Post_RamTest_Fail_Indirect ; Fail.
       dey
       bne    Post_RamTest2_ByteLoop ; Loop through page.
       dex
       bpl    Post_RamTest2_PatternLoop ; Loop through patterns.
       dec    $F4
       ldy    $F4
       bpl    Post_RamTest2_OuterLoop ; Loop through pages.
       jmp    Bios_InitSystem ; ram test passed, so jump in here.

; --- RAM Test Data ---
Post_RamTest_Data: .byte $00,$FF,$55,$AA,$69,$0F
Post_RamTest_AddrHi1: .byte $22,$23,$24,$25,$26,$27,$22,$23
Post_RamTest_AddrHi2: .byte $18,$19,$1A,$1B,$1C,$1D,$1E,$1F

Post_CpuTest_Fail:
       ldy    #$00       ; local place for selftest fail branch target
       jmp    Post_FailHandler

; --- POST: 6502 CPU Test ---
; This section exhaustively tests the 6502's instruction set, flags,
; and addressing modes to ensure the CPU is functioning correctly.
Post_CpuTest_Start:
       lda    #$AA       ; test some flags and branches
       beq    Post_CpuTest_Fail ; test failed
       bpl    Post_CpuTest_Fail ; test failed
       bmi    CpuTest_CheckBne ; test passed
       jmp    Post_CpuTest_Fail ; test failed
CpuTest_CheckBne:
       bne    CpuTest_CheckStore ; test passed
       jmp    Post_CpuTest_Fail ; test failed
CpuTest_CheckStore:
       sta    $AA        ; store AA to 00AA
       cmp    $AA        ; compare it back
       bne    Post_CpuTest_Fail ; if it doesn't match, selftest fail
       lda    #$00       ; do some more flag tests
       bne    Post_CpuTest_Fail ;
       bmi    Post_CpuTest_Fail ;
       bpl    CpuTest_CheckBeq ; test passed
       jmp    Post_CpuTest_Fail ;
CpuTest_CheckBeq:
       beq    CpuTest_CheckCmp ; test passed
       jmp    Post_CpuTest_Fail ;
CpuTest_CheckCmp:
       cmp    #$00       ; test the compare instruction
       bne    Post_CpuTest_Fail ;
       bcc    Post_CpuTest_Fail ;
       bcs    CpuTest_CheckCmpBcs ; test passed, since they're equal
       jmp    Post_CpuTest_Fail ;
CpuTest_CheckCmpBcs:
       cmp    #$01       ; compare it to 01
       bcs    Post_CpuTest_Fail ;
       bcc    CpuTest_CheckCpx ; A < 01, so carry is clear
       jmp    Post_CpuTest_Fail ;
CpuTest_CheckCpx:
       ldx    #$55       ; test comparisons with the X register
       cpx    #$56       ;
       beq    Post_CpuTest_Fail ;
       stx    $01AA      ;
       cpx    $01AA      ;
       bne    Post_CpuTest_Fail ;
       ldy    $AA        ; and with the Y register.
       cpy    #$AB       ;
CpuTest_CheckCpy:
       beq    Post_CpuTest_Fail ;
       STY    $0155      ; put some stuff in the stack area to test stack
       cpy    $0155      ; and then access this data in many different ways
       bne    Post_CpuTest_Fail ;
       dex               ;
       txs               ;
       inx               ;
       pla               ;
       cmp    #$AA       ;
       bne    Post_CpuTest_Fail_Central ;
       txa               ;
       pha               ;
       cpx    $0155      ;
       bne    Post_CpuTest_Fail_Central ;
       TYA               ;
       cmp    #$AA       ;
       bne    Post_CpuTest_Fail_Central ;
       tax               ;
       lda    $0100,X    ;
       tay               ;
       cpy    #$55       ;
       bne    Post_CpuTest_Fail_Central ;
       lda    VSYNC,X    ;
       cmp    $AA        ;
       bne    Post_CpuTest_Fail_Central ;
       cmp    #$AA       ;
       bne    Post_CpuTest_Fail_Central ;
       eor    #$FF       ;
       sta    $0000,Y    ;
       cmp    $55        ;
       bne    Post_CpuTest_Fail_Central ;
       cmp    $0100,Y    ;
       bne    Post_CpuTest_Fail_Central ;
       cmp    $20AB,X    ;
       bne    Post_CpuTest_Fail_Central ;
       lda    #$20       ;
       sta    $F1        ;
       lda    #$CC       ;
       sta    $F0        ;
       sta    ($46,X)    ;
       cmp    $CC        ;
       bne    Post_CpuTest_Fail_Central ;
       sta    ($F0),Y    ;
       cmp    $2121      ;
       bne    Post_CpuTest_Fail_Central ;
       lda    #$EE       ; test the indirect jump by setting up a jump
       sta    $F0        ; to Post_CpuMath_Start
       lda    #$F9       ;
       sta    $F1        ;
       jmp ($00F0)        ; and do it.

CpuTest_ShouldNotBeReached:
       jmp    Post_CpuTest_Fail_Central

Post_CpuTest_Fail_Central:
       jmp    Post_CpuTest_Fail


; --- POST: CPU Math and Logic Tests ---
Post_CpuMath_Start:
       lda    #$55       ; now test out the math functions.
       clc
       adc    #$55
       nop
       bcs    Post_CpuTest_Fail_Central ; test addition.
       bpl    Post_CpuTest_Fail_Central
       beq    Post_CpuTest_Fail_Central
       cmp    #$AA       ; make sure it worked
       bne    Post_CpuTest_Fail_Central
       adc    #$55       ; test addition again.
CpuMath_TestAdcCarry:
       nop
       bcc    Post_CpuTest_Fail_Central
       bmi    Post_CpuTest_Fail_Central
       bne    Post_CpuTest_Fail_Central
       sbc    #$55       ; test subtraction
       bcs    Post_CpuTest_Fail_Central
       bpl    Post_CpuTest_Fail_Central
       beq    Post_CpuTest_Fail_Central
       cmp    #$AB       ; make sure it worked
       bne    Post_CpuTest_Fail_Central
       clc
       sbc    #$AA       ; test subtraction again
       bcc    Post_CpuTest_Fail_Central
       bmi    Post_CpuTest_Fail_Central
       bne    Post_CpuTest_Fail_Central
       lda    #$FF       ; set up a stack
       tax               ; and do all kinds of stuff in it for tests
       inx
       bne    CpuMath_Fail
       dex
       beq    CpuMath_Fail
       bpl    CpuMath_Fail
       cpx    #$FF
       bne    CpuMath_Fail
       tay
       iny
       bne    CpuMath_Fail
       dey
       beq    CpuMath_Fail
       iny
       bne    CpuMath_Fail
       sta    $F0
       inc    $F0
       bne    CpuMath_Fail
       cpy    $F0
       bne    CpuMath_Fail
       dec    $F0
       beq    CpuMath_Fail
       cmp    $F0
       bne    CpuMath_Fail
       lda    #$AA
       clc
       rol               ; now we get onto the more complex math instrs
       rol
       rol
       cmp    #$52
       bne    CpuMath_Fail ; make sure rotate left works.
       ror
       ror
       ror
       cmp    #$AA
       beq    CpuMath_TestAsl ; test rotate right
CpuMath_Fail:
       jmp    Post_CpuTest_Fail ; fail!

CpuMath_TestAsl:
       asl               ; test arithmetic shift left
       bcc    CpuMath_Fail
       asl
       bcs    CpuMath_Fail
       asl
       cmp    #$50
       bne    CpuMath_Fail
       eor    #$05
       lsr               ; and logical shift right
       bcc    CpuMath_Fail
       lsr
       bcs    CpuMath_Fail
       lsr
       cmp    #$0A
       bne    CpuMath_Fail
       lda    #$55       ; now test the ands and ors.
       ora    #$1B
       cmp    #$5F
       bne    CpuMath_Fail
       and    #$55
       and    #$1B
       cmp    #$11
       bne    CpuMath_Fail
       ora    #$55
       eor    #$1B       ; and the eors
       cmp    #$4E
       bne    CpuMath_Fail
       jsr    Cpu_TestJsr ; test jump subroutine instruction
       jmp    CpuMath_Fail ; if we return, fail

Cpu_TestJsr:
       tsx
       cpx    #$52       ; check stack pointer
       bne    CpuMath_Fail ; fail if not right
       pla
       cmp    #$8D
       bne    CpuMath_Fail
       pla
       cmp    #$FA
       bne    CpuMath_Fail ; get the old return address off the stack
       lda    #$F8
       pha
       lda    #$E6
       pha               ; and make our own
       rts               ; and 'return' to Post_RamTest2_Start

       jmp    CpuMath_Fail ; another jump to catch a failure

;=============================================================================
;
; IV. NMI HANDLER (FUJI LOGO DISPLAY)
;
;=============================================================================

; This NMI routine is responsible for drawing the "Fuji" mountain logo and
; the "ATARI" text on the screen during the boot-up/authentication process.
; It is called on every VBLANK. Its main job is to manipulate Maria's palette
; registers to create the signature color-cycling effect on the Fuji logo.

Nmi_DrawFujiAndAtari:
       txa          ;Save A
       pha          ;
       lda    #$43  ;Setup control register
       sta    CTRL  ;
       ldx    #$0F  ; Handle the color scrolling in the FUJI
       lda    $EF
       sta    P0C2
       bit    $F3
       bvc    Nmi_Sync3
       bpl    Nmi_Sync2
Nmi_Sync1:
       sta    MWSYNC ;Wait for 3 scanlines
Nmi_Sync2:
       sta    MWSYNC ;
Nmi_Sync3:
       sta    MWSYNC ;
       sec
       sbc    #$10
       cmp    #$10
       bcs    Nmi_StoreColor
       sbc    #$0F
Nmi_StoreColor:
       sta    P0C2
       dex
       bpl    Nmi_Sync1 ;Branch to do next section of fuji
       ldx    #$40    ;set 160x2/160x4 mode
       stx    CTRL    ;
       and    #$F0    ;
       ora    #$0E    ;set Palette 1 color 3
       sta    P1C3    ;
       lda    $EF     ;
       and    #$F0    ;
       ora    #$06    ;set Palette 1 color 1
       sta    P1C1    ;
       and    #$F0
       clc
       adc    #$40
       bcc    Nmi_SetPalette1Color2
       adc    #$0F
Nmi_SetPalette1Color2:
       ora    #$03   ;set Palette 1 color 2
       sta    P1C2
       dec    $F1
       bpl    Nmi_RestoreRegs
       lda    $F3
       adc    #$60
       bcc    Nmi_UpdateFrameCounter
       lda    $EF
       clc
       adc    #$10
       bcc    Nmi_StoreNewBaseColor
       adc    #$0F
Nmi_StoreNewBaseColor:
       sta    $EF
       lda    $F2
       sta    $F1
       lda    #$00
Nmi_UpdateFrameCounter:
       sta    $F3
Nmi_RestoreRegs:
       lda    #$02
       sta    $F0
       pla
       tax
       pla
       rti

Trap_InfiniteLoop:
       jmp    Trap_InfiniteLoop

;=============================================================================
;
; V. SYSTEM INITIALIZATION (POST-TEST)
;
;=============================================================================

; This routine is executed after all Power-On Self Tests have passed.
Bios_InitSystem:
       ldx    #$FF       ; selftest has passed, start system init
       txs               ; set up a stack
       lda    #$00       ; Clear TIA/Maria registers
       tax               ;
Bios_ClearRegsLoop:
       sta    $01,X ;
       inx               ;
       cpx    #$2C       ;
       bne    Bios_ClearRegsLoop
       lda    #$02       ;
       sta    INPTCTRL   ; Enable 7800 RAM
       ldx    #$00       ;
       stx    BACKGRND   ; Set background color

; --- Copy BIOS Routines and Data to RAM ---
; This is a critical step. It copies the cartridge authentication code,
; graphics display routines, and associated data from the BIOS ROM
; into the main system RAM. This allows the BIOS to run its complex
; authentication logic from RAM, freeing up the cartridge bus.
Bios_CopyCodeToRam_Loop:
       lda    RamExec_Start,X ; copy the authentication and title screen to
       sta    $2300,X    ; ram
       lda    Auth_Sub_MixAndLookup_Equate,X ;
       sta    $2400,X    ;
       lda    AuthData_Table8,X ;
       sta    $2500,X    ;
       lda    LF700,X    ;
       sta    $2600,X    ;
       lda    LF800,X    ;
       sta    $2700,X    ;
       lda    DisplayList_Defs,X ;
       sta    $2200,X    ;
       cpx    #$00       ;
       bmi    Bios_CopyCodeToRam_Done ;
       lda    DisplayList_Master,X ;
       sta    $1F84,X     ;
       lda    GraphicsData_FujiAtari_1,X ;
       sta    $1984,X     ;
       lda    LFD3D,X     ;
       sta    $1A84,X     ;
       lda    LFDB4,X     ;
       sta    $1B84,X     ;
       lda    LFE18,X     ;
       sta    $1C84,X     ;
       lda    LFE57,X     ;
       sta    $1D84,X     ;
       lda    LFE96,X     ;
       sta    $1E84,X     ;
Bios_CopyCodeToRam_Done:
       dex                ;
       bne    Bios_CopyCodeToRam_Loop ;
       jmp    $2306       ; and execute it (CartTest)

;Start display of Atari logo
Display_InitLogo:
       lda    CartKeyStartPage      ; Read ROM start byte from cart
       and    #$04       ; Is rom start greater then $4000?
       beq    Display_InitLogo_Done ; Branch if not
       lda    #$03
       sta    $F1
       sta    $F2
       lda    #$49
       sta    $EF
       lda    #$66       ;Palette 1 Color 1
       sta    P1C1       ;
       lda    #$56       ;Palette 1 Color 2
       sta    P1C2       ;
       lda    #$2E       ;Palette 1 Color 3
       sta    P1C3       ;
       lda    #$AA       ;Set NMI vector to Nmi_DrawFujiAndAtari
       sta    $F4        ;
       lda    #$FA       ;
       sta    $F5        ;
Display_WaitForVblankEnd:
       bit    MSTAT      ;Check VBLANK status
       bmi    Display_WaitForVblankEnd ;Wait till end of VBLANK
Display_WaitForVblankStart:
       bit    MSTAT      ;Check BLANK status
       bpl    Display_WaitForVblankStart ;Wait for start of next VBLANK
       lda    #$84       ;Set Display list pointer to $1f84
       sta    DPPL       ;
       lda    #$1F       ;
       sta    DPPH       ;
       lda    #$43       ;Maria mode = DMA on/320A or 320C
       sta    CTRL       ;
Display_InitLogo_Done:
       rts               ;

;=============================================================================
;
; VI. GRAPHICS DATA AND DISPLAY LISTS
;
;=============================================================================

; --- Display List Definitions for Fuji/Atari Logo ---
; Each entry defines a block of scanlines, pointing to the graphics data
; to be displayed. Copied to $2200 in RAM.
DisplayList_Defs:                       ;$2200

       .byte $84,$1F,$19,$BB            ;$2200   Blank space
       .byte $00,$00

       .byte $84,$40,$19,$1F,$BB        ;$2206   First DL on screen
       .byte $00,$00

       .byte $85,$1C,$19,$4A            ;$220D   Blank space before Fuji
       .byte $00,$00

       .byte $89,$1C,$19,$4A            ;$2213   Fuji line 1
       .byte $00,$00

       .byte $8D,$1C,$19,$48            ;$2219   Fuji line 2
       .byte $00,$00

       .byte $91,$1B,$19,$46            ;$221F   Fuji line 3
       .byte $00,$00

       .byte $96,$19,$19,$42            ;$2225   Fuji line 4
       .byte $00,$00

       .byte $9D,$17,$19,$3E            ;$222B   Fuji line 5
       .byte $00,$00

       .byte $A6,$17,$19,$3E            ;$2231   Fuji line 6
       .byte $00,$00

       .byte $AF,$2C,$1C,$00            ;$2237   Start of Atari
       .byte $AF,$2C,$1C,$50            ;        and between lines
       .byte $00,$00

       .byte $AF,$2C,$1D,$00            ;$2241   End of Atari
       .byte $AF,$2C,$1D,$50
       .byte $00,$00

       .byte $AF,$2D,$19,$28            ;$224B    Atari line 1
       .byte $00,$00

       .byte $C2,$2D,$19,$28            ;$2251    Atari line 2
       .byte $00,$00

       .byte $D5,$2D,$19,$28            ;$2257     Atari line 3
       .byte $00,$00

       .byte $E8,$2D,$19,$28            ;$225D     Atari line 4
       .byte $00,$00

       .byte $AF,$2D,$1A,$28            ;$2263     Atari line 5
       .byte $00,$00

       .byte $C2,$2D,$1A,$28            ;$2269     Atari line 6
       .byte $00,$00

       .byte $D5,$2D,$1A,$28            ;$226F     Atari line 7
       .byte $00,$00

       .byte $E8,$2D,$1A,$28            ;$2275     Atari line 8
       .byte $00,$00

       .byte $AF,$2D,$1B,$28            ;$227B     Atari line 9
       .byte $00,$00

       .byte $C2,$2D,$1B,$28            ;$2281     Atari line 10
       .byte $00,$00

       .byte $D5,$2D,$1B,$28            ;$2287     Atari line 11
       .byte $00,$00

; --- Master Display List for Boot Screen ---
; This is the main display list that Maria reads. It is a list of pointers
; to the display list definitions above. Copied to $1F84 in RAM.
DisplayList_Master:
       .byte $0F,$22,$06      ;Blank space
       .byte $0F,$22,$00      ;
       .byte $0F,$22,$00      ;
       .byte $0F,$22,$00      ;
       .byte $03,$22,$00      ;
       .byte $85,$22,$0D      ;DLI - Triggers NMI for color cycling
       .byte $05,$22,$13      ;Draw Fuji
       .byte $05,$22,$19      ;
       .byte $05,$22,$1F      ;
       .byte $05,$22,$25      ;
       .byte $05,$22,$2B      ;
       .byte $05,$22,$31      ;
       .byte $0F,$22,$00      ;Blank area
       .byte $01,$22,$37      ;Draw "ATARI"
       .byte $00,$22,$4B      ;Line 1
       .byte $02,$22,$37
       .byte $00,$22,$51      ;Line 2
       .byte $02,$22,$37
       .byte $00,$22,$57      ;Line 3
       .byte $02,$22,$37
       .byte $00,$22,$5D      ;Line 4
       .byte $02,$22,$37
       .byte $00,$22,$63      ;Line 5
       .byte $02,$22,$37
       .byte $00,$22,$69      ;Line 6
       .byte $02,$22,$37
       .byte $00,$22,$6F      ;Line 7
       .byte $02,$22,$37
       .byte $00,$22,$75      ;Line 8
       .byte $02,$22,$37
       .byte $00,$22,$7B      ;Line 9
       .byte $02,$22,$37
       .byte $00,$22,$81      ;Line 10
       .byte $02,$22,$37
       .byte $00,$22,$87      ;Line 11
       .byte $01,$22,$41
       .byte $0F,$22,$00      ;Blank Space
       .byte $0F,$22,$00      ;
       .byte $0F,$22,$00      ;
       .byte $0F,$22,$00      ;
       .byte $0F,$22,$00      ;

; --- Fuji/Atari Logo Graphics Data ---
; These are the raw bitmap graphics for the logo, copied to RAM.
GraphicsData_FujiAtari_1:
    .byte $00,$7c,$7f,$8f,$80,$fc,$7f,$8f,$c0,$1f,$87,$f8,$7e,$0f,$e0,$7f
GraphicsData_FujiAtari_2:
    .byte $81,$fc,$07,$ff,$80,$7f,$80,$7f,$f8,$1f,$ff,$f0,$00,$7f,$80,$03
GraphicsData_FujiAtari_3:
    .byte $ff,$fe,$1f,$00,$00,$00,$7f,$80,$00,$00,$3e,$00,$00,$0c,$00,$3f
GraphicsData_FujiAtari_4:
    .byte $ff,$ff,$ff,$f0,$00,$c0,$00,$00,$3f,$ff,$ff,$00,$03,$fc,$00,$00
GraphicsData_FujiAtari_5:
    .byte $3f,$00,$3f,$ff,$ff,$ff,$f0,$03,$f0,$00,$00,$3f,$ff,$ff,$fc,$03
GraphicsData_FujiAtari_6:
    .byte $fc,$00,$00,$ff,$c0,$00,$03,$ff,$00,$00,$0f,$fc,$00,$00,$3f,$f0
GraphicsData_FujiAtari_7:
    .byte $03,$ff,$c3,$fc,$00,$03,$ff,$f0,$00,$03,$ff,$00,$00,$3f,$ff,$00
LFD36:
    .byte $00,$3f,$f0,$00,$3f,$c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80
LFD46:
    .byte $1f,$87,$f8,$7e,$0f,$f0,$7f,$83,$fc,$01,$ff,$80,$7f,$80,$7f,$e0
LFD56:
    .byte $1f,$ff,$f8,$00,$7f,$80,$07,$ff,$fe,$1f,$f0,$00,$00,$7f,$80,$00
LFD66:
    .byte $03,$fe,$00,$0f,$f3,$fc,$00,$03,$ff,$00,$00,$ff,$3f,$c0,$00,$3f
LFD76:
    .byte $f0,$00,$ff,$c3,$fc,$00,$3f,$c0,$ff,$00,$03,$ff,$00,$03,$fc,$0f
LFD86:
    .byte $f0,$00,$3f,$f0,$3f,$fc,$03,$fc,$00,$ff,$00,$3f,$c0,$03,$ff,$00
LFD96:
    .byte $0f,$f0,$03,$fc,$00,$3f,$f0,$ff,$c0,$03,$fc,$03,$ff,$ff,$ff,$f0
LFDA6:
    .byte $03,$ff,$00,$3f,$ff,$ff,$ff,$00,$3f,$f0,$3f,$f0,$03,$fc,$00,$7c
LFDB6:
    .byte $7f,$8f,$80,$7c,$7f,$8f,$80,$1f,$87,$f8,$7e,$07,$f0,$7f,$83,$f8
LFDC6:
    .byte $00,$ff,$c0,$7f,$80,$ff,$c0,$1f,$ff,$fc,$00,$7f,$80,$0f,$ff,$fe
LFDD6:
    .byte $1f,$fc,$00,$00,$7f,$80,$00,$0f,$fe,$0f,$ff,$ff,$ff,$fc,$03,$ff
LFDE6:
    .byte $00,$ff,$ff,$ff,$ff,$c0,$3f,$f0,$0f,$fc,$03,$fc,$3f,$f0,$00,$03
LFDF6:
    .byte $ff,$03,$ff,$03,$ff,$00,$00,$3f,$f0,$3f
LFE00:
    .byte $f0,$03,$ff,$03,$fc,$ff
LFE06:
    .byte $c0,$00,$00,$ff,$c3,$ff,$0f,$fc,$00,$00,$0f,$fc,$3f,$f0,$00,$ff
LFE16:
    .byte $c3,$fc,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$87,$f8,$7c,$07
LFE26:
    .byte $f0,$7f,$83,$f8,$00,$7f,$c0,$7f,$80,$ff,$80,$1f,$ff,$fe,$00,$7f
LFE36:
    .byte $80,$1f,$ff,$fe,$1f,$ff,$00,$00,$7f,$80,$00,$3f,$fe,$55,$55,$55
LFE46:
    .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
LFE56:
    .byte $55,$00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f0
LFE66:
    .byte $7f,$83,$f0,$00,$3f,$e0,$7f,$81,$ff,$00,$01,$ff,$fe,$00,$7f,$80
LFE76:
    .byte $1f,$ff,$e0,$1f,$ff,$c0,$00,$7f,$80,$00,$ff,$fe,$aa,$aa,$aa,$aa
LFE86:
    .byte $aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
LFE96:
    .byte $00,$7c,$7f,$8f,$80,$7c,$7f,$8f,$80,$0f,$c7,$f8,$fc,$03,$f8,$7f
LFEA6:
    .byte $87,$f0,$00,$1f,$e0,$7f,$81,$fe,$00,$00,$1f,$ff,$00,$7f,$80,$3f
LFEB6:
    .byte $fe,$00,$1f,$ff,$e0,$00,$7f,$80,$01,$ff,$fe,$55,$55,$55,$55,$55
LFEC6:
    .byte $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$09
LFED6:
    .byte $ca,$c9,$c6,$b4,$12,$08,$1b,$60,$58,$81,$4b,$86,$01,$d8,$bf,$d9
LFEE6:
    .byte $25,$a0,$7b,$dc,$32,$79,$84,$3b,$7c,$bc,$2f,$e2,$e2,$fa,$8d,$0a
LFEF6:
    .byte $00,$3b,$c5,$ec,$af,$2d,$8a,$cd,$06,$93
LFF00:
    .byte $6a,$a5,$14,$46,$77,$c4
LFF06:
    .byte $6a,$b2,$53,$36,$ef,$8c,$ce,$0c,$a2,$68,$71,$d3,$73,$e8,$f7,$6d
LFF16:
    .byte $06,$b5,$20,$ef,$23,$47,$0c,$51,$55,$c8,$fe,$f4,$58,$c4,$3f,$20
LFF26:
    .byte $a7,$67,$38,$b0,$76,$e2,$c4,$d8,$05,$63,$f8,$3c,$58,$3b,$2d,$22
LFF36:
    .byte $cc,$88,$b3,$71,$8f,$1d,$80,$0a,$87,$bd,$a1,$59,$23,$e9,$70,$e2
LFF46:
    .byte $d3,$ec,$46,$68,$80,$42,$39,$ea,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF56:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF66:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF76:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF86:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFF96:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFA6:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFB6:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFC6:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFD6:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
LFFE6:
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff



LFD3D = $FD3D
LFDB4 = $FDB4
LFDD5 = $FDD5
LFE18 = $FE18
LFE57 = $FE57
LFE84 = $FE84
LFE96 = $FE96
LFED5 = $FED5
LFF00 = $FF00

GccCopyright:
       .byte $47,$43,$43,$28,$43,$29 ; 'GCC(C)'
       .byte $31,$39,$38,$34,$2D,$F7 ; '1984-'

;=============================================================================
;
; VII. 6502 HARDWARE VECTORS
;
;=============================================================================

; These are the processor's hard-wired vectors at the top of memory.
; The BIOS uses these to direct the CPU on NMI, Reset, and IRQ events.
; When a cartridge is mapped in, its own vectors at these locations are used.

CartNMIVectorLo:
       .byte $00,$F0 ; System NMI vector points to NmiVector_Rom.
CartResetVectorLo:
       .word START   ; System RESET vector points to $F884.
CartIRQVectorLo:
       .byte $33,$F9 ; System IRQ vector.