mirror of
https://github.com/iaddis/metalnes.git
synced 2024-06-01 19:08:14 -04:00
553 lines
8.7 KiB
NASM
553 lines
8.7 KiB
NASM
**** PRIOR DEFINITIONS ****
|
|
|
|
.include "maping.asm" ;This tells the ROM definition for the hardware
|
|
;.define PAL
|
|
|
|
.asctable
|
|
MAP "1" TO "9" = $10
|
|
MAP "A" TO "Z" = $20
|
|
MAP "=" = $1c
|
|
MAP "?" = $1e
|
|
MAP " " = $1f
|
|
MAP "/" = $3b
|
|
.enda
|
|
|
|
.ramsection "NMIVars" SLOT 0
|
|
;Thoose variables are used in the NMI routine
|
|
;Don't do calculations with them if a VBlank is pending
|
|
;set them after the calculation
|
|
SpriteDMAFlag db ;This tells if sprite DMA is ready in a frame
|
|
PalFlag db ;Check if palette uploaded is needed
|
|
NMIFlag db ;Check if a NMI is pending or not
|
|
FrameCounter db
|
|
NMITemp db
|
|
NMITemp2 db
|
|
NMITemp3 db
|
|
NMITemp4 db
|
|
ScrollV db
|
|
ScrollH db
|
|
M2001 db
|
|
M2000 db
|
|
|
|
.ends
|
|
|
|
.ramsection "Palette" SLOT 1
|
|
PaletteBuffer dsb $20
|
|
.ends
|
|
|
|
.ramsection "Main Vars" SLOT 0
|
|
Pointer .dw
|
|
PointerL db
|
|
PointerH db
|
|
Temp db
|
|
Temp2 db
|
|
Temp3 db
|
|
Temp4 db
|
|
EffectCtr db
|
|
DataCtr db
|
|
VRAMPointerH db
|
|
VRAMPointerL db
|
|
.ends
|
|
|
|
.ramsection "JoypadVar" SLOT 0
|
|
Pad1 db
|
|
Pad2 db
|
|
Pad1Locked db
|
|
Pad2Locked db
|
|
.ends
|
|
|
|
.ramsection "PlayerVars" SLOT 0
|
|
Delay db
|
|
.ends
|
|
.define DelayMax = $50
|
|
|
|
.struct SpriteDMA ;Structure for the Sprites
|
|
PosV db
|
|
TileNmr db
|
|
Palette db
|
|
PosH db
|
|
.endst
|
|
;$200-$2ff is reserved for sprite DMA
|
|
.enum $200
|
|
SpriteBuffer INSTANCEOF SpriteDMA 64
|
|
.ende
|
|
|
|
.ramsection "MMC1" SLOT 0
|
|
BankLatch1 db
|
|
BankLatch2 db
|
|
.ends
|
|
|
|
****** ROM aera begins here *******
|
|
|
|
.bank 0 SLOT 2
|
|
.orga $8000
|
|
.bank 1 SLOT 2
|
|
.orga $8000
|
|
.bank 3 SLOT 2
|
|
.orga $8000
|
|
.bank 4 SLOT 2
|
|
.orga $8000
|
|
.bank 5 SLOT 2
|
|
.orga $8000
|
|
.bank 6 SLOT 2
|
|
.orga $8000
|
|
|
|
.bank 7 SLOT 3
|
|
.orga $c000
|
|
|
|
***********************
|
|
*** Wait for a VBlank ***
|
|
***********************
|
|
|
|
.section "WaitNMI" FREE
|
|
WaitNMI
|
|
lda #$01
|
|
sta NMIFlag
|
|
- lda NMIFlag
|
|
bne -
|
|
rts
|
|
|
|
;Wait multiple NMIs in function of the value in X
|
|
WaitNMIs
|
|
- jsr WaitNMI
|
|
dex
|
|
bne -
|
|
rts
|
|
.ends
|
|
|
|
.section "NMIRoutine" FREE
|
|
|
|
NMI
|
|
pha
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
bit $2002
|
|
lda M2001
|
|
sta $2001
|
|
lda SpriteDMAFlag
|
|
beq _skipSpriteDMA ;Is the sprite buffer ready ?
|
|
lda #$00
|
|
sta SpriteDMAFlag ;Sprite buffer is read
|
|
sta $2003.w
|
|
lda #$02
|
|
sta $4014.w ;Do sprite DMA at $200
|
|
_skipSpriteDMA
|
|
lda PalFlag
|
|
beq + ;Do we need to update tiles ?
|
|
lda #$00
|
|
sta PalFlag
|
|
jsr WritePalette
|
|
|
|
+ lda #$22
|
|
sta $2006.w
|
|
lda #$1d
|
|
sta $2006.w
|
|
|
|
ldx #$00
|
|
lda Delay
|
|
- cmp #$0a ;Display units and tens of delay to NT
|
|
bcc +
|
|
sbc #$0a
|
|
inx
|
|
jmp -
|
|
+ tay
|
|
txa
|
|
clc
|
|
bne +
|
|
lda #$3f
|
|
bne ++
|
|
+ adc #$0f
|
|
++ sta $2007.w
|
|
tya
|
|
bne +
|
|
lda #$2e
|
|
bne ++
|
|
+ adc #$0f
|
|
++ sta $2007.w
|
|
|
|
lda ScrollH
|
|
sta $2005.w
|
|
lda ScrollV
|
|
sta $2005.w ;Upload scrolling regs
|
|
lda M2000
|
|
sta $2000.w
|
|
lda FrameCounter
|
|
eor #$01
|
|
sta FrameCounter
|
|
lda #$00 ;Clears the flag to stop waiting the frame
|
|
sta NMIFlag
|
|
pla ;Restore registers
|
|
tay
|
|
pla
|
|
tax
|
|
pla
|
|
IRQ rti
|
|
.ends
|
|
|
|
******************
|
|
* Graphics Stuff **
|
|
******************
|
|
|
|
;then clear all nametables and attribute tables with spaces ($60)
|
|
.section "ClearVRAM" FREE
|
|
ClearVRAM
|
|
lda M2000 ;Enable NMIs
|
|
ora #$80
|
|
sta M2000
|
|
sta $2000
|
|
jsr PaletteFadeOut ;Fade out palette (trick to save a routine to clear it)
|
|
lda #$00
|
|
sta $2000
|
|
lda #$06
|
|
sta M2001
|
|
sta $2001 ;Rendering off (so that nametables can be cleared)
|
|
jsr Clr2ndNamTbl ;Clear 2 active name tables
|
|
jmp ClrNamTbl
|
|
.ends
|
|
|
|
.section "PaletteFadeOut" FREE
|
|
PaletteFadeOut ;Fade out the palette
|
|
lda #$04
|
|
sta EffectCtr
|
|
_palfadeLoop
|
|
ldy #$1f
|
|
- lda PaletteBuffer.w,Y
|
|
sec
|
|
sbc #$10 ;Remove $10 from the color
|
|
bpl +
|
|
lda #$0f ;"Negative" colors forced to black
|
|
+ sta PaletteBuffer.w,Y
|
|
dey
|
|
bpl -
|
|
jsr WritePalette ;Palette will be uploaded at next NMI
|
|
ldx #$05
|
|
jsr WaitNMIs ;Wait 5 NMIs
|
|
dec EffectCtr
|
|
bne _palfadeLoop
|
|
rts
|
|
.ends
|
|
|
|
.section "ClrNamTbl" FREE
|
|
Clr2ndNamTbl
|
|
lda #$24 ;Clears the name tables
|
|
.db $cd
|
|
ClrNamTbl
|
|
lda #$20
|
|
SetNamAdress
|
|
sta $2006 ;Begin at $2000/$2400 (vertical mirroring)
|
|
lda #$00
|
|
sta $2006
|
|
lda #$0f
|
|
ldx #$1e ;Clears 30 rows with spaces ($60)
|
|
_screenloop
|
|
ldy #$20
|
|
_rowloop
|
|
sta $2007
|
|
dey
|
|
bne _rowloop
|
|
dex
|
|
bne _screenloop
|
|
lda #$00
|
|
ldx #$40 ;Clear attribute table with color $0
|
|
_attribloop
|
|
sta $2007
|
|
dex
|
|
bne _attribloop
|
|
rts
|
|
.ends
|
|
|
|
.section "ClrSprRam" FREE
|
|
ClrSprRam ;Clears the whole OAM buffer at $200
|
|
ldx #$00
|
|
beq _ClearRemainingSprites
|
|
|
|
FillBlankSprites ;This does just clears the unused sprites in $200-$2ff
|
|
lda SpriteDMAFlag ;For proper filling before sprite DMA
|
|
bne _endClrSprRam
|
|
_ClearRemainingSprites
|
|
lda #$f0
|
|
- sta SpriteBuffer.w,X
|
|
inx
|
|
inx
|
|
inx
|
|
inx
|
|
bne -
|
|
_endClrSprRam
|
|
inc SpriteDMAFlag
|
|
rts
|
|
.ends
|
|
|
|
;Turn the screen back on without scrolling glitches
|
|
;Set nametable 0 and scrolling to 0,0
|
|
;To be used only when the screen is disabled
|
|
.section "ResetScreen" FREE
|
|
ResetScreen
|
|
- bit $2002
|
|
bpl - ;Wait for VBlank and acknownledge it (no NMI)
|
|
lda #$88
|
|
sta M2000
|
|
sta $2000
|
|
lda #$00
|
|
sta ScrollV ;Enable NMI, enable endering, reset scrolling
|
|
sta ScrollH
|
|
lda M2001
|
|
ora #$1e
|
|
sta M2001 ;Enable rendering
|
|
sta $2001
|
|
rts
|
|
.ends
|
|
|
|
*****************
|
|
* Main programm *
|
|
*****************
|
|
|
|
.section "RESET" FREE
|
|
RESET ;The programm will start here
|
|
sei
|
|
ldx #$ff
|
|
txs ;Init stack pointer
|
|
inx
|
|
stx $2000.w
|
|
stx $2001.w ;Turn off rendering and interrupts
|
|
lda #$40
|
|
sta $4017.w ;Set sound clock, IRQ off
|
|
txa
|
|
sta PointerL
|
|
tay
|
|
ldx #$07
|
|
_initRAMloop
|
|
stx PointerH
|
|
- dey
|
|
sta [Pointer],Y ;Clear RAM
|
|
bne -
|
|
dex
|
|
bpl _initRAMloop
|
|
|
|
- bit $2002.w
|
|
bpl -
|
|
- bit $2002.w ;Wait for several VBlanks
|
|
bpl -
|
|
_MMC1
|
|
inc _MMC1.w
|
|
jsr ClearVRAM ;Clear the whole PPU
|
|
jsr LoadAlphabet ;Load character set
|
|
lda #$1e
|
|
jsr WriteR0 ;Initialise mapper
|
|
lda #$00
|
|
jsr WriteR1
|
|
lda #$00
|
|
jsr WriteR2 ;WRAM always enabled (for now)
|
|
lda #$06
|
|
jsr WriteR3
|
|
|
|
lda #$00
|
|
sta $2000.w
|
|
sta $2001.w
|
|
jsr PaletteInit
|
|
jsr PrintMsg
|
|
jsr ResetScreen ;This will make sprites use right pattern table (important !)
|
|
lda #$10
|
|
sta Delay ;Initial delay of $10
|
|
|
|
Loop
|
|
jsr ClrSprRam
|
|
lda #$85
|
|
sta $200
|
|
lda #$0f
|
|
sta $201
|
|
lda #$0f
|
|
sta $202
|
|
lda #$de
|
|
sta $203 ;Setup sprite zero hit
|
|
inc SpriteDMAFlag
|
|
jsr WaitNMI ;Wait a frame
|
|
|
|
jsr ReadLockJoypad
|
|
lda Pad1
|
|
lsr A ;Increase delay if right is pressed
|
|
bcc _noRight
|
|
lda Delay
|
|
cmp #DelayMax
|
|
bcs _noRight
|
|
inc Delay
|
|
|
|
_noRight
|
|
lda #$02
|
|
and Pad1
|
|
beq _noLeft
|
|
lda Delay ;Decrease delay if left is pressed
|
|
cmp #$01
|
|
beq _noLeft
|
|
dec Delay
|
|
|
|
_noLeft
|
|
lda #$04
|
|
and Pad1
|
|
beq _noDown
|
|
lda Delay ;Substract 10 to delay if down is pressed
|
|
sec
|
|
sbc #$0a
|
|
bcc +
|
|
bne ++
|
|
+ lda #$01
|
|
++ sta Delay
|
|
|
|
_noDown
|
|
lda #$08
|
|
and Pad1
|
|
beq _noUp ;Add 10 to delay if up is pressed
|
|
lda Delay
|
|
clc
|
|
adc #$0a
|
|
cmp #DelayMax
|
|
bcc +
|
|
lda #DelayMax
|
|
+ sta Delay
|
|
_noUp
|
|
jsr DisplayTestBar ;Display the grayscale test area
|
|
jmp Loop
|
|
.ends
|
|
|
|
|
|
.section "PaletteInit" FREE
|
|
PaletteInit
|
|
ldx #$00
|
|
- lda PalData.w,X
|
|
sta PaletteBuffer.w,X
|
|
inx
|
|
cpx #$20
|
|
bne -
|
|
inc PalFlag
|
|
rts
|
|
|
|
PalData
|
|
.db $01, $06, $26, $36
|
|
.db $01, $06, $27, $36
|
|
.db $01, $06, $0a, $0a
|
|
.db $01, $06, $0a, $0a
|
|
.db $01, $06, $0a, $0a
|
|
.db $01, $06, $0a, $0a
|
|
.db $01, $06, $0a, $0a
|
|
.db $01, $06, $0a, $0a
|
|
.ends
|
|
|
|
.section "WritePalette" FREE
|
|
WritePalette
|
|
lda #$3f
|
|
sta $2006.w
|
|
lda #$00
|
|
sta $2006.w
|
|
tay
|
|
_palLoop
|
|
lda PaletteBuffer.w,Y
|
|
sta $2007.w
|
|
iny
|
|
cpy #$20
|
|
bne _palLoop
|
|
rts
|
|
.ends
|
|
|
|
.section "LoadAlphabet" FREE
|
|
|
|
LoadAlphabet
|
|
ldy #$00
|
|
jsr + ;Load tileset into first pattern table
|
|
ldy #$10 ;Load identical tileset into second pattern table
|
|
+ sty $2006.w
|
|
ldy #$00
|
|
sty $2006.w
|
|
sty PointerL
|
|
ldx #$04
|
|
lda #>Alphabet
|
|
sta PointerH
|
|
- lda [Pointer],Y
|
|
sta $2007
|
|
iny
|
|
bne -
|
|
inc PointerH
|
|
dex
|
|
bne -
|
|
rts
|
|
.ends
|
|
|
|
.section "Alphabet" ALIGN $100
|
|
|
|
Alphabet
|
|
.incbin "alphabet.chr"
|
|
|
|
.ends
|
|
|
|
.section "PrintMsg" FREE
|
|
PrintMsg
|
|
lda #$21
|
|
sta $2006
|
|
lda #$a0
|
|
sta $2006
|
|
ldy #$00
|
|
- lda Msg.w,Y
|
|
sta $2007
|
|
iny
|
|
bpl -
|
|
rts
|
|
|
|
Msg
|
|
.asc " MMC1 WRAM DISABLE SCANLINE "
|
|
.asc " COUNTER TEST "
|
|
.asc " C 2O1O BREGALAD "
|
|
.asc " USE U/D L/R TO ADJUST DELAY= "
|
|
|
|
.ends
|
|
|
|
.section "DisplayTestBar" FREE
|
|
.define TestConst = $60~$ff ;Use the value oposite as the open bus value.
|
|
|
|
DisplayTestBar
|
|
lda #TestConst
|
|
sta $6000 ;Write a test constant in PRG RAM
|
|
|
|
lda #$10
|
|
jsr WriteR2 ;WRAM disabled when fecthing sprites, but enabled when fetchin BG (!)
|
|
;Now we can read $6000 as if we were reading PPU A12 directly...
|
|
;We can detect
|
|
- bit $2002
|
|
bvs -
|
|
- bit $2002 ;Wait for sprite zero hit
|
|
bvc -
|
|
|
|
lda #$1f
|
|
sta $2001 ;Turn on grayscale mode
|
|
ldx Delay
|
|
_delayLoop
|
|
- lda $6000
|
|
cmp #TestConst ;Wait until PRG RAM is disabled (emulators will freeze here)
|
|
beq -
|
|
|
|
ldy #$05
|
|
- dey ;Delay while sprites are being fetched
|
|
bne -
|
|
|
|
dex
|
|
bne _delayLoop ;Loop until the delay is expired
|
|
|
|
|
|
lda #$1e
|
|
sta $2001
|
|
lda #$00
|
|
jsr WriteR2 ;WRAM always enabled
|
|
sta $6000
|
|
rts
|
|
.ends
|
|
|
|
*************************
|
|
**** INTERUPTS VECTORS ****
|
|
*************************
|
|
|
|
.orga $fffa
|
|
.section "vectors" FORCE
|
|
.dw NMI
|
|
.dw RESET ;Thoose are the actual interupts vectors
|
|
.dw IRQ
|
|
.ends
|