diff --git a/snes/msu1/Makefile b/snes/msu1/Makefile new file mode 100644 index 0000000..6687d8b --- /dev/null +++ b/snes/msu1/Makefile @@ -0,0 +1,17 @@ +OBJS = header.ips reset.o65 main.o65 data.o65 const.o65 dma.o65 msu1.o65 # gfx.o65 # vars.o65 + +all: msu1vid.sfc + +msu1vid.sfc: $(OBJS) + sneslink -fsmc -o $@ $^ + +# Generic rule to create .o65 out from .a65 +%.o65: %.a65 + snescom -J -Wall -o $@ $< + +# Generic rule to create .ips out from .a65 +%.ips: %.a65 + snescom -I -J -Wall -o $@ $< + +clean: + rm -f *.ips *.o65 *~ msu1vid.sfc diff --git a/snes/msu1/const.a65 b/snes/msu1/const.a65 new file mode 100644 index 0000000..6f3f9bd --- /dev/null +++ b/snes/msu1/const.a65 @@ -0,0 +1,91 @@ +zero .word 0 +; hdma_blank: write to $2100 once (mode 0) +; force blanking up to line 40 and from line 184 +; (active display = 144 lines) +hdma_blank .byt 40 + .byt $8f + .byt 127 + .byt $0f + .byt 17 + .byt $0f + .byt 1 + .byt $8f + .byt 0 + +; h/vscroll: write to $210d twice, write to $210e twice (mode 3) +; adjust hscroll and vscroll to split one tilemap row into two display rows +; (tilemap memory saving measure) +hdma_scroll .byt 40 + .word 0 + .word 511 + .byt 16 + .word 0 + .word 152+255 + .byt 16 + .word 256 + .word 136+255 + .byt 16 + .word 0 + .word 136+255 + .byt 16 + .word 256 + .word 120+255 + .byt 16 + .word 0 + .word 120+255 + .byt 16 + .word 256 + .word 104+255 + .byt 16 + .word 0 + .word 104+255 + .byt 16 + .word 256 + .word 88+255 +; last row -> new tilemap + .byt 16 + .word 0 + .word 24+255 + .byt 0 + +; tilemap address switch: write to $2107 once (mode 0) +; last row of tilemap is located elsewhere due to size +hdma_tilemap .byt 40 + .byt $3c + .byt 127 + .byt $3c + .byt 1 + .byt $3c + .byt 1 + .byt $7c + .byt 0 + +; tilemap part 1 (goes to VRAM 7F00-7FFF) +tilemap .word $0000, $0000, $0002, $0004, $0006, $0008, $000a, $000c + .word $000e, $0020, $0022, $0024, $0026, $0028, $002a, $0000 + + .word $0000, $002c, $002e, $0040, $0042, $0044, $0046, $0048 + .word $004a, $004c, $004e, $0060, $0062, $0064, $0066, $0000 + + .word $0000, $0068, $006a, $006c, $006e, $0080, $0082, $0084 + .word $0086, $0088, $008a, $008c, $008e, $00a0, $00a2, $0000 + + .word $0000, $00a4, $00a6, $00a8, $00aa, $00ac, $00ae, $00c0 + .word $00c2, $00c4, $00c6, $00c8, $00ca, $00cc, $00ce, $0000 + + .word $0000, $00e0, $00e2, $00e4, $00e6, $00e8, $00ea, $00ec + .word $00ee, $0100, $0102, $0104, $0106, $0108, $010a, $0000 + + .word $0000, $010c, $010e, $0120, $0122, $0124, $0126, $0128 + .word $012a, $012c, $012e, $0140, $0142, $0144, $0146, $0000 + + .word $0000, $0148, $014a, $014c, $014e, $0160, $0162, $0164 + .word $0166, $0168, $016a, $016c, $016e, $0180, $0182, $0000 + + .word $0000, $0184, $0186, $0188, $018a, $018c, $018e, $01a0 + .word $01a2, $01a4, $01a6, $01a8, $01aa, $01ac, $01ae, $0000 + +; tilemap part 2 (goes to VRAM FF00-FFFF) +tilemap2 .word $0000, $01c0, $01c2, $01c4, $01c6, $01c8, $01ca, $01cc + .word $01ce, $01e0, $01e2, $01e4, $01e6, $01e8, $01ea, $0000 + diff --git a/snes/msu1/data.a65 b/snes/msu1/data.a65 new file mode 100644 index 0000000..a09516b --- /dev/null +++ b/snes/msu1/data.a65 @@ -0,0 +1,16 @@ +.data + +framecnt .word 0 +dispcnt .byt 0 + +charaddr .word 0 +charptr .byt 0 + +;----------parameters for dma---------- +dma_a_bank .byt 0 +dma_a_addr .word 0 +dma_b_reg .byt 0 +dma_len .word 0 +dma_mode .byt 0 + +isr_flag .byt 0 diff --git a/snes/msu1/dma.a65 b/snes/msu1/dma.a65 new file mode 100644 index 0000000..07b3028 --- /dev/null +++ b/snes/msu1/dma.a65 @@ -0,0 +1,58 @@ + +dma0: + rep #$10 : .xl + sep #$20 : .as + lda dma_mode + sta $4300 + lda dma_b_reg + sta $4301 + lda dma_a_bank + ldx dma_a_addr + stx $4302 + sta $4304 + ldx dma_len + stx $4305 + lda #$01 + sta $420b + rts + +setup_hdma: + sep #$20 : .as + rep #$10 : .xl + stz $420b + stz $420c + + lda #$00 ;A to B; direct; 1x single reg + sta $4310 ;ch. 1 for blanking + lda #$00 ;2100 = inidisp + sta $4311 + lda #^hdma_blank + ldy #!hdma_blank + sty $4312 + sta $4314 + + lda #$00 ;A to B; direct; 1x single reg + sta $4320 ;ch. 2 for tilemap switch + lda #$07 ;2107 = BG1 Tilemap Address + sta $4321 + lda #^hdma_tilemap + ldy #!hdma_tilemap + sty $4322 + sta $4324 + + lda #$03 ;A to B; direct; 2x 2x single reg + sta $4330 ;ch. 3 for scroll + lda #$0d ;210d = BG1HOFS + sta $4331 + lda #^hdma_scroll + ldy #!hdma_scroll + sty $4332 + sta $4334 + + ldx #184 ;Set IRQ trigger to line 184 + stx $4209 ; + lda #$a1 ;NMI + V-Count IRQ + Auto Joypad Read + sta $4200 + rts + + diff --git a/snes/msu1/dma.i65 b/snes/msu1/dma.i65 new file mode 100644 index 0000000..f5e6040 --- /dev/null +++ b/snes/msu1/dma.i65 @@ -0,0 +1,13 @@ +#define DMA0(mode, len, a_bank, a_addr, b_reg)\ + lda mode \ +: sta dma_mode \ +: ldx a_addr \ +: lda a_bank \ +: stx dma_a_addr \ +: sta dma_a_bank \ +: ldx len \ +: stx dma_len \ +: lda b_reg \ +: sta dma_b_reg \ +: jsr dma0 + diff --git a/snes/msu1/header.a65 b/snes/msu1/header.a65 new file mode 100644 index 0000000..b04b8f6 --- /dev/null +++ b/snes/msu1/header.a65 @@ -0,0 +1,74 @@ +; This file is part of the snescom-asm demo - a demo of how to build a SNES program. +; See http://bisqwit.iki.fi/source/snescom.html for details. + +; Begin assembling to this address. +*= $C0FF00 + +RESET: + sei: clc: xce + jmp @GAME_MAIN + +NMI_16bit: + php + rep #$30 : .al : .xl + pha: phx: phy: phd: phb + jsl @NMI_ROUTINE + rep #$30 : .al : .xl +int_exit: + plb: pld: ply: plx: pla + plp + rti + +IRQ_16bit: + php + rep #$30 : .al : .xl + pha: phx: phy: phd: phb + jsl @IRQ_ROUTINE + rep #$30 : .al : .xl + bra int_exit + +;error vectors +ABT_8bit: ABT_16bit: +BRK_8bit: BRK_16bit: +COP_8bit: COP_16bit: +IRQ_8bit: +NMI_8bit: + - wai: lda $ABCDEF : bra - + +*= $C0FFB0 + ; Zero the area from $FFB0 - $FFFF + ; to ensure that the linker won't get clever + ; and fill it with small pieces of code. + .word 0,0,0,0, 0,0,0,0 + .word 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .word 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + +*= $C0FFB0 + +.byt "MR" ;2 bytes - company id +.byt "MSU1" ;4 bytes - rom id + +*= $C0FFC0 +.byt "MSU1 VIDEO PLAYER " + ;123456789012345678901; - max 21 chars + +*= $C0FFD5 .byt $31 ;rom speed +*= $C0FFD6 .byt $02 ;rom type +*= $C0FFD7 .byt $06 ;rom size 64 kByte +*= $C0FFD8 .byt $03 ;sram size 8 kBit +*= $C0FFD9 .byt $09 ;rom region 4 = Finland +*= $C0FFDA .byt $33 ;company id flag + +*= $C0FFDC .word 0,0 ;checksums + +*= $C0FFE4 .word COP_16bit +*= $C0FFE6 .word BRK_16bit +*= $C0FFE8 .word ABT_16bit +*= $C0FFEA .word NMI_16bit +*= $C0FFEE .word IRQ_16bit +*= $C0FFF4 .word COP_8bit +*= $C0FFF8 .word ABT_8bit +*= $C0FFFA .word NMI_8bit +*= $C0FFFC .word RESET +*= $C0FFFE .word BRK_8bit +*= $C0FFFE .word IRQ_8bit diff --git a/snes/msu1/main.a65 b/snes/msu1/main.a65 new file mode 100644 index 0000000..d48da89 --- /dev/null +++ b/snes/msu1/main.a65 @@ -0,0 +1,227 @@ +#include "dma.i65" + +GAME_MAIN: + sep #$20 : .as + stz $4200 ; inhibit IRQs + jsr killdma + jsr waitblank + jsr snes_init + lda #$01 + sta $420d ; fast cpu + jsr setup_gfx + jsr colortest + jsr setup_hdma + jsr screen_init + sep #$20 : .as + jsr msu1init + cli + jsr msu1loop +- wai ; idle loop + bra - + +killdma: + stz $420b + stz $420c + stz $4310 + stz $4311 + stz $4312 + stz $4313 + stz $4314 + stz $4320 + stz $4321 + stz $4322 + stz $4323 + stz $4324 + stz $4330 + stz $4331 + stz $4332 + stz $4333 + stz $4334 + stz $4340 + stz $4341 + stz $4342 + stz $4343 + stz $4344 + stz $4350 + stz $4351 + stz $4352 + stz $4353 + stz $4354 + stz $4360 + stz $4361 + stz $4362 + stz $4363 + stz $4364 + rts + + + + +waitblank: +- lda $4212 + and #$80 + bne - +- lda $4212 + and #$80 + beq - + rts + +colortest: + sep #$20 : .as + rep #$10 : .xl + stz $2130 + rts + +setup_gfx: + sep #$20 : .as + rep #$10 : .xl + stz $4200 + stz $420b + stz $420c + +;clear VRAM + ldx #$0000 + stx $2116 + DMA0(#$09, #$0000, #^zero, #!zero, #$18) + +;copy low tilemap + ldx #$3F80 ; == 8-bit address $7F00 + stx $2116 + DMA0(#$01, #$100, #^tilemap, #!tilemap, #$18) + +;copy high tilemap + ldx #$7F80 ; == 8-bit address $FF00 + stx $2116 + DMA0(#$01, #$20, #^tilemap2, #!tilemap2, #$18) + +;clear OAM tables + ldx #$0000 + stx $2102 + DMA0(#$08, #544, #^zero, #!zero, #$04) + + rts + +screen_init: + sep #$20 : .as ;8-bit accumulator + rep #$10 : .xl ;16-bit index + lda #$13 ;mode 3, 16x16 + sta $2105 + lda #$3C ;Tilemap addr 0x7800, 32x32 + sta $2107 ;for BG1 + lda #$00 ;chr base addr: + sta $210b ;BG1=0x0000, BG2=0x0000 + lda #$01 ;enable BG1 + sta $212c ;BG Main + lda #$01 ;enable none + sta $212d ;BG Sub + lda #$20 ;Window 1 for color + sta $2125 ;Color window +; lda #$02 ;Window 1 for BG1 +; sta $2123 + lda #$10 ;cut off 16 pixels left + sta $2126 + lda #$ef ;cut off 16 pixels right + sta $2127 + lda #$40 ;enable clipping outside window + sta $2130 +; lda #$01 ;enable clipping for BG1 +; sta $212e + stz $2121 ;reset CGRAM ptr + lda #$0f + sta $2100 ;screen on, full brightness + rts + +snes_init: + sep #$20 : .as ;8-bit accumulator + rep #$10 : .xl ;16-bit index + stz $4200 ; + lda #$ff + sta $4201 ; + stz $4202 ; + stz $4203 ; + stz $4204 ; + stz $4205 ; + stz $4206 ; + stz $4207 ; + stz $4208 ; + stz $4209 ; + stz $420a ; + stz $420b ; + stz $420c ; + lda #$01 + sta $420d ; FAAAAAST + lda #$8f + sta $2100 ;INIDISP: force blank + stz $2101 ; + stz $2102 ; + stz $2103 ; +; stz $2104 ; (OAM Data?!) +; stz $2104 ; (OAM Data?!) + stz $2105 ; + stz $2106 ; + stz $2107 ; + stz $2108 ; + stz $2109 ; + stz $210a ; + stz $210b ; + stz $210c ; + stz $210d ; + stz $210d ; + stz $210e ; + stz $210e ; + stz $210f ; + stz $210f ; + stz $2110 ; + stz $2110 ; + stz $2111 ; + stz $2111 ; + stz $2112 ; + stz $2112 ; + stz $2113 ; + stz $2113 ; + stz $2114 ; + stz $2114 ; + lda #$80 ;VRAM addr increment after high byte + sta $2115 ; + stz $2116 ; + stz $2117 ; +; stz $2118 ;(VRAM Data?!) +; stz $2119 ;(VRAM Data?!) + stz $211a ; + stz $211b ; + lda #$01 + sta $211b ; + stz $211c ; + stz $211c ; + stz $211d ; + stz $211d ; + stz $211e ; + sta $211e ; + stz $211f ; + stz $211f ; + stz $2120 ; + stz $2120 ; + stz $2121 ; +; stz $2122 ; (CG Data?!) +; stz $2122 ; (CG Data?!) + stz $2123 ; + stz $2124 ; + stz $2125 ; + stz $2126 ; + stz $2127 ; + stz $2128 ; + stz $2129 ; + stz $212a ; + stz $212b ; + stz $212c ; + stz $212d ; + stz $212e ; + stz $212f ; + stz $2130 ; + stz $2131 ; + lda #$e0 ;clear fixed color + sta $2132 ; + stz $2133 ; + + rts + diff --git a/snes/msu1/msu1.a65 b/snes/msu1/msu1.a65 new file mode 100644 index 0000000..b3bac82 --- /dev/null +++ b/snes/msu1/msu1.a65 @@ -0,0 +1,73 @@ +#include "dma.i65" +#include "msu1.i65" + +msu1init: + sep #$20 : .as + rep #$10 : .xl + ldx #$0000 + stx MSU_SEEK_OFFSET + stx MSU_SEEK_BANK +- bit MSU_STATUS + bmi - + ldx #$0000 + stx $2116 + + lda #$04 + sta charptr + sta $210b + + ; prepare DMA + ldx #$2001 + stx $4302 + stz $4304 + + rts + +msu1loop: + sep #$20 : .as + rep #$10 : .xl + stz dispcnt +msu1loop2 + lda isr_flag + beq msu1loop2 + stz isr_flag + ;load half picture + lda #$18 + sta $4301 + lda #$09 + sta $4300 + ldx #16256 + stx $4305 + lda #$01 + sta $420b + inc dispcnt + lda dispcnt + cmp #$02 + bne msu1loop2 + + stz dispcnt + ;load palette + stz $2121 + lda #$22 + sta $4301 + lda #$08 + sta $4300 + ldx #512 + stx $4305 + lda #$01 + sta $420b + lda charptr + bne ptr2 +ptr1 + lda #$04 + sta $210b + sta charptr + ldx #$0000 + stx $2116 + bra msu1loop2 +ptr2 + stz $210b + stz charptr + ldx #$4000 + stx $2116 + bra msu1loop2 diff --git a/snes/msu1/msu1.i65 b/snes/msu1/msu1.i65 new file mode 100644 index 0000000..6163c8d --- /dev/null +++ b/snes/msu1/msu1.i65 @@ -0,0 +1,11 @@ + +#define MSU_STATUS $2000 +#define MSU_READ $2001 +#define MSU_ID $2002 + +#define MSU_SEEK_OFFSET $2000 +#define MSU_SEEK_BANK $2002 +#define MSU_TRACK $2004 +#define MSU_VOLUME $2006 +#define MSU_CONTROL $2007 + diff --git a/snes/msu1/reset.a65 b/snes/msu1/reset.a65 new file mode 100644 index 0000000..dd93eeb --- /dev/null +++ b/snes/msu1/reset.a65 @@ -0,0 +1,26 @@ +; This file is part of the snescom-asm demo - a demo of how to build a SNES program. +; See http://bisqwit.iki.fi/source/snescom.html for details. + +#include "dma.i65" + +#define TILE_ADDR_REG_VAL(addr, scsize) \ + (((addr & $FC00) >> 8) + scsize) +#define BMAP_ADDR_REG_VAL(addr, addr2) \ + (((addr & $F000) >> 12) | (((addr2 & $F000) >> 12) << 4)) + +; NMI - called on VBlank +NMI_ROUTINE: + sep #$20 : .as + lda $4210 ; ack interrupt + lda #$0e + sta $420c ; enable HDMA ch. 1-3 + rtl + +; IRQ - called when triggered +IRQ_ROUTINE: + sep #$20 : .as + lda #$01 + sta isr_flag + lda $4211 ;Acknowledge irq + rtl +