Useful Code Snippets
Useful code snippets for the 65c816 ASM and general SNES hardware.
65c816 S-CPU
General
Wait for H-Blank
- BIT $4212 BVS - - BIT $4212 BVC -
Inverse the accumulator (8-bit)
By Nambona890
Works with SA-1.
EOR #$FF INC
Inverse the accumulator (16-bit)
By Nambona890
Works with SA-1.
EOR #$FFFF INC
Toggle Carry Flag Macro
Works with SA-1.
macro XOC() BCC ?set CLC BRA ?done ?set: SEC ?done: endmacro
Toggle Carry Flag Alternative (8-bit)
Works with SA-1.
ROL EOR #$01 ROR
Toggle Carry Flag Alternative (16-bit)
Works with SA-1.
ROL EOR #$0001 ROR
Long Branch Macros
Useful if you want to branch more than 0x80 bytes forward/backwards.
Works with SA-1.
macro JEQ(branch) BNE ?branch JMP <branch> ?branch: endmacro macro JNE(branch) BEQ ?branch JMP <branch> ?branch: endmacro macro JCC(branch) BCS ?branch JMP <branch> ?branch: endmacro macro JCS(branch) BCC ?branch JMP <branch> ?branch: endmacro macro JPL(branch) BMI ?branch JMP <branch> ?branch: endmacro macro JMI(branch) BPL ?branch JMP <branch> ?branch: endmacro macro JVC(branch) BVS ?branch JMP <branch> ?branch: endmacro macro JVS(branch) BVC ?branch JMP <branch> ?branch: endmacro
Jump Tables (word pointers)
By lion
Useful for creating complex bits of code with multiple states.
IF USED ON SMW: You will need to reload the Sprite Index ($15E9) to X in each label due to it using the X Register, else it'll crash. SMW however has its own premade Jump Table routine.
LDA ?pointer ; A simple RAM address that changes value depending on state will suffice. ASL ; Multiply the value by 2, as labels are words (16-bit 2 bytes). TAX JSR.w (Pointers,x) RTL/RTS pointers: dw Label00 dw Label01 dw Label02 Label00: RTS Label01: RTS Label02: RTS
Jump Tables (longword pointers)
By lion
Same as above but for longwords instead of words, such as when needing to access different banks.
You can also alter it to use words if you cannot use the X Register for whatever reason.
LDA ?pointer ; A simple RAM address that changes value depending on state will suffice. STA <scratch> ; Scratch RAM, like $00 in SMW will suffice. ASL ; \ CLC ; | Multiply the value by 3, as labels are longwords (24-bits, 3 bytes). ADC <scratch> ; / TAX LDA Pointers,x STA <scratch> LDA Pointers+1,x STA <scratch>+1 LDA Pointers+2,x STA <scratch>+2 JML [<scratch>] pointers: dl Label00 dl Label01 dl Label02 Label00: RTS/RTL Label01: RTS/RTL Label02: RTS/RTL
SMW Hacking
Custom block template
By Alcaro
Works with SA-1.
db $42 ; or db $37 JMP MarioBelow : JMP MarioAbove : JMP MarioSide JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireball JMP TopCorner : JMP BodyInside : JMP HeadInside ; JMP WallFeet : JMP WallBody ; if using db $37 MarioBelow: MarioAbove: MarioSide: TopCorner: BodyInside: HeadInside: WallFeet: WallBody: SpriteV: SpriteH: MarioCape: MarioFireball: RTL
Decompress GFX File
By Vitor Vilela
Works with SA-1.
; Decompress input GFX file ; Must be called from SNES CPU. ; SA-1 is automatically invoked on SA-1 Pack ROMs. STZ $00 REP #$20 LDA #$7EAD ; destination buffer = $7EAD00 STA $01 LDA #$0080 ; deoompress ExGFX80.bin .. JSL $0FF900
Get acts like from map16 number
By Vitor Vilela
Works with SA-1.
; $00 = map16 tile get_act_like: LDA $06F624 STA $02 LDA $06F625 STA $03 LDA $06F626 STA $04 REP #$30 LDA $00 AND #$3FFF ASL TAY LDA [$02],y STA $00 SEP #$30 RTS
Find free OAM slot
By Vitor Vilela
SA-1 hybrid.
; Routine for finding a free OAM slot ; NMSTL compatible. Tested against Level ASM, Overworld ASM. find_oam: LDY #$FC - LDA $02FD|!addr,y CMP #$F0 BNE + CPY #$3C BEQ + DEY DEY DEY DEY BRA - + RTS
Erase current save file
By Sixtare
Erase: REP #$10 LDA $010A CMP #$01 BEQ .01 BCS .02 .00 LDX #$008F JMP .delete .01 LDX #$011E JMP .delete .02 LDX #$01AD .delete LDY #$008F LDA #$00 - STA $700000,x STA $7001AD,x DEX DEY BPL - SEP #$10 RTS
Jump Tables (Using ExecutePtr)
By lion
The above Jump Table codes can also be used in SMW, however there is also a routine included in the original code.
However this does have the inconvenience of the table being right next to the JSL and is also much slower.
LDA ?pointer ; A simple RAM address that changes value depending on state will suffice. JSL $0086DF ; The word (2 bytes) equivalent. pointers: dw Label00 Label00: RTS/RTL
LDA ?pointer ; A simple RAM address that changes value depending on state will suffice. JSL $0086FA ; The longword (3 bytes) equivalent. pointers: dl Label00 Label00: RTS/RTL
65c816 SA-1 CPU
Some snippets present on S-CPU section works with SA-1 CPU as well.
General
Unsigned 16 bit x 16 bit = 32 bit multiplication
By Akaginite
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 16bit * 16bit Multiplication SA-1 version ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Parameters ; $00-$01 : Multiplicand ; $02-$03 : Multiplier ; Return values ; $04-$07 : Product ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MathMul16_16: STZ $2250 REP #$20 LDA $00 STA $2251 ASL A LDA $02 STA $2253 BCS + LDA.w #$0000 + BIT $02 BPL + CLC ADC $00 + CLC ADC $2308 STA $06 LDA $2306 STA $04 SEP #$20 RTS