Skip to content

Commit

Permalink
Fixed PSG drum phasing issue + moved SCC player state to 0xee00
Browse files Browse the repository at this point in the history
The PSG kick/snare drum transient could sometime occur during the 'off'' phase of the oscillator, which would cause the transient to not be there, or to lose its bite. We fix this by changing the frequency of those drums to '0' so that the oscillator is permanently in the 'on 'state. (note: for the snares this only applies to the initial 'click' part of the sound, not the noise part)
I managed to find some memory for the SCC player's state in 0xee00-0xf100. This is where Vampire Killer normally stores the stack, so I moved the stack to 0xfaf0 which is an unused area of memory (normally used by MSX BASIC). This way we no longer need to change page 0 to RAM, which allows us to remove a lot of complicated slot manipulation code and potential compatibility issues.
  • Loading branch information
jan11011977 committed Jan 6, 2018
1 parent a4947f6 commit 5e73667
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 88 deletions.
52 changes: 46 additions & 6 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
TODO:
- Switch to another ROM that has 'stage select'?
- Reverse engineer and reapply turbofix, sprite flickering fix, jump button fix, R800 enable
- Re-work all music with proper speakers
- drums sound distorted in R800 mode. a lot better in Z80 although not perfect
maybe the player is too fast somehow and it misses a transient?
- SCC doesn't sound loud enough and/or SFX sound too loud (on my TurboR)
- game over music should have sharper instrument
- heart of fire - lead instrument should be louder
- stage clear theme - not bright enough
needs to be higher octave
- out of time need brighter lead
(one at the start is ok)
- ending music needs brighter instruments


turbofix patch (19 dec 2017)
Expand All @@ -19,6 +19,46 @@ sidenote: the turbofix patch causes graphics corruption on the ending
titles (when you complete the game)


kick drum fix notes
-------------------
The Konami PSG kick and snare rely on a click noise generated by a PSG envelope.
The snare consists of a click, followed by noise. The bass drum is just a click
(a slightly longer one). The problem is that if the oscillator is in the 'off'
state at the start of the envelope, you don't hear the initial 'click'.
This means that the sound of the kick/snare is not consistent.
The fix is to set the oscillator frequency to '0', which makes it output
a solid '1'. This way the sound of the click is consistent.

SCC player reverse engineering notes:

229c <- contains bit of PSG register that need to be set
229d/e/f <- contains the values of PSG registers 11, 12, 13


6b51 <- where the jump table is used
6b5d <- jump table of addresses for drum set routines???
6bed <- kick drum routine


PSG frequency eg. register 0, 1 values are stored in IX+a/b, e.g. 200A, 200B


66EE <- frequency is set here
if I NOP this routine out and force the frequency to 0000 then the kick/snare are consistent
but we lose the tonal part of some of the drums

the frequency that 66EE sets comes from IX+10/11
(these are basically copied from 10/11 -> a/b)

6509 <- 10/11 frequency is set here
for the kick drum, HL = 7485?
kick drum settings are at 7484:
7484 = 0A envelope frequency
7485 = 94 flags + frequency (high bits)
7486 = 50 frequency low bits



music corruption when changing songs
------------------------------------
when changing songs, the music must first be stopped using command 00
Expand Down
49 changes: 45 additions & 4 deletions patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@ def patch_mapper(rom):
rom[offset + 2] += 0x10

PATCH_IGNORE_LIST = [0x20daa, 0x23340, 0x20beb]
CHANNEL_OFFSET = -0xc0 # 0e00h -> 02000h
#CHANNEL_OFFSET = -0xc000 # 0e00h -> 02000h
CHANNEL_OFFSET = +0x0e00 # 0e00h -> 0ee00h


def offset_address(rom, index, offset):
"""Modify an address in the ROM by a certain amount"""
addr = rom[index] + rom[index + 1] * 256
addr += offset
rom[index] = addr & 255
rom[index + 1] = addr >> 8


def patch_music_channel_locations(rom):
"""Patch scc player to move channel data locations"""
Expand All @@ -41,10 +51,10 @@ def patch_music_channel_locations(rom):
if (rom[offset] == 0xdd and
rom[offset + 1] == 0x21 and
(rom[offset + 3] & 0xfc) == 0xe0):
rom[offset + 3] += CHANNEL_OFFSET
offset_address(rom, offset + 2, CHANNEL_OFFSET)
if (rom[offset] in [0x01, 0x11, 0x21, 0x32, 0x3a, 0x22, 0x2a] and
(rom[offset + 2] & 0xfc) == 0xe0):
rom[offset + 2] += CHANNEL_OFFSET
offset_address(rom, offset + 1, CHANNEL_OFFSET)


def patch_bios_psg_calls(rom):
Expand Down Expand Up @@ -78,7 +88,38 @@ def save_kss_file(filename, rom):
# Nemesis 3 kick drum fix
# See: https://www.msx.org/forum/msx-talk/general-discussion/nemesis-3-gofers-ambition-episode-ii-bass-drum-lost
assert rom[0x21484] == 0x0a
rom[0x21484] = 0xf0
#rom[0x21484] = 0xf0 # make kick envelope longer
# kick fix (maybe?)
rom[0x21485] = 0x90
rom[0x21486] = 0
# snare fix (maybe?)
rom[0x21487] = 0x90
rom[0x21488] = 0

# kick
rom[0x213e0] = 0xc0
rom[0x213e1] = 0

# snare click
rom[0x213ec] = 0xc0
rom[0x213ed] = 0

# snare2 click
rom[0x21404] = 0xa0
rom[0x21405] = 0

# move the stack to 0xfaf0. this is a bit of memory
# that is used by the MSX BASIC 'PAINT' command so it
# is unused for our purposes. This then frees up the area
# that Vampire Killer has reserved for the stack:
# 0xee00 - 0xf100. We then use this area of memory
# for the Nemesis 3 SCC player's state data
rom[0x0078] = 0xfa
rom[0x0077] = 0xf0

# there are lots of these, and some of the drums
# will iterate through a list of them over time


# compile new music into ROM
compile('mml/vkiller_scc.mml', rom, nemesis3, 0x1a000, 0x7510, 0x8000)
Expand Down
88 changes: 10 additions & 78 deletions vkiller_scc.asm
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@

; disable R800 mode
; R800 mode causes the PSG drums to sound inconsistent/weird
output vkiller_patch01db2.bin
nop
nop
nop
; output vkiller_patch01db2.bin
; nop
; nop
; nop


output vkiller_patch01c8a.bin
Expand Down Expand Up @@ -124,7 +124,7 @@ write_psg:

; if the game is paused, don't write PSG ch7
; this is to prevent interference with the game paused jingle
ld a, (02280h)
ld a, (0f080h)
and 2
ret nz ; paused

Expand Down Expand Up @@ -152,69 +152,18 @@ not_register_seven:
ret

map_slots:
; map RAM into bank 0000-3fff
; returns original value of #ffff in a
; returns original slot select in b/c
ld c, 0a8h
in b, (c)
push bc
push hl
ld a, b
rlca ; replicate slot in page 3 to page 0
rlca
and 03h
ld l, a
ld a, b
and ~03h
or l
out (c), a

; SOFAROM uses these addresses for SCC patching
; to take into account that we map RAM into page 0, we need
; to change these values. this is a SOFAROM specific hack
ld (0f6ebh), a ; primary slot select (game)
ld a, (0f6eah) ; primary slot select (SCC)
or 03h
ld (0f6eah), a

; get subslot from page 3 (c000-ffff) and apply to page 0 (0000-3fff)
ld hl, 0ffffh
ld a, (hl)
cpl
push af
ld b, a
and 011000000b
rlca
rlca
ld c, a
ld a, b
and 011111100b
or c
ld (hl), a

; map music data using konami SCC mapper
ld a, 17
ld (09000h), a
ld a, 18
ld (0b000h), a

ld a, 1
out (0fch), a

pop af
pop hl
pop bc
ret

music_start:
di

call map_slots

push bc
push hl
push af

; interpret the command
ld a, e
cp 0xfa ; 0xfa and higher = commands: fade out, pause, etc.
Expand All @@ -234,9 +183,9 @@ music_stop:
; clear music player state
push bc
push de
ld hl, 02000h
ld de, 02001h
ld bc, 00300h
ld hl, 0ee00h
ld de, 0ee01h
ld bc, 00280h
ld (hl), 0
ldir
pop de
Expand All @@ -256,18 +205,10 @@ music_start_command:
music_start_call:
push bc
call 06003h ; nemesis 3 song start function
call 06180h ; initialize some state which fixes boss music cutting out
pop bc

music_start_skip:

pop af
ld (0ffffh), a
pop hl
pop bc

; restore BIOS ROM
out (c), b

di
ld a, 14
ld (09000h), a
Expand All @@ -288,21 +229,12 @@ music_update:

call map_slots

push bc
push af

call 06006h ; nemesis 3 song update function

pop af
ld (0ffffh), a

; set a flag which vkiller uses to know whether music is playing
ld a,(020c0h)
ld a,(0eec0h)
ld (0c0a7h), a

; restore ROM
pop bc
out (c), b
ram_not_initialised:
ld a, 14
ld (09000h), a
Expand Down

0 comments on commit 5e73667

Please sign in to comment.