Real SNES hardware help?

Programming the SNES - covers hardware via 6502 emulation mode (65816 coming next year!)
Post Reply
Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Real SNES hardware help?

Post by Domeshtan » Mon Jul 25, 2022 1:07 am

I hope you can help me because I'm staring to loose my mind trying so many different ways. I have both of the books and I wanted to learn SNES assembly programing. I know it isn't ment to be "in depth" to cover everything. I've already wrote about a dozen games total for Atari 2600, NES and one Colecovision so assembly isn't totally new to me.
I managed to get the examples to assemble and link into a rom image. Only thing I changed was the location so I wouldn't have to type out extra stuff. So my lines would be....
wla-65816.exe -i -o cart.o HellolWorld.asm
wlalink -i -b cart.txt cart.sfc

I can get the stuff to run on an emulator but not real hardware. It's driving me nuts. Snes9x tells me things like the rom is corrupt, bad checksum, etc. It does run but it seemed something was off...

I bought some circuit boards from Muramasa for making my own SNES cartridges. I have test boards made for LOROM games 1 Meg and under and others for LOROM or HIROM games (and probably others like ExHi, etc) up to 2 Megabytes. I am using a GQ 4x4 (and also an adp-054 adaptor for larger eproms.) Eproms I am using are 27C040 (512K chip) and 27C160 (2 Megabyte chip). I've tested a few LoROM and HIROM homebrew games on them and the boards work fine on a real Super Nintendo. (No rewiring either... Yay!) I have 12F629s programer as SuperCICs to get around the lock-out chip problem. (Reverse engineered multi region lock out chip clone.) I've tested them with Classic Kong Complete, Jet Pilot Rising and some other multi-player simple fighting game. Everything works fine so I know it isn't a hardware issue or writing the files wrong.

With all of the tutorials they come up as a blank screen on a real system. After much looking around reading and watching videos I think I have found some issues...

The file always came out as 32K actual size. After some reading I changed the linker command line from -b to -r to make a proper sized rom image...
wlalink -i -r cart.txt cart.sfc

File size was now right. Next thing I noticed...
SLOTSIZE $020000

BANKSIZE $020000
BANKS 1
It does make a file 128K in size but from what I understand if a game is LOROM it uses 32K banks. HIROM uses 64K banks. All the other examples I found out there have multiple banks using these sizes.

Another thing... No header type information defined. SLOWROM/FASTROM, LoROM, HIROM, title, country, rom size, etc. I understand this part can be a bit optional.

Next I think this may be part of the problem... Defining the vectors. A video made it sound like the vectors are pretty important to make a game run. I see something at the end like...
.ORG $FFFA
.DW $0000 ;NMI
.DW $8000 ;Reset vector
.DW $0000 ;IRQ/Break
These are the only examples I've seen done that way. Others I see things defining
.SNESNATIVEVECTOR
COP EmptyHandler
BRK EmptyHandler
ABORT EmptyHandler
NMI VBLANK
UNUSED $0000
IRQ EmptyHandler
.ENDNATIVEVECTOR

and then something simular...

.SNESEMUVECTOR
COP EmptyHandler
UNUSED $0000
ABORT EmptyHandler
NMI EmptyHandler
RESET Boot
IRQBRK EmptyHandler
.ENDEMUVECTOR

So I take it that written this way it would do slightly different things depending if you are in 65816 Native mode or the 6502 emulated mode?
All I know is every other program looks different.

The another thing that I am sure is playing a part is having things in memory zeroed out and set on a real system. Snes_Init SEMIFREE section I saw in some files. It's long with quite a bit to zero out and set. I know emulators and stuff might have things zeroed out and set already. My NES games ran fine on emulators and even worked fine on my Everdrive N8 I used for testing, but once I put my programs on Eproms cannibalizing some Ice Hockey cartridges I got square patches of wrong colors all over the screen and gibberish at the top and bottom of the screen because my atribute table wasn't zeroed out and the entire screen was not filled with empty spaces for unused areas.

So basically I have tried to "re-word" and rearrange things every way I could think of to get things working on a real SNES. I tried parts of other programs, I've tried LOROM headers, HIROM headers.... I don't want to change out of WLADX at this point after all this. Other examples ... No use ca65, no use 64tass, etc. Everything seems scattered all over and I can't get ANYTHING to assemble and work on real hardware. Like I said, other homebrew games run fine on it so it's not the circuit boards or writing to the Eproms.
Basically can someone PLEASE make a version of the tutorial examples that runs on a real machine using WLADX? Preferably all in one assembly file not split up for the header or Snes_Init info to zero things out properly.
I just want some kind of "skeleton" program where I can just add and tweak stuff with a ready made routine to get someone up and running. I already played with the text, colors, changing graphics, changing keypad stuff around experimenting but I'm at my wits end trying to get it to run on a real machine. Only other thing I can think of is if it's bouncing back and forth the wrong way expecting 8 or 16 bit values swapped around. Thanks so much for your time!

Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Re: Real SNES hardware help?

Post by Domeshtan » Mon Jul 25, 2022 1:25 am

Test boards I am using.
Test boards I am using.
TestBoardsSNES.jpg (113.05 KiB) Viewed 1266 times

Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Re: Real SNES hardware help?

Post by Domeshtan » Sat Aug 27, 2022 4:01 pm

After a couple months and countless tries I FINALLY got the ChibiAkumas SNES examples to work on a real Super Nintendo.
The examples worked on emulators but to run on a real system it seemed a few more things had to be done. I set up the header for a 256K LoROM format using 8 32K banks. Again, I'm new to a lot of the Super Nintendo stuff but from what I saw in other places LoROM games use 32K banks and HiROM games use 64K banks. Another thing seemed the wlalink command line was using a -b option to build the ROM image. This drove me nuts... it was allways coming out as 32K. I used the option -r instead and the ROM image sizes were coming out the proper size. The major issue I think was having to reset and initialize a bunch of stuff. Well, I changed the code for the first and third examples, so here they are. (The third example was pretty much like the second but with reading the pad this time). Is the code 100% correct? I don't know, but I have tested it on a real SNES. Video to follow... and show how to do it with a GQ 4x4.

Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Re: Real SNES hardware help?

Post by Domeshtan » Sat Aug 27, 2022 4:04 pm

;Hello World SNES example that works on real SNES hardware
;==LoRom==
.MEMORYMAP
SLOTSIZE $8000
DEFAULTSLOT 0
SLOT 0 $8000
.ENDME

.ROMBANKSIZE $8000
.ROMBANKS 8

.SNESHEADER
ID "SNES"

NAME "SNES Program Name "
; "123456789012345678901"

SLOWROM
LOROM

CARTRIDGETYPE $00
ROMSIZE $08
SRAMSIZE $00
COUNTRY $01
LICENSEECODE $00
VERSION $00
.ENDSNES

.SNESNATIVEVECTOR
COP EmptyHandler
BRK EmptyHandler
ABORT EmptyHandler
NMI EmptyHandler
IRQ EmptyHandler
.ENDNATIVEVECTOR

.SNESEMUVECTOR
COP EmptyHandler
ABORT EmptyHandler
NMI EmptyHandler
RESET Start
IRQBRK EmptyHandler
.ENDEMUVECTOR

.BANK 0 SLOT 0
;--------------------- My tweak here ------------------------------------
.EQU z_HL $20 ;Zero page variables for our 24 bit addresses
.EQU z_L $20
.EQU z_H $21
.EQU z_HLU $22

.EQU CursorX $40 ;X position of next character draw
.EQU CursorY $41 ;Y position of next character draw
;------------------------------------------------------------------------

.ORG 0
.SECTION "EmptyVectors" SEMIFREE

EmptyHandler:
rti
.ENDS

.EMPTYFILL $00
;---------------------------------------- END ------------------------------


;------------------- My tweaking again with Hello World program ------------

;++++++++++++++++++++++++++++++++++++++++++++++++
Start: ; ME ADDING IN HERE
;.MACRO Snes_Init
sei ; Disabled interrupts
clc ; clear carry to switch to native mode
xce ; Xchange carry & emulation bit. native mode
rep #$18 ; Binary mode (decimal mode off), X/Y 16 bit

.INDEX 16 ;XY 16 bit ME ADDING

ldx #$1FFF ; set stack to $1FFF
txs
;jsr Init
;.ENDM
.bank 0
.section "Snes_Init" SEMIFREE
Init:
sep #$30 ; X,Y,A are 8 bit numbers

.INDEX 8 ;XY 8 bit ME ADDING

lda #$8F ; screen off, full brightness
sta $2100 ;(INIDISP) brightness + screen enable register
stz $2101 ;(OBSEL) Sprite register (size + address in VRAM)
stz $2102 ;(OAMADDL) Sprite registers (address of sprite memory [OAM])
stz $2103 ;(OAMADDH) "" ""
stz $2105 ;(BGMODE) Mode 0, = Graphic mode register
stz $2106 ;(MOSAIC) noplanes, no mosaic, = Mosaic register
stz $2107 ;(BG1SC) Plane 0 map VRAM location
stz $2108 ;(BG2SC) Plane 1 map VRAM location
stz $2109 ;(BG3S3) Plane 2 map VRAM location
stz $210A ;(BG3S3)??? Plane 3 map VRAM location
stz $210B ;(BG12NBA) Plane 0+1 Tile data location
stz $210C ;(BG34NBA) Plane 2+3 Tile data location
stz $210D ;(BG1HOFS) Plane 0 scroll x (first 8 bits)
stz $210D ;(BG1HOFS) Plane 0 scroll x (last 3 bits) #$0 - #$07ff
lda #$FF ; The top pixel drawn on the screen isn't the top one in the tilemap, it's the one above that.
sta $210E ;(BG1VOFS) Plane 0 scroll y (first 8 bits)
sta $2110 ;(BG2VOFS) Plane 1 scroll y (first 8 bits)
sta $2112 ;(HVBJOY) Plane 2 scroll y (first 8 bits)
sta $2114 ;(BG4VOFS) Plane 3 scroll y (first 8 bits)
lda #$07 ; Since this could get quite annoying, it's better to edit the scrolling registers to fix this.
sta $210E ;(BG1VOFS) Plane 0 scroll y (last 3 bits) #$0 - #$07ff
sta $2110 ;(BG2VOFS) Plane 1 scroll y (last 3 bits) #$0 - #$07ff
sta $2112 ;(HVBJOY) Plane 2 scroll y (last 3 bits) #$0 - #$07ff
sta $2114 ;(BG4VOFS) Plane 3 scroll y (last 3 bits) #$0 - #$07ff
stz $210F ;(BG2HOFS) Plane 1 scroll x (first 8 bits)
stz $210F ;(BG2HOFS) Plane 1 scroll x (last 3 bits) #$0 - #$07ff
stz $2111 ;(BG3HOFS) Plane 2 scroll x (first 8 bits)
stz $2111 ;(BG3HOFS) Plane 2 scroll x (last 3 bits) #$0 - #$07ff
stz $2113 ;(BG4HOFS) Plane 3 scroll x (first 8 bits)
stz $2113 ;(BG4HOFS) Plane 3 scroll x (last 3 bits) #$0 - #$07ff
lda #$80 ; increase VRAM address after writing to $2119
sta $2115 ;(VMAIN) VRAM address increment register
stz $2116 ;(VMADDL) VRAM address low
stz $2117 ;(VMADDH) VRAM address high
stz $211A ;(M7SEL) Initial Mode 7 setting register
stz $211B ;(M7A) Mode 7 matrix parameter A register (low)
lda #$01
sta $211B ;(M7A) Mode 7 matrix parameter A register (high)
stz $211C ;(M7B) Mode 7 matrix parameter B register (low)
stz $211C ;(M7B) Mode 7 matrix parameter B register (high)
stz $211D ;(M7C) Mode 7 matrix parameter C register (low)
stz $211D ;(M7C) Mode 7 matrix parameter C register (high)
stz $211E ;(M7D) Mode 7 matrix parameter D register (low)
sta $211E ;(M7D) Mode 7 matrix parameter D register (high)
stz $211F ;(M7X) Mode 7 center position X register (low)
stz $211F ;(M7X) Mode 7 center position X register (high)
stz $2120 ;(M7Y) Mode 7 center position Y register (low)
stz $2120 ;(M7Y) Mode 7 center position Y register (high)
stz $2121 ;(CGADD) Color number register ($0-ff)
stz $2123 ;(W12SEL) BG1 & BG2 Window mask setting register
stz $2124 ;(W34SEL) BG3 & BG4 Window mask setting register
stz $2125 ;(WOBJSEL) OBJ & Color Window mask setting register
stz $2126 ;(WH0) Window 1 left position register
stz $2127 ;(WH1) Window 2 left position register
stz $2128 ;(WH2) Window 3 left position register
stz $2129 ;(WH3) Window 4 left position register
stz $212A ;(WBGLOG) BG1, BG2, BG3, BG4 Window Logic register
stz $212B ;(WOBJLOG) OBJ, Color Window Logic Register (or,and,xor,xnor)
sta $212C ;(TM) Main Screen designation (planes, sprites enable)
stz $212D ;(TS) Sub Screen designation
stz $212E ;(TMW) Window mask for Main Screen
stz $212F ;(TSW) Window mask for Sub Screen
lda #$30
sta $2130 ;(CGWSEL) Color addition & screen addition init setting
stz $2131 ;(CGADSUB) Add/Sub sub designation for screen, sprite, color
lda #$E0
sta $2132 ;(COLDATA) color data for addition/subtraction
stz $2133 ;(SETINI) Screen setting (interlace x,y/enable SFX data)
stz $4200 ;(NMITIMEN) Enable V-blank, interrupt, Joypad register
lda #$FF
sta $4201 ;(WRIO) Programmable I/O port
stz $4202 ;(WRMPYA) Multiplicand A
stz $4203 ;(WRMPYB) Multiplier B
stz $4204 ;(WRDIVL) Multiplier C
stz $4205 ;(WRVIDH) Multiplicand C
stz $4206 ;(WRDIVB) Divisor B
stz $4207 ;(HTIMEL) Horizontal Count Timer
stz $4208 ;(HTIMEH) Horizontal Count Timer MSB (most significant bit)
stz $4209 ;(VTIMEL) Vertical Count Timer
stz $420A ;(VTIMEH) Vertical Count Timer MSB
stz $420B ;(MDMAEN) General DMA enable (bits 0-7)
stz $420C ;(HDMAEN) Horizontal DMA (HDMA) enable (bits 0-7)
stz $420D ;(MEMSEL) Access cycle designation (slow/fast rom)
cli ; Enable interrupts
;rts
.ends


;++++++++++++++++++++++++++++++++++++++++++++++++
MyProg:
;===================================== $8000 =======================
;======================Assembled with the -b option... not -r ======
SEI ;Stop interrupts
clc
xce ;16 bit mode (65816 Native)

; --MX---- M=Accumulator X=XY
REP #%00010000 ;16 bit XY
.INDEX 16 ;XY 16 bit

;Set up the screen
;aaaabbbb - aaa=base addr for BG2 bbb=base addr for BG1
lda #%00010001
sta $210B ;BG1 & BG2 VRAM location register [BG12NBA]

;xxxxxxss - xxx=address ss=SC size 00=32x32 01=64x32 10=32x64 11=64x64
stz $2107 ;BG1SC - BG1 Tilemap VRAM location (%00000000)

;x000bbbb - x=screen disable (1=disable) bbbb=brightness (15=max)
lda #%10001111 ;INIDISP - Screen display register
sta $2100

;i000abcd - i=0 inc on $2118/2139 i=1 $2119/213A abcd=move size
stz $2115 ;VMAIN - Video port control
;(Inc on write to $2118)

; abcdefff - abcd=tile sizes e=pri fff=mode def
lda #%00001001
sta $2105 ;BGMODE - Screen mode register

;Set up Palette - Color 0
stz $2121 ;CGADD -Palette selection
stz $2122 ;CGDATA - Color data register gggrrrrr
stz $2122 ;CGDATA - Color data register ?bbbbbgg

lda #3 ;Color 3
sta $2121 ;CGADD - Palette selection
lda #%11111111
sta $2122 ;CGDATA - Color data register gggrrrrr
lda #%00000111
sta $2122 ;CGDATA - Color data register ?bbbbbgg

;Transfer Patterns (1 bpp font)
lda #<BitmapFont
sta z_L ;L byte of address (24 bit UHL)
lda #>BitmapFont
sta z_H ;H byte of address (24 bit UHL)
lda #BitmapFont>>16
sta z_HLU ;U byte of address (24 bit UHL)

ldx #$1000 ;Vram Dest - $1000 (Patterns)
stx $2116 ;2116/7 -Video port address (VMADDL/H)

ldy #0
fontchar_loop:
ldx #8 ;8 lines - Bitplanes 0/1
fontchar_NextWord:
lda [z_HL],y ;We write 1 word/2 bytes to each VRAM address
sta $2119 ;1st byte H
sta $2118 ;2nd byte L (and Inc VRAM address)
iny
dex
bne fontchar_NextWord

ldx #8 ;8 lines - Bitplanes 2/3
fontchar_NextZero:
stz $2119 ;1st byte H
stz $2118 ;2nd byte L (and Inc VRAM address)
dex
bne fontchar_NextZero

cpy #27*8 ;All Characters done?
bne fontchar_loop

;Set Scroll position
stz $210D ;BG1HOFS BG1 horizontal scroll
stz $210D ;BG1HOFS
lda #-1
sta $210E ;BG1VOFS BG1 vertical scroll
stz $210E ;BG1VOFS

stz $2116 ;MemL - Video port address
stz $2117 ;MemH - Video port address

;Clear Tilemap
ldx #$400 ;Size of tilemap
ClearTilemap:
stz $2119 ;1st byte H
stz $2118 ;2nd byte L (and Inc VRAM address)
dex
bne ClearTilemap

;Turn on screen
; ---S4321 - S=sprites 4-1=enable Bgx
lda #%00000001 ;Turn on BG1
sta $212C ;Main screen designation [TM]

; x000bbbb - x=screen disable (1=disable) bbbb=brightness
lda #%00001111 ;Screen ON
sta $2100 ;INIDISP - Screen display register

;Start our test program
stz CursorX ;Zero Text Drawing Position
stz CursorY

lda #<txtHelloWorld
sta z_L ;L byte of address (24 bit UHL)
lda #>txtHelloWorld
sta z_H ;H byte of address (24 bit UHL)
lda #txtHelloWorld>>16
sta z_HLU ;U byte of address (24 bit UHL)



jsr PrintString ;Show z_HL string to screen
;================================ $80A1 =======================

infloop:
jmp infloop ;Halt program
;================================ $80A4 =======================

;=========================== $80A7 Unidentified ===============


txtHelloWorld: ;255 Terminated string
.DB "Hello WorlD",255

NewLine: ;Move down a line
stz CursorX ;Zero X pos
inc CursorY ;Move down one line
rts

PrintString:
ldy #0 ;Char offset
PrintString_again:
lda [z_HL],y ;Load a character from z_HL + Y
cmp #255
beq PrintString_Done ;If it's 255 we're done!
jsr PrintChar ;Print the character
iny
jmp PrintString_again
PrintString_Done:
rts

PrintChar: ;Print ASCII Character A
and #%11011111 ;We have no lowercase
beq PrintCharSpace ;Char 32 (0) = Space
sec
sbc #64 ;First Char after space is A (64)
PrintCharSpace:
pha
ldx z_HL ;Backup z_HL
phx ;Vram= (Ypos*32) + Xpos
lda CursorY
sta z_H

lda #0
clc
ror z_H ;Y pos * 32
ror
ror z_H
ror
ror z_H
ror
adc CursorX ;add X pos
sta z_L
WaitVblank:
lda $4212 ;HVBJOY - Status
; xy00000a - x=vblank state y=hblank state a=joypad ready
and #%10000000
beq WaitVblank ;Wait until we get nonzero
;this means we're in VBLANK
ldx z_HL
stx $2116 ;MemHL -Video port address [VMADDL/VMADDH]

stz $2119 ;DataH - Video port data
plx
stx z_HL ;Restore z_HL
pla
sta $2118 ;DataL - Video port data

inc CursorX ;Move cursor across
rts

BitmapFont: ;Chibiakumas bitmap font
.DB $00,$00,$00,$00,$00,$00,$00,$00 ;Space
.DB $18,$3C,$66,$66,$7E,$66,$24,$00 ;A
.DB $3C,$66,$66,$7C,$66,$66,$3C,$00 ;B
.DB $38,$7C,$C0,$C0,$C0,$7C,$38,$00 ;C
.DB $3C,$64,$66,$66,$66,$64,$38,$00 ;D
.DB $3C,$7E,$60,$78,$60,$7E,$3C,$00 ;E
.DB $38,$7C,$60,$78,$60,$60,$20,$00 ;F
.DB $3C,$66,$C0,$C0,$CC,$66,$3C,$00 ;G
.DB $24,$66,$66,$7E,$66,$66,$24,$00 ;H
.DB $10,$18,$18,$18,$18,$18,$08,$00 ;I
.DB $08,$0C,$0C,$0C,$4C,$FC,$78,$00 ;J
.DB $24,$66,$6C,$78,$6C,$66,$24,$00 ;K
.DB $20,$60,$60,$60,$60,$7E,$3E,$00 ;L
.DB $44,$EE,$FE,$D6,$D6,$D6,$44,$00 ;M
.DB $44,$E6,$F6,$DE,$CE,$C6,$44,$00 ;N
.DB $38,$6C,$C6,$C6,$C6,$6C,$38,$00 ;O
.DB $38,$6C,$64,$7C,$60,$60,$20,$00 ;P
.DB $38,$6C,$C6,$C6,$CA,$74,$3A,$00 ;Q
.DB $3C,$66,$66,$7C,$6C,$66,$26,$00 ;R
.DB $3C,$7E,$60,$3C,$06,$7E,$3C,$00 ;S
.DB $3C,$7E,$18,$18,$18,$18,$08,$00 ;T
.DB $24,$66,$66,$66,$66,$66,$3C,$00 ;U
.DB $24,$66,$66,$66,$66,$3C,$18,$00 ;V
.DB $44,$C6,$D6,$D6,$FE,$EE,$44,$00 ;W
.DB $C6,$6C,$38,$38,$6C,$C6,$44,$00 ;X
.DB $24,$66,$66,$3C,$18,$18,$08,$00 ;Y
.DB $7C,$FC,$0C,$18,$30,$7E,$7C,$00 ;Z

Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Re: Real SNES hardware help?

Post by Domeshtan » Sat Aug 27, 2022 4:09 pm

;SNES Joypad example that works on a real SNES
;==LoRom==
.MEMORYMAP
SLOTSIZE $8000
DEFAULTSLOT 0
SLOT 0 $8000
.ENDME

.ROMBANKSIZE $8000
.ROMBANKS 8

.SNESHEADER
ID "SNES"

NAME "SNES Program Name "
; "123456789012345678901"

SLOWROM
LOROM

CARTRIDGETYPE $00
ROMSIZE $08
SRAMSIZE $00
COUNTRY $01
LICENSEECODE $00
VERSION $00
.ENDSNES

.SNESNATIVEVECTOR
COP EmptyHandler
BRK EmptyHandler
ABORT EmptyHandler
NMI EmptyHandler
IRQ EmptyHandler
.ENDNATIVEVECTOR

.SNESEMUVECTOR
COP EmptyHandler
ABORT EmptyHandler
NMI EmptyHandler
RESET Start
IRQBRK EmptyHandler
.ENDEMUVECTOR

.BANK 0 SLOT 0
;--------------------- My tweak here ------------------------------------
.EQU z_HL $20 ;Zero page variables for our 24 bit addresses
.EQU z_L $20
.EQU z_H $21
.EQU z_HLU $22

.EQU CursorX $40 ;X position of next character draw
.EQU CursorY $41 ;Y position of next character draw
;------------------------------------------------------------------------

.ORG 0
.SECTION "EmptyVectors" SEMIFREE

EmptyHandler:
rti
.ENDS

.EMPTYFILL $00
;---------------------------------------- END ------------------------------




;++++++++++++++++++++++++++++++++++++++++++++++++
Start: ; ME ADDING IN HERE
;.MACRO Snes_Init
sei ; Disabled interrupts
clc ; clear carry to switch to native mode
xce ; Xchange carry & emulation bit. native mode
rep #$18 ; Binary mode (decimal mode off), X/Y 16 bit

.INDEX 16 ;XY 16 bit ME ADDING

ldx #$1FFF ; set stack to $1FFF
txs
;jsr Init
;.ENDM
.bank 0
.section "Snes_Init" SEMIFREE
Init:
sep #$30 ; X,Y,A are 8 bit numbers

.INDEX 8 ;XY 8 bit ME ADDING

lda #$8F ; screen off, full brightness
sta $2100 ;(INIDISP) brightness + screen enable register
stz $2101 ;(OBSEL) Sprite register (size + address in VRAM)
stz $2102 ;(OAMADDL) Sprite registers (address of sprite memory [OAM])
stz $2103 ;(OAMADDH) "" ""
stz $2105 ;(BGMODE) Mode 0, = Graphic mode register
stz $2106 ;(MOSAIC) noplanes, no mosaic, = Mosaic register
stz $2107 ;(BG1SC) Plane 0 map VRAM location
stz $2108 ;(BG2SC) Plane 1 map VRAM location
stz $2109 ;(BG3S3) Plane 2 map VRAM location
stz $210A ;(BG3S3)??? Plane 3 map VRAM location
stz $210B ;(BG12NBA) Plane 0+1 Tile data location
stz $210C ;(BG34NBA) Plane 2+3 Tile data location
stz $210D ;(BG1HOFS) Plane 0 scroll x (first 8 bits)
stz $210D ;(BG1HOFS) Plane 0 scroll x (last 3 bits) #$0 - #$07ff
lda #$FF ; The top pixel drawn on the screen isn't the top one in the tilemap, it's the one above that.
sta $210E ;(BG1VOFS) Plane 0 scroll y (first 8 bits)
sta $2110 ;(BG2VOFS) Plane 1 scroll y (first 8 bits)
sta $2112 ;(HVBJOY) Plane 2 scroll y (first 8 bits)
sta $2114 ;(BG4VOFS) Plane 3 scroll y (first 8 bits)
lda #$07 ; Since this could get quite annoying, it's better to edit the scrolling registers to fix this.
sta $210E ;(BG1VOFS) Plane 0 scroll y (last 3 bits) #$0 - #$07ff
sta $2110 ;(BG2VOFS) Plane 1 scroll y (last 3 bits) #$0 - #$07ff
sta $2112 ;(HVBJOY) Plane 2 scroll y (last 3 bits) #$0 - #$07ff
sta $2114 ;(BG4VOFS) Plane 3 scroll y (last 3 bits) #$0 - #$07ff
stz $210F ;(BG2HOFS) Plane 1 scroll x (first 8 bits)
stz $210F ;(BG2HOFS) Plane 1 scroll x (last 3 bits) #$0 - #$07ff
stz $2111 ;(BG3HOFS) Plane 2 scroll x (first 8 bits)
stz $2111 ;(BG3HOFS) Plane 2 scroll x (last 3 bits) #$0 - #$07ff
stz $2113 ;(BG4HOFS) Plane 3 scroll x (first 8 bits)
stz $2113 ;(BG4HOFS) Plane 3 scroll x (last 3 bits) #$0 - #$07ff
lda #$80 ; increase VRAM address after writing to $2119
sta $2115 ;(VMAIN) VRAM address increment register
stz $2116 ;(VMADDL) VRAM address low
stz $2117 ;(VMADDH) VRAM address high
stz $211A ;(M7SEL) Initial Mode 7 setting register
stz $211B ;(M7A) Mode 7 matrix parameter A register (low)
lda #$01
sta $211B ;(M7A) Mode 7 matrix parameter A register (high)
stz $211C ;(M7B) Mode 7 matrix parameter B register (low)
stz $211C ;(M7B) Mode 7 matrix parameter B register (high)
stz $211D ;(M7C) Mode 7 matrix parameter C register (low)
stz $211D ;(M7C) Mode 7 matrix parameter C register (high)
stz $211E ;(M7D) Mode 7 matrix parameter D register (low)
sta $211E ;(M7D) Mode 7 matrix parameter D register (high)
stz $211F ;(M7X) Mode 7 center position X register (low)
stz $211F ;(M7X) Mode 7 center position X register (high)
stz $2120 ;(M7Y) Mode 7 center position Y register (low)
stz $2120 ;(M7Y) Mode 7 center position Y register (high)
stz $2121 ;(CGADD) Color number register ($0-ff)
stz $2123 ;(W12SEL) BG1 & BG2 Window mask setting register
stz $2124 ;(W34SEL) BG3 & BG4 Window mask setting register
stz $2125 ;(WOBJSEL) OBJ & Color Window mask setting register
stz $2126 ;(WH0) Window 1 left position register
stz $2127 ;(WH1) Window 2 left position register
stz $2128 ;(WH2) Window 3 left position register
stz $2129 ;(WH3) Window 4 left position register
stz $212A ;(WBGLOG) BG1, BG2, BG3, BG4 Window Logic register
stz $212B ;(WOBJLOG) OBJ, Color Window Logic Register (or,and,xor,xnor)
sta $212C ;(TM) Main Screen designation (planes, sprites enable)
stz $212D ;(TS) Sub Screen designation
stz $212E ;(TMW) Window mask for Main Screen
stz $212F ;(TSW) Window mask for Sub Screen
lda #$30
sta $2130 ;(CGWSEL) Color addition & screen addition init setting
stz $2131 ;(CGADSUB) Add/Sub sub designation for screen, sprite, color
lda #$E0
sta $2132 ;(COLDATA) color data for addition/subtraction
stz $2133 ;(SETINI) Screen setting (interlace x,y/enable SFX data)
stz $4200 ;(NMITIMEN) Enable V-blank, interrupt, Joypad register
lda #$FF
sta $4201 ;(WRIO) Programmable I/O port
stz $4202 ;(WRMPYA) Multiplicand A
stz $4203 ;(WRMPYB) Multiplier B
stz $4204 ;(WRDIVL) Multiplier C
stz $4205 ;(WRVIDH) Multiplicand C
stz $4206 ;(WRDIVB) Divisor B
stz $4207 ;(HTIMEL) Horizontal Count Timer
stz $4208 ;(HTIMEH) Horizontal Count Timer MSB (most significant bit)
stz $4209 ;(VTIMEL) Vertical Count Timer
stz $420A ;(VTIMEH) Vertical Count Timer MSB
stz $420B ;(MDMAEN) General DMA enable (bits 0-7)
stz $420C ;(HDMAEN) Horizontal DMA (HDMA) enable (bits 0-7)
stz $420D ;(MEMSEL) Access cycle designation (slow/fast rom)
cli ; Enable interrupts
;rts
.ends


;++++++++++++++++++++++++++++++++++++++++++++++++







MyProg:
SEI ;Stop interrupts
clc
xce ;16 bit mode (65816 Native)

; --MX---- M=Accumulator X=XY
REP #%00010000 ;16 bit XY
.INDEX 16 ;XY 16 bit

;Set up the screen
;aaaabbbb -aaa=base addr for BG2 bbb=base addr for BG1
lda #%00010001
sta $210B ;BG1 & BG2 VRAM location register [BG12NBA]

;xxxxxxss - xxx=address ss=SC size 00=32x32 01=64x32 10=32x64 11=64x64
stz $2107 ;BG1SC - BG1 Tilemap VRAM location (%00000000)

;x000bbbb - x=screen disable (1=disable) bbbb=brightness (15=max)
lda #%10001111 ;INIDISP - Screen display register
sta $2100

;i000abcd - i=0 inc on $2118/2139 i=1 $2119/213A abcd=move size
stz $2115 ;VMAIN - Video port control
;(Inc on write to $2118)

; abcdefff - abcd=tile sizes e=pri fff=mode def
lda #%00001001
sta $2105 ;BGMODE - Screen mode register

;Set up Palette - Color 0
stz $2121 ;CGADD -Palette selection
stz $2122 ;CGDATA - Color data register gggrrrrr
stz $2122 ;CGDATA - Color data register ?bbbbbgg
;Color 1
lda #%00001111
sta $2122 ;CGDATA - Color data register gggrrrrr
lda #%00111100
sta $2122 ;CGDATA - Color data register ?bbbbbgg
;Color 2
lda #%11100000
sta $2122 ;CGDATA - Color data register gggrrrrr
lda #%01111111
sta $2122 ;CGDATA - Color data register ?bbbbbgg
;Color 3
lda #%11111111
sta $2122 ;CGDATA - Color data register gggrrrrr
lda #%01111111
sta $2122 ;CGDATA - Color data register ?bbbbbgg

;Transfer Patterns
lda #<Bitmap ;Source Data
sta z_L ;L byte of address (24 bit UHL)
lda #>Bitmap
sta z_H ;H byte of address (24 bit UHL)
lda #Bitmap>>16
sta z_HLU ;U byte of address (24 bit UHL)

ldx #$1000 ;Vram Dest - $1000 (Patterns)
stx $2116 ;2116/7 - Video port address (VMADDL/H)

ldy #0
Patterns_NextWord: ;Bitplanes 0/1/2/3
lda [z_HL],y ;We write 1 word/2 bytes to each VRAM address
iny
sta $2119 ;1st byte H

lda [z_HL],y ;We write 1 word/2 bytes to each VRAM address
iny
sta $2118 ;2nd byte L (and Inc VRAM address)

cpy #(Bitmap_End-Bitmap) ;Repeat for more bytes
bne Patterns_NextWord

;Set Scroll position
stz $210D ;BG1HOFS BG1 horizontal scroll
stz $210D ;BG1HOFS
lda #-1
sta $210E ;BG1VOFS BG1 vertical scroll
stz $210E ;BG1VOFS

stz $2116 ;MemL - Video port address
stz $2117 ;MemH - Video port address

;Clear Tilemap
ldx #$400 ;Size of tilemap
ClearTilemap:
stz $2119 ;1st byte H
stz $2118 ;2nd byte L (and Inc VRAM address)
dex
bne ClearTilemap

;Turn on screen
; ---S4321 - S=sprites 4-1=enable Bgx
lda #%00000001 ;Turn on BG1
sta $212C ;Main screen designation [TM]

; x000bbbb - x=screen disable (1=disable) bbbb=brightness
lda #%00001111 ;Screen ON
sta $2100 ;INIDISP - Screen display register

;Start our test program
; --MX---- M=Accumulator X=XY
sep #%00010000 ;8 bit XY
.INDEX 8 ;XY 8 bit

ldx #4 ;Sprite Xpos
ldy #4 ;Sprite Ypos
jmp StartDraw

infloop:
jsr ReadJoystick ;Read Joystick into z_H
lda z_H
beq infloop ;See if no keys are pressed

StartDraw:
lda z_H ;Joystick Buttons
pha
jsr RemovePlayer ;Remove old player sprite
pla
sta z_H
and #%00010000 ;RLDUSsBA
beq JoyNotUp ;Jump if UP not pressed
cpy #0
beq JoyNotUp
dey ;Move Y Up the screen
JoyNotUp:
lda z_H
and #%00100000 ;RLDUSsBA
beq JoyNotDown ;Jump if DOWN not pressed
cpy #27
beq JoyNotDown
iny ;Move Y Down the screen
JoyNotDown:
lda z_H
and #%01000000 ;RLDUSsBA
beq JoyNotLeft ;Jump if LEFT not pressed
cpx #0
beq JoyNotLeft
dex ;Move X Left
JoyNotLeft:
lda z_H
and #%10000000 ;RLDUSsBA
beq JoyNotRight ;Jump if RIGHT not pressed
cpx #31
beq JoyNotRight
inx ;Move X Right
JoyNotRight:

jsr DrawPlayer ;Draw Player Sprite

phx ; --MX---- M=Accumulator X=XY
rep #%00010000 ;16 bit XY
.INDEX 16 ;XY 16 bit

ldx #65535
PauseX:
dex
bne PauseX
; --MX---- M=Accumulator X=XY
sep #%00010000 ;8 bit XY
.INDEX 8 ;XY 8 bit
plx
jmp infloop

ReadJoystick:
txa
pha
;Strobe joysticks to reset them
ldx #$01 ;Send a 1 to joysticks (strobe reset)
stx $4016 ;JOYPAD1 port
dex ;Send a 0 to joysticks (read data)
stx $4016 ;JOYPAD1 port

ldx #8 ;Read in 8 bits from joystick
ReadJoystick_Loop:
lda $4016 ;JOYPAD1
lsr ; bit0 -> Carry
ror z_H ;Add carry to Joy1 data
dex
bne ReadJoystick_Loop
pla
tax
rts

RemovePlayer:
lda #0
jmp DrawTile ;Remove the old smiley
DrawPlayer:
lda #1
DrawTile: ;A = Tilenum (X,Y) = Tilepos
phx
phy
pha
tya ;Vram= (Ypos*32) + Xpos
sta z_H
lda #0
clc
ror z_H ;Y pos * 32
ror
ror z_H
ror
ror z_H
ror
sta z_L
txa ;+ X pos
adc z_L
sta z_L
WaitVBlank:
lda $4212 ;HVBJOY - Status
; xy00000a - x=vblank state y=hblank state
and #%10000000 ;a=joypad ready
beq WaitVBlank ;Wait until we get nonzero
;this means we're in VBLANK
lda z_L
sta $2116 ;MemL - Video port address
lda z_H
sta $2117 ;MemH - Video port address

stz $2119 ;DataH - Video port data
pla
sta $2118 ;DataL - Video port data
ply
plx
rts

Bitmap: ;Empty Tile
.db 0,0,0,0,0,0,0,0
.db 0,0,0,0,0,0,0,0
.db 0,0,0,0,0,0,0,0
.db 0,0,0,0,0,0,0,0

; 11111111 000000000 - Bitplane 1/0 - Smiley
.db %00000000,%00111100 ; 0
.db %00000000,%01111110 ; 1
.db %00100100,%11111111 ; 2
.db %00000000,%11111111 ; 3
.db %00000000,%11111111 ; 4
.db %00100100,%11011011 ; 5
.db %00011000,%01100110 ; 6
.db %00000000,%00111100 ; 7
; 33333333 22222222 - Bitplane 3/2
.db %00000000,%00000000 ; 0
.db %00000000,%00000000 ; 1
.db %00000000,%00000000 ; 2
.db %00000000,%00000000 ; 3
.db %00000000,%00000000 ; 4
.db %00000000,%00000000 ; 5
.db %00000000,%00000000 ; 6
.db %00000000,%00000000 ; 7
Bitmap_End:

;.ORG $FFFA ;Cartridge Footer
;.DW $0000 ;NMI (Vblank)
;.DW $8000 ;RESET VECTOR
;.DW $0000 ;IRQ/BRK VECTOR

Domeshtan
Posts: 6
Joined: Sun Jul 24, 2022 6:35 pm

Re: Real SNES hardware help?

Post by Domeshtan » Sat Aug 27, 2022 4:21 pm

And some video to show the process. Nice thing about Muramasa boards is that that they don't need any "re-wiring". I guess SNES used Mask ROMs where some pins need to be changed around to work. The 1Meg LoROM board is simple enough and doesn't need an adaptor to write to the Eproms. The 2 Meg boards I have, you have to solder certain pads together to let the SNES know if the game is a LoROM game, HiROM, etc... I think there is a way to do ExHiROM and I think there is a setting even for ExLOROM which I don't think was ever used. The larger chips need an ADP-054 adaptor to write properly. If your GQ model is a 4x4 make sure the ADP-054 adaptor you buy is version 4.1 and you have the latest software installed. Also if you really need to write a HUGE game and want to go with the even fancier boards they have you can write to 27C322 Eproms. The site said they would work on my board type but don't. I think they got their boards mixed up as it was not written on my circuit board but is written on another one they have. 27C322s you need to change the jumper on the upper left corner of the board to connect pins 2 and 3 instead of pins 1 and 2 or it won't write properly.


Post Reply

Return to “Super Nintendo Assembly Programming”