Difference between revisions of "SCHG How-to:Port Flamewing's Sonic 3 & Knuckles Sound Driver"
From Sonic Retro
(forgot a z) |
(added step 2) |
||
Line 13: | Line 13: | ||
*A utitily to extract .7z files. I'd Recommend 7Zip. | *A utitily to extract .7z files. I'd Recommend 7Zip. | ||
− | ==Step 2: | + | ==Step 2: Setup== |
+ | Make a new .asm files called 'Macos.asm' and include it in your disasm's /_inc/ folder. | ||
+ | Put this code in the file: | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | SonicControl equ $FFFFF602 | ||
+ | Joypad equ $FFFFF604 | ||
+ | |||
+ | Held equ 0 | ||
+ | Press equ 1 | ||
+ | |||
+ | iStart equ 7 | ||
+ | iA equ 6 | ||
+ | iC equ 5 | ||
+ | iB equ 4 | ||
+ | iRight equ 3 | ||
+ | iLeft equ 2 | ||
+ | iDown equ 1 | ||
+ | iUp equ 0 | ||
+ | |||
+ | MaskStart equ 1<<7 | ||
+ | MaskA equ 1<<6 | ||
+ | MaskC equ 1<<5 | ||
+ | MaskB equ 1<<4 | ||
+ | MaskRight equ 1<<3 | ||
+ | MaskLeft equ 1<<2 | ||
+ | MaskDown equ 1<<1 | ||
+ | MaskUp equ 1 | ||
+ | |||
+ | ; ============================================================= | ||
+ | ; Macro to check button presses | ||
+ | ; Arguments: 1 - buttons to check | ||
+ | ; 2 - bitfield to check | ||
+ | ; ------------------------------------------------------------- | ||
+ | tpress macro | ||
+ | move.b (\2+1),d0 | ||
+ | andi.b #\1,d0 | ||
+ | endm | ||
+ | |||
+ | ; ============================================================= | ||
+ | ; Macro to check if buttons are held | ||
+ | ; Arguments: 1 - buttons to check | ||
+ | ; 2 - bitfield to check | ||
+ | ; ------------------------------------------------------------- | ||
+ | theld macro | ||
+ | move.b \2,d0 | ||
+ | andi.b #\1,d0 | ||
+ | endm | ||
+ | |||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; Align and pad | ||
+ | ; input: length to align to, value to use as padding (default is 0) | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | align: macro | ||
+ | if (narg=1) | ||
+ | dcb.b \1-(*%\1),0 | ||
+ | else | ||
+ | dcb.b \1-(*%\1),\2 | ||
+ | endc | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; Set a VRAM address via the VDP control port. | ||
+ | ; input: 16-bit VRAM address, control port (default is ($C00004).l) | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | locVRAM: macro loc,controlport | ||
+ | if (narg=1) | ||
+ | move.l #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),($C00004).l | ||
+ | else | ||
+ | move.l #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),controlport | ||
+ | endc | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; DMA copy data from 68K (ROM/RAM) to the VRAM | ||
+ | ; input: source, length, destination | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | writeVRAM: macro | ||
+ | lea (vdp_control_port).l,a5 | ||
+ | move.l #$94000000+(((\2>>1)&$FF00)<<8)+$9300+((\2>>1)&$FF),(a5) | ||
+ | move.l #$96000000+(((\1>>1)&$FF00)<<8)+$9500+((\1>>1)&$FF),(a5) | ||
+ | move.w #$9700+((((\1>>1)&$FF0000)>>16)&$7F),(a5) | ||
+ | move.w #$4000+(\3&$3FFF),(a5) | ||
+ | move.w #$80+((\3&$C000)>>14),(v_vdp_buffer2).w | ||
+ | move.w (v_vdp_buffer2).w,(a5) | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; DMA copy data from 68K (ROM/RAM) to the CRAM | ||
+ | ; input: source, length, destination | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | writeCRAM: macro | ||
+ | lea (vdp_control_port).l,a5 | ||
+ | move.l #$94000000+(((\2>>1)&$FF00)<<8)+$9300+((\2>>1)&$FF),(a5) | ||
+ | move.l #$96000000+(((\1>>1)&$FF00)<<8)+$9500+((\1>>1)&$FF),(a5) | ||
+ | move.w #$9700+((((\1>>1)&$FF0000)>>16)&$7F),(a5) | ||
+ | move.w #$C000+(\3&$3FFF),(a5) | ||
+ | move.w #$80+((\3&$C000)>>14),(v_vdp_buffer2).w | ||
+ | move.w (v_vdp_buffer2).w,(a5) | ||
+ | endm | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; stop the Z80 | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | stopZ80: macro | ||
+ | move.w #$100,($A11100).l | ||
+ | @wait: btst #0,($A11100).l | ||
+ | bne.s @wait | ||
+ | endm | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; wait for Z80 to stop | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | waitZ80: macro | ||
+ | @wait: btst #0,($A11100).l | ||
+ | bne.s @wait | ||
+ | endm | ||
+ | |||
+ | stopZ80a: macro | ||
+ | move.w #$100,($A11100).l | ||
+ | endm | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; reset the Z80 | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | resetZ80: macro | ||
+ | move.w #$100,($A11200).l | ||
+ | endm | ||
+ | |||
+ | resetZ80a: macro | ||
+ | move.w #0,($A11200).l | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; start the Z80 | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | startZ80: macro | ||
+ | move.w #0,($A11100).l | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; disable interrupts | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | disable_ints: macro | ||
+ | move #$2700,sr | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; enable interrupts | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | enable_ints: macro | ||
+ | move #$2300,sr | ||
+ | endm | ||
+ | |||
+ | ; --------------------------------------------------------------------------- | ||
+ | ; play a sound effect or music | ||
+ | ; input: track, terminate routine (leave blank to not terminate) | ||
+ | ; --------------------------------------------------------------------------- | ||
+ | |||
+ | music: macro track,terminate | ||
+ | move.w #track,d0 | ||
+ | if (narg=1) | ||
+ | jsr (PlaySound).l | ||
+ | else | ||
+ | jmp (PlaySound).l | ||
+ | endc | ||
+ | endm | ||
+ | |||
+ | sfx: macro track,terminate | ||
+ | move.w #track,d0 | ||
+ | if (narg=1) | ||
+ | jsr (PlaySound_Special).l | ||
+ | else | ||
+ | jmp (PlaySound_Special).l | ||
+ | endc | ||
+ | endm | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This code adds some macros that the S3K driver uses, along with controller macros that you may find helpful. | ||
+ | |||
+ | ==Step 3: Removing the Sonic 1 Sound Driver== | ||
+ | First, W | ||
− | ==Step | + | ==Step 4: Inserting the Sonic 3K Sound Driver== |
After you have removed the Sonic 1 Sound Driver, Locate the SoundDriverLoad Routine. | After you have removed the Sonic 1 Sound Driver, Locate the SoundDriverLoad Routine. | ||
The routine will look like this: | The routine will look like this: | ||
Line 76: | Line 264: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ==Step | + | ==Step 5: Modifying Build.bat== |
− | ==Step | + | ==Step 6: Changing SFX== |
− | ==Step | + | ==Step 7: Fixing Music== |
==Known Issues== | ==Known Issues== | ||
Some of the Known Issues with this guide are: | Some of the Known Issues with this guide are: |
Revision as of 15:17, 12 May 2020
(Original guide by KZG4)
Many people have been using the older Sonic 3 and Knuckles sound driver port made by Kram1024 many years ago. I decided to try and port over Flamewing's improved Sonic 3 and Knuckles sound driver so people that intend to port over a Z80 based sound driver will be able to use a newer one.
Contents
Note
This guide is meant for a fresh install. I have not made this in order for the user to copy this over a disasm with Port Sonic 3 Sound Driver Part 1 applied onto it. I have not tested it so I have no idea if adding this guide over it will work.
Step 1: Resources
First you need the following:
- An ASM68K version of Hivebrain's disasm of Sonic 1. You can use the original version: Sonic 1 (Split and Text by Hivebrain) (ASM68K) (info) (1,016 kB) or you can use a modified version, such as Project Sonic 1: Two-Eight by MarkeyJester
- Flamewing's Sonic 3 and Knuckles sound driver: You can get this right here.
- Flamewing's smps2asm Music and SFX Pack: You can get this right here
- A utitily to extract .7z files. I'd Recommend 7Zip.
Step 2: Setup
Make a new .asm files called 'Macos.asm' and include it in your disasm's /_inc/ folder. Put this code in the file:
SonicControl equ $FFFFF602
Joypad equ $FFFFF604
Held equ 0
Press equ 1
iStart equ 7
iA equ 6
iC equ 5
iB equ 4
iRight equ 3
iLeft equ 2
iDown equ 1
iUp equ 0
MaskStart equ 1<<7
MaskA equ 1<<6
MaskC equ 1<<5
MaskB equ 1<<4
MaskRight equ 1<<3
MaskLeft equ 1<<2
MaskDown equ 1<<1
MaskUp equ 1
; =============================================================
; Macro to check button presses
; Arguments: 1 - buttons to check
; 2 - bitfield to check
; -------------------------------------------------------------
tpress macro
move.b (\2+1),d0
andi.b #\1,d0
endm
; =============================================================
; Macro to check if buttons are held
; Arguments: 1 - buttons to check
; 2 - bitfield to check
; -------------------------------------------------------------
theld macro
move.b \2,d0
andi.b #\1,d0
endm
; ---------------------------------------------------------------------------
; Align and pad
; input: length to align to, value to use as padding (default is 0)
; ---------------------------------------------------------------------------
align: macro
if (narg=1)
dcb.b \1-(*%\1),0
else
dcb.b \1-(*%\1),\2
endc
endm
; ---------------------------------------------------------------------------
; Set a VRAM address via the VDP control port.
; input: 16-bit VRAM address, control port (default is ($C00004).l)
; ---------------------------------------------------------------------------
locVRAM: macro loc,controlport
if (narg=1)
move.l #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),($C00004).l
else
move.l #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),controlport
endc
endm
; ---------------------------------------------------------------------------
; DMA copy data from 68K (ROM/RAM) to the VRAM
; input: source, length, destination
; ---------------------------------------------------------------------------
writeVRAM: macro
lea (vdp_control_port).l,a5
move.l #$94000000+(((\2>>1)&$FF00)<<8)+$9300+((\2>>1)&$FF),(a5)
move.l #$96000000+(((\1>>1)&$FF00)<<8)+$9500+((\1>>1)&$FF),(a5)
move.w #$9700+((((\1>>1)&$FF0000)>>16)&$7F),(a5)
move.w #$4000+(\3&$3FFF),(a5)
move.w #$80+((\3&$C000)>>14),(v_vdp_buffer2).w
move.w (v_vdp_buffer2).w,(a5)
endm
; ---------------------------------------------------------------------------
; DMA copy data from 68K (ROM/RAM) to the CRAM
; input: source, length, destination
; ---------------------------------------------------------------------------
writeCRAM: macro
lea (vdp_control_port).l,a5
move.l #$94000000+(((\2>>1)&$FF00)<<8)+$9300+((\2>>1)&$FF),(a5)
move.l #$96000000+(((\1>>1)&$FF00)<<8)+$9500+((\1>>1)&$FF),(a5)
move.w #$9700+((((\1>>1)&$FF0000)>>16)&$7F),(a5)
move.w #$C000+(\3&$3FFF),(a5)
move.w #$80+((\3&$C000)>>14),(v_vdp_buffer2).w
move.w (v_vdp_buffer2).w,(a5)
endm
; ---------------------------------------------------------------------------
; stop the Z80
; ---------------------------------------------------------------------------
stopZ80: macro
move.w #$100,($A11100).l
@wait: btst #0,($A11100).l
bne.s @wait
endm
; ---------------------------------------------------------------------------
; wait for Z80 to stop
; ---------------------------------------------------------------------------
waitZ80: macro
@wait: btst #0,($A11100).l
bne.s @wait
endm
stopZ80a: macro
move.w #$100,($A11100).l
endm
; ---------------------------------------------------------------------------
; reset the Z80
; ---------------------------------------------------------------------------
resetZ80: macro
move.w #$100,($A11200).l
endm
resetZ80a: macro
move.w #0,($A11200).l
endm
; ---------------------------------------------------------------------------
; start the Z80
; ---------------------------------------------------------------------------
startZ80: macro
move.w #0,($A11100).l
endm
; ---------------------------------------------------------------------------
; disable interrupts
; ---------------------------------------------------------------------------
disable_ints: macro
move #$2700,sr
endm
; ---------------------------------------------------------------------------
; enable interrupts
; ---------------------------------------------------------------------------
enable_ints: macro
move #$2300,sr
endm
; ---------------------------------------------------------------------------
; play a sound effect or music
; input: track, terminate routine (leave blank to not terminate)
; ---------------------------------------------------------------------------
music: macro track,terminate
move.w #track,d0
if (narg=1)
jsr (PlaySound).l
else
jmp (PlaySound).l
endc
endm
sfx: macro track,terminate
move.w #track,d0
if (narg=1)
jsr (PlaySound_Special).l
else
jmp (PlaySound_Special).l
endc
endm
This code adds some macros that the S3K driver uses, along with controller macros that you may find helpful.
Step 3: Removing the Sonic 1 Sound Driver
First, W
Step 4: Inserting the Sonic 3K Sound Driver
After you have removed the Sonic 1 Sound Driver, Locate the SoundDriverLoad Routine. The routine will look like this:
SoundDriverLoad: ; XREF: GameClrRAM; TitleScreen
nop
move.w #$100,($A11100).l ; stop the Z80
move.w #$100,($A11200).l ; reset the Z80
lea (Kos_Z80).l,a0 ; load sound driver
lea ($A00000).l,a1
bsr.w KosDec ; decompress
move.w #0,($A11200).l
nop
nop
nop
nop
move.w #$100,($A11200).l ; reset the Z80
move.w #0,($A11100).l ; start the Z80
rts
; End of function SoundDriverLoad
Now, replace this routine with this:
SoundDriverLoad: ; XREF: GameClrRAM; TitleScreen
LoadZ80drv:
nop
stopZ80a
resetZ80
lea (RomEndLoc).l,a0
move.l (a0),d0
addq.l #1,d0
movea.l d0,a0
lea ($A00000).l,a1
jsr KosDec
; lea (DriverResetData).l,a0
; lea ($A01C8A).l,a1 ; z80 ram start of variables (A01C00 in older version)
; move.w #DriverResetDataEnd-DriverResetData,d0
;DriverResetDataLoadLoop:
; move.b (a0)+,(a1)+
; dbf d0,DriverResetDataLoadLoop
btst #0,($C00005).l ; check video mode
sne ($A01C02).l ; set PAL mode flag
resetZ80a
nop
nop
nop
nop
resetZ80
startZ80
rts
; End of function SoundDriverLoad
DriverResetData:
dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DriverResetDataEnd:
Step 5: Modifying Build.bat
Step 6: Changing SFX
Step 7: Fixing Music
Known Issues
Some of the Known Issues with this guide are:
- Pushing SFX is broken
- Point SFX is broken
- tba