mirror of
https://github.com/cc65/cc65.git
synced 2024-08-18 10:29:06 +00:00
The configuration file and runtime (crt0.s) provided for the default NES ROM layout (2x16k PRG, 8k CHR) incorrectly added interrupts (IRQ1, IRQ2, TIMERIRQ) which are not supported by the NES hardware. For example, see the NESdev wiki, which makes no reference to these interrupts. https://wiki.nesdev.com/w/index.php/CPU_memory_map The VECTORS region was also incorrectly set to 0xFFF6, which would have left the 0xFFF4 normally unspecified. This did not result in any error, however, since cc65 simply placed ROMV directly after ROM0 regardless of start address. (This layout may be due to a copy-and-paste from the PC-Engine configuration, whose interrupt registers start at 0xFFF6, begins with the three interrupts listed above, followed by NMI and START, and does not end with a final IRQ interrupt.) Despite the absence of any actual error, since START is still placed at 0xFFFC, this patch removes the nonexistent interrupts and also correctly aligns the ROM0 and ROMV regions. It also has the (admittedly very minor) benefit of freeing up 6 additional bytes for ROM0.
184 lines
5.4 KiB
ArmAsm
184 lines
5.4 KiB
ArmAsm
;
|
|
; Startup code for cc65 (NES version)
|
|
;
|
|
; by Groepaz/Hitmen <groepaz@gmx.net>
|
|
; based on code by Ullrich von Bassewitz <uz@cc65.org>
|
|
;
|
|
|
|
.export _exit
|
|
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
|
.import initlib, donelib, callmain
|
|
.import push0, _main, zerobss, copydata
|
|
.import ppubuf_flush
|
|
|
|
; Linker generated symbols
|
|
.import __RAM_START__, __RAM_SIZE__
|
|
.import __SRAM_START__, __SRAM_SIZE__
|
|
.import __ROM0_START__, __ROM0_SIZE__
|
|
.import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__
|
|
.import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__
|
|
.import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__
|
|
|
|
.include "zeropage.inc"
|
|
.include "nes.inc"
|
|
|
|
|
|
; ------------------------------------------------------------------------
|
|
; 16 bytes INES header
|
|
|
|
.segment "HEADER"
|
|
|
|
; +--------+------+------------------------------------------+
|
|
; | Offset | Size | Content(s) |
|
|
; +--------+------+------------------------------------------+
|
|
; | 0 | 3 | 'NES' |
|
|
; | 3 | 1 | $1A |
|
|
; | 4 | 1 | 16K PRG-ROM page count |
|
|
; | 5 | 1 | 8K CHR-ROM page count |
|
|
; | 6 | 1 | ROM Control Byte #1 |
|
|
; | | | %####vTsM |
|
|
; | | | | ||||+- 0=Horizontal mirroring |
|
|
; | | | | |||| 1=Vertical mirroring |
|
|
; | | | | |||+-- 1=SRAM enabled |
|
|
; | | | | ||+--- 1=512-byte trainer present |
|
|
; | | | | |+---- 1=Four-screen mirroring |
|
|
; | | | | | |
|
|
; | | | +--+----- Mapper # (lower 4-bits) |
|
|
; | 7 | 1 | ROM Control Byte #2 |
|
|
; | | | %####0000 |
|
|
; | | | | | |
|
|
; | | | +--+----- Mapper # (upper 4-bits) |
|
|
; | 8-15 | 8 | $00 |
|
|
; | 16-.. | | Actual 16K PRG-ROM pages (in linear |
|
|
; | ... | | order). If a trainer exists, it precedes |
|
|
; | ... | | the first PRG-ROM page. |
|
|
; | ..-EOF | | CHR-ROM pages (in ascending order). |
|
|
; +--------+------+------------------------------------------+
|
|
|
|
.byte $4e,$45,$53,$1a ; "NES"^Z
|
|
.byte 2 ; ines prg - Specifies the number of 16k prg banks.
|
|
.byte 1 ; ines chr - Specifies the number of 8k chr banks.
|
|
.byte %00000011 ; ines mir - Specifies VRAM mirroring of the banks.
|
|
.byte %00000000 ; ines map - Specifies the NES mapper used.
|
|
.byte 0,0,0,0,0,0,0,0 ; 8 zeroes
|
|
|
|
|
|
; ------------------------------------------------------------------------
|
|
; Place the startup code in a special segment.
|
|
|
|
.segment "STARTUP"
|
|
|
|
start:
|
|
|
|
; Set up the CPU and System-IRQ.
|
|
|
|
sei
|
|
cld
|
|
ldx #0
|
|
stx VBLANK_FLAG
|
|
|
|
stx ringread
|
|
stx ringwrite
|
|
stx ringcount
|
|
|
|
txs
|
|
|
|
lda #$20
|
|
@l: sta ringbuff,x
|
|
sta ringbuff+$0100,x
|
|
sta ringbuff+$0200,x
|
|
inx
|
|
bne @l
|
|
|
|
; Clear the BSS data.
|
|
|
|
jsr zerobss
|
|
|
|
; Initialize the data.
|
|
jsr copydata
|
|
|
|
; Set up the stack.
|
|
|
|
lda #<(__SRAM_START__ + __SRAM_SIZE__)
|
|
ldx #>(__SRAM_START__ + __SRAM_SIZE__)
|
|
sta sp
|
|
stx sp+1 ; Set argument stack ptr
|
|
|
|
; Call the module constructors.
|
|
|
|
jsr initlib
|
|
|
|
; Push the command-line arguments; and, call main().
|
|
|
|
jsr callmain
|
|
|
|
; Call the module destructors. This is also the exit() entry.
|
|
|
|
_exit: jsr donelib ; Run module destructors
|
|
|
|
; Reset the NES.
|
|
|
|
jmp start
|
|
|
|
; ------------------------------------------------------------------------
|
|
; System V-Blank Interrupt
|
|
; Updates PPU Memory (buffered).
|
|
; Updates VBLANK_FLAG and tickcount.
|
|
; ------------------------------------------------------------------------
|
|
|
|
nmi: pha
|
|
tya
|
|
pha
|
|
txa
|
|
pha
|
|
|
|
lda #1
|
|
sta VBLANK_FLAG
|
|
|
|
inc tickcount
|
|
bne @s
|
|
inc tickcount+1
|
|
|
|
@s: jsr ppubuf_flush
|
|
|
|
; Reset the video counter.
|
|
lda #$20
|
|
sta PPU_VRAM_ADDR2
|
|
lda #$00
|
|
sta PPU_VRAM_ADDR2
|
|
|
|
; Reset scrolling.
|
|
sta PPU_VRAM_ADDR1
|
|
sta PPU_VRAM_ADDR1
|
|
|
|
pla
|
|
tax
|
|
pla
|
|
tay
|
|
pla
|
|
|
|
; Interrupt exit
|
|
|
|
irq:
|
|
rti
|
|
|
|
; ------------------------------------------------------------------------
|
|
; hardware vectors
|
|
; ------------------------------------------------------------------------
|
|
|
|
.segment "VECTORS"
|
|
|
|
.word nmi ; $fffa vblank nmi
|
|
.word start ; $fffc reset
|
|
.word irq ; $fffe irq / brk
|
|
|
|
; ------------------------------------------------------------------------
|
|
; character data
|
|
; ------------------------------------------------------------------------
|
|
|
|
.segment "CHARS"
|
|
|
|
.include "neschar.inc"
|
|
|
|
|