7800 NTSC BIOS
From 8BitDev.org - Atari 7800 Development Wiki
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.