Skip to content

Instantly share code, notes, and snippets.

@mlarouche
Created December 21, 2015 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlarouche/a15211d2c7d97863d85c to your computer and use it in GitHub Desktop.
Save mlarouche/a15211d2c7d97863d85c to your computer and use it in GitHub Desktop.
ActRaiser MSU-1 WIP Code
arch snes.cpu
// MSU memory map I/O
constant MSU_STATUS($2000)
constant MSU_ID($2002)
constant MSU_AUDIO_TRACK_LO($2004)
constant MSU_AUDIO_TRACK_HI($2005)
constant MSU_AUDIO_VOLUME($2006)
constant MSU_AUDIO_CONTROL($2007)
// SPC communication ports
constant SPC_COMM_0($2140)
constant SPC_COMM_1($2141)
constant SPC_COMM_2($2142)
constant SPC_COMM_3($2143)
// MSU_STATUS possible values
constant MSU_STATUS_TRACK_MISSING($8)
constant MSU_STATUS_AUDIO_PLAYING(%00010000)
constant MSU_STATUS_AUDIO_REPEAT(%00100000)
constant MSU_STATUS_AUDIO_BUSY($40)
constant MSU_STATUS_DATA_BUSY(%10000000)
// SNES Multiply register
constant SNES_MUL_OPERAND_A($4202)
constant SNES_MUL_OPERAND_B($4203)
constant SNES_DIV_DIVIDEND_L($4204)
constant SNES_DIV_DIVIDEND_H($4205)
constant SNES_DIV_DIVISOR($4206)
constant SNES_DIV_QUOTIENT_L($4214)
constant SNES_DIV_QUOTIENT_H($4215)
constant SNES_MUL_DIV_RESULT_L($4216)
constant SNES_MUL_DIV_RESULT_H($4217)
// Constants
if {defined EMULATOR_VOLUME} {
constant FULL_VOLUME($50)
} else {
constant FULL_VOLUME($FF)
}
constant TOTAL_TRACKS(22)
// **********
// * Macros *
// **********
// seek converts SNES LoROM address to physical address
macro seek(variable offset) {
origin ((offset & $7F0000) >> 1) | (offset & $7FFF)
base offset
}
macro CheckMSUPresence(labelToJump) {
lda MSU_ID
cmp.b #'S'
bne {labelToJump}
}
macro WaitMulResult() {
nop
nop
nop
nop
}
macro WaitDivResult() {
nop
nop
nop
nop
nop
nop
nop
nop
}
// ********
// * Code *
// ********
// Hijack
seek($00a412)
jsl MSU_SetupFade
jmp $a41e
seek($02b66c)
jsl SPC_Hijack_1
nop
seek($02b674)
jsl SPC_Hijack_2
jmp $b67e
// During gameplay
seek($00a48f)
jsl MSU_Main
// Sound test
seek($0298f9)
jsl MSU_Main
//seek($029953)
// jsl MSU_Main
//
//seek($029E1B)
// jsl MSU_Main
// Menu ?
seek($02b68d)
jsl MSU_Main
// MSU-1 code
seek($9F8000)
scope MSU_Main: {
php
rep #$30
pha
phx
phy
sep #$30
CheckMSUPresence(OriginalCode)
jsr FindTrackIndex
cpx.b #TOTAL_TRACKS
beq OriginalCode
stx MSU_AUDIO_TRACK_LO
stz MSU_AUDIO_TRACK_HI
IsMSUReady:
lda.w MSU_STATUS
and.b #MSU_STATUS_AUDIO_BUSY
bne IsMSUReady
// Check if the track is missing
lda.w MSU_STATUS
and.b #MSU_STATUS_TRACK_MISSING
bne TrackMissing
// Play the song and add repeat if needed
jsr TrackNeedLooping
sta.w MSU_AUDIO_CONTROL
// Set volume
lda.b #FULL_VOLUME
sta.w MSU_AUDIO_VOLUME
// Play silence on the SPC
rep #$10
ldy #$ab8f
sty $a5
lda #$06
sta $a7
bra OriginalCode
TrackMissing:
stz MSU_AUDIO_CONTROL
stz MSU_AUDIO_VOLUME
OriginalCode:
rep #$30
ply
plx
pla
plp
// lda #$f0
// sta $2140
//-
// lda $2140
// bne -
jsl $029964
rtl
}
scope TrackNeedLooping: {
// Round Clear (Victory Jingle)
cpx.b #04
beq NoLooping
// Descent
cpx.b #08
beq NoLooping
// Level Up (Jingle)
cpx.b #11
beq NoLooping
// Silence (name of the track)
cpx.b #15
beq NoLooping
// Ending (Jingle)
cpx.b #17
beq NoLooping
// Ending (Another Jingle, shorter one)
cpx.b #18
beq NoLooping
lda.b #$03
rts
NoLooping:
lda.b #$01
rts
}
scope FindTrackIndex: {
rep #$10
ldx #$0000
sep #$30
FindTrackLoop:
phx
txa
asl
clc
adc $01,s
tax
rep #$30
lda $a5
cmp TrackPointerData,x
bne +
sep #$30
lda $a7
cmp TrackPointerData+2,x
bne +
sep #$30
plx
bra Exit
+
sep #$30
plx
inx
cpx.b #TOTAL_TRACKS
bne FindTrackLoop
Exit:
rts
TrackPointerData:
dl $18947f // Fillmore
dl $1ca988 // Sky Palace
dl $18ddcc // Bloodpool ~ Casandora
dl $1ae9e2 // The Beast Appears (Boss Battle 1)
dl $1ca5fb // Round Clear (Victory Jingle)
dl $1b8554 // Aitos ~ Temple
dl $1b9470 // Powerful Enemy (Boss Battle 2)
dl $1a94b8 // Opening
dl $1ca7cc // Descent
dl $0ef60f // Piramid ~ Marana
dl $1babed // Birth of the People
dl $1cafeb // Level Up (Jingle)
dl $19fa4b // North Wall
dl $17c027 // All over the World
dl $18d4fa // Satan
dl $1c9f3d // Silence (name of the track)
dl $1aef63 // Sacrifices
dl $1bfd6b // Ending (Jingle)
dl $1cb3f2 // Ending (Another Jingle, shorter one)
dl $1ba2ab // Peaceful World
dl $06ab8f // (Actual Silence)
dl $17b05c // Ending (Long Track)
}
scope SPC_Hijack_1: {
php
rep #$30
pha
sep #$20
CheckMSUPresence(OriginalCode)
rep #$30
pla
plp
rtl
OriginalCode:
rep #$30
pla
plp
-
lda $2143
bne -
rtl
}
scope SPC_Hijack_2: {
php
rep #$30
pha
sep #$20
CheckMSUPresence(OriginalCode)
rep #$30
pla
plp
rtl
OriginalCode:
rep #$30
pla
plp
lda #$f0
sta $2140
-
lda $2140
bne -
rtl
}
scope MSU_SetupFade: {
php
rep #$30
pha
sep #$20
CheckMSUPresence(OriginalCode)
// TODO Setup Fade
stz MSU_AUDIO_CONTROL
rep #$30
pla
plp
rtl
OriginalCode:
rep #$30
pla
plp
lda #$f1
-
cmp $2140
bne -
lda #$01
sta $2140
rtl
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment