aboutsummaryrefslogtreecommitdiff
path: root/src-z80
diff options
context:
space:
mode:
authorsik2018-01-22 19:19:19 -0300
committersik2018-01-22 19:19:19 -0300
commit8fdf49b8e53fd3063ccc2eb51c49c3b6e4d073bb (patch)
treeaddb91518f99d4df76986d3e282e41cd6baf077e /src-z80
parenta2f67fbe8fe6b27f661e70ce2b6b75c17cd1fe54 (diff)
Echo 1.6 release... kind of a mess, will clean up in further commits I guess
Diffstat (limited to 'src-z80')
-rw-r--r--src-z80/core/bgm.z803
-rw-r--r--src-z80/core/main.z8017
-rw-r--r--src-z80/core/sfx.z802
-rw-r--r--src-z80/core/vars.z803
-rw-r--r--src-z80/player/fm.z8060
-rw-r--r--src-z80/player/freq.z806
-rw-r--r--src-z80/player/pcm (copia).z80236
-rw-r--r--src-z80/player/psg.z80130
8 files changed, 421 insertions, 36 deletions
diff --git a/src-z80/core/bgm.z80 b/src-z80/core/bgm.z80
index b48d87a..c043616 100644
--- a/src-z80/core/bgm.z80
+++ b/src-z80/core/bgm.z80
@@ -376,10 +376,11 @@ ClearBGM:
ld a, b ; Reset panning
and $04
+ rrca
ld iyl, a
ld a, b
and $03
- add $B4
+ add a, $B4
ld (iy+0), a
ld (iy+1), $C0
diff --git a/src-z80/core/main.z80 b/src-z80/core/main.z80
index 387b879..1de8930 100644
--- a/src-z80/core/main.z80
+++ b/src-z80/core/main.z80
@@ -20,6 +20,11 @@ EntryPoint:
ld (RAM_PSGData+16), a
ld (RAM_PSGData+32), a
ld (RAM_PSGData+48), a
+ dec a
+ ld (RAM_PSGData+11), a
+ ld (RAM_PSGData+11+16), a
+ ld (RAM_PSGData+11+32), a
+ ld (RAM_PSGData+11+48), a
ld hl, $6000 ; Set default bank
ld (hl), l
@@ -114,6 +119,8 @@ RunCommand:
jp z, SetPCMRate
dec a ; Command $08: pause BGM
jp z, PauseBGM
+ dec a ; Command $09: set stereo
+ jp z, SetStereo
PollPCM
@@ -207,17 +214,11 @@ DoTick_PSGSkip:
;****************************************************************************
; LoadList [command $01]
; Loads the pointer list
+;----------------------------------------------------------------------------
+; notes: doesn't return
;****************************************************************************
LoadList:
-; ld hl, RAM_ComBank ; Get command parameters
-; ld c, (hl)
-; inc l
-; ld e, (hl)
-; inc l
-; ld d, (hl)
-; ex de, hl
-
ld hl, (RAM_ComAddr) ; Get command parameters
ld a, (RAM_ComBank)
ld c, a
diff --git a/src-z80/core/sfx.z80 b/src-z80/core/sfx.z80
index 8c5e7dd..2430b74 100644
--- a/src-z80/core/sfx.z80
+++ b/src-z80/core/sfx.z80
@@ -281,6 +281,8 @@ ClearSFX:
PollPCM
dec b ; Restore FM channel
+ ld a, b
+ call KillFM
call RestoreFM
inc b
diff --git a/src-z80/core/vars.z80 b/src-z80/core/vars.z80
index 79e4a1d..321d552 100644
--- a/src-z80/core/vars.z80
+++ b/src-z80/core/vars.z80
@@ -9,7 +9,7 @@ RAM_PSGData: ds 4*16 ; PSG envelope data
; ds 3 ... Current address
; ds 3 ... Looping address
; ds 3 ... Start address
- ; ds 1 ... Padding
+ ; ds 1 ... Semitone ($FF if void)
; ds 3 ... BGM instrument address
; ds 1 ... BGM channel volume
@@ -45,6 +45,7 @@ RAM_SFXAddress: ds 2 ; Current SFX address
RAM_SFXLoopPoint: ds 3 ; SFX loop point
RAM_Paused: ds 1 ; Set if BGM stream is paused
+RAM_Mono: ds 1 ; Set if panning is disabled
RAM_PCMBank1: db 1 ; (not implemented yet)
RAM_PCMAddr1: dw 1 ; (not implemented yet)
diff --git a/src-z80/player/fm.z80 b/src-z80/player/fm.z80
index d5d49ba..8afd0e7 100644
--- a/src-z80/player/fm.z80
+++ b/src-z80/player/fm.z80
@@ -49,8 +49,9 @@ NoteOnFM:
PollPCM
call GetParam ; Get note
PollPCM
-
ex af, af'
+
+SetFMSemitone:
push de
push hl
@@ -175,8 +176,8 @@ SetNoteFMBGM:
jp ProcessBGMRun ; End of subroutine
SetNoteFM:
- push af
ld b, a
+ ex af, af'
PollPCM
ld a, b ; Determine which port to write
@@ -188,7 +189,11 @@ SetNoteFM:
call GetParam ; Get high byte
PollPCM
- pop af
+ ld a, b ; Is it a semitone?
+ add a, a
+ jp c, .freqtone
+
+ ex af, af'
push de
and $07
@@ -217,6 +222,14 @@ SetNoteFM:
pop de
ret ; End of subroutine
+;----------------------------------------------------------------------------
+
+.freqtone:
+ inc a
+ ld b, a
+ ex af, af'
+ jp SetFMSemitone
+
;****************************************************************************
; LoadFM* [events $40~$47]
; Loads a FM instrument
@@ -678,6 +691,16 @@ SetFMParamSFX:
PollPCM
call GetParam ; Get parameters
PollPCM
+
+ ld a, (RAM_Mono) ; Is stereo disabled? (always turn on both
+ or a ; speakers in that case)
+ jr z, .sfxpanok
+ ld a, b
+ or $C0
+ ld b, a
+ PollPCM
+.sfxpanok:
+
ex af, af'
and $03 ; Get channel ID
@@ -701,6 +724,16 @@ SetFMParamBGM:
PollPCM
call GetParam ; Get parameters
PollPCM
+
+ ld a, (RAM_Mono) ; Is stereo disabled? (always turn on both
+ or a ; speakers in that case)
+ jr z, .bgmpanok
+ ld a, b
+ or $C0
+ ld b, a
+ PollPCM
+.bgmpanok:
+
ex af, af'
push hl
@@ -880,6 +913,14 @@ KillFM:
dec c
jp nz, .loaddummy
+ ld e, 0 ; Make the pitch so low it's unherable
+ add 4 ; because the above is STILL not enough
+ ld (iy+0), a ; sometimes. If you ever notice a very low
+ ld (iy+1), e ; pitch waveform... this is why
+ sub 4
+ ld (iy+0), a
+ ld (iy+1), e
+
pop hl
pop de
PollPCM
@@ -941,3 +982,16 @@ RestoreFM:
PollPCM
ret ; End of subroutine
+
+;****************************************************************************
+; SetStereo [command $09]
+; Toggles whether stereo is enabled or not.
+;----------------------------------------------------------------------------
+; notes: doesn't return
+;****************************************************************************
+
+SetStereo:
+ ld a, (RAM_ComBank) ; Just copy the argument as-is
+ ld (RAM_Mono), a
+
+ jp EndOfCommand ; End of subroutine
diff --git a/src-z80/player/freq.z80 b/src-z80/player/freq.z80
index 7f963e5..6aae77b 100644
--- a/src-z80/player/freq.z80
+++ b/src-z80/player/freq.z80
@@ -94,9 +94,9 @@ FMFreqTable:
;****************************************************************************
PSGShiftTable:
- db 0
- db 2, 4, 6, 8, 10, 12
- db -2, -4, -6, -8, -10, -12
+ db 0*2 ; $0x
+ db 1*2, 2*2, 3*2, 4*2, 6*2, 8*2, 12*2 ; $1x..$7x
+ db -1*2, -2*2, -3*2, -4*2, -6*2, -8*2, -12*2 ; $8x..$Ex
;****************************************************************************
; DummyFMInstr
diff --git a/src-z80/player/pcm (copia).z80 b/src-z80/player/pcm (copia).z80
new file mode 100644
index 0000000..ae7b34a
--- /dev/null
+++ b/src-z80/player/pcm (copia).z80
@@ -0,0 +1,236 @@
+;****************************************************************************
+; UpdatePCM
+; Updates PCM output upon a timer event
+;****************************************************************************
+
+UpdatePCM:
+ ret ; $C9 = RET = no PCM playback
+ ; $D0 = RET NC = PCM playback
+
+ exx ; Switch to PCM registers
+
+.doagain:
+ ld (ix+0), $27 ; Acknowledge timer
+ ld (ix+1), $1F
+
+ ld a, (hl) ; Fetch next sample
+ inc a ; Check if it's the end of the waveform
+ jr z, .stop
+ ld (ix+0), $2A ; Nope, send sample to YM2612
+ ld (ix+1), a
+
+ inc l ; Update buffer position
+ jr z, .reload ; Need to buffer more?
+
+.nopcm:
+ exx ; Switch to normal registers
+ ret ; End of subroutine
+
+.stop:
+ ld a, $C9 ; Stop playback
+ ld (UpdatePCM), a
+ ld (ix+0), $2A ; Turn off DAC
+ ld (ix+1), $80
+ ld (ix+0), $2B
+ ld (ix+1), $00
+ exx ; Switch to normal registers
+ ret ; End of subroutine
+
+.reload:
+ ld a, (RAM_LastBank) ; Bank switch if needed
+ cp c
+ jp z, .noswitchu
+ ld a, c
+ ld (RAM_LastBank), a
+ ld hl, $6000
+ BankSwitch
+.noswitchu:
+
+ ld hl, RAM_PCMBuffer ; Load samples into the buffer
+ ld a, c
+ ex de, hl
+
+ ldi
+ ldi
+ ldi
+ ldi
+
+ ldi
+ ldi
+ ldi
+ ldi
+
+ ldi
+ ldi
+ ldi
+ ldi
+
+ ldi
+ ldi
+ ldi
+ ldi
+
+ ex de, hl
+ ld c, a
+
+ ld a, e
+ or a
+ jp nz, .nobankchg ; Update high bytes of address if needed
+ inc d
+ jp nz, .nobankchg
+ ld d, $80
+ inc c
+.nobankchg:
+
+ ld l, RAM_PCMBuffer&$FF ; Go back to the beginning of the buffer
+ jp .doagain ; We took so long we should play the next
+ ; sample already ._.'
+
+;****************************************************************************
+; PlayPCM* [event $0C]
+; Plays a PCM sample
+;----------------------------------------------------------------------------
+; input c .... current bank
+; input hl ... current address
+;----------------------------------------------------------------------------
+; breaks: af, b
+;****************************************************************************
+
+PlayPCMSFX:
+ call PlayPCM ; We're just a wrapper
+ jp ProcessSFXRun ; End of subroutine
+
+PlayPCMBGM:
+ PollPCM
+
+ ld a, (RAM_Locked+6) ; Check if channel is free
+ or a
+ jp nz, ProcessBGMSkip1 ; Don't play sample if locked
+
+ call PlayPCM ; We're just a wrapper
+ jp ProcessBGMRun ; End of subroutine
+
+PlayPCM:
+ ld a, (RAM_GlobalVol+$0C) ; Are we allowed to play PCM?
+ or a
+ ret z
+
+ call GetParam ; Get sample ID
+
+ ld a, b
+ exx ; We'll modify PCM data now
+
+ ld h, RAM_PointerList>>8 ; Get offset in pointer list
+ ld l, a
+
+ ld d, (hl) ; Get PCM address
+ inc h
+ ld e, (hl)
+ inc h
+ ld c, (hl)
+
+ ld hl, $6000 ; Initial bank switch
+ ld a, c
+ ld (RAM_LastBank), a
+ BankSwitch
+
+ ld h, RAM_PCMBuffer>>8 ; Set buffer where the sample starts
+ ld a, e
+ or $F0
+ ld l, a
+
+ ld b, l
+.load1st: ; Copy initial samples into the buffer
+ ld a, (de)
+ ld (hl), a
+ inc e
+ inc l
+ jp nz, .load1st
+ ld l, b
+
+ ld a, e ; Check if the sample should skip ahead
+ or a ; already
+ jp nz, .noskip1st
+ inc d
+ jp nz, .noskip1st
+ ld d, $80
+ inc c
+.noskip1st:
+
+ exx ; Back to standard registers
+ ld a, $D0 ; Enable PCM playback
+ ld (UpdatePCM), a
+
+ ld (ix+0), $2B ; Turn on DAC
+ ld (ix+1), $80
+ ld (ix+0), $2A
+ ld (ix+1), $80
+
+ ret ; End of subroutine
+
+;****************************************************************************
+; StopPCM*
+; Stops a PCM sample
+;****************************************************************************
+
+StopPCMSFX:
+ call StopPCM ; We're just a wrapper
+ jp ProcessSFXRun ; End of subroutine
+
+StopPCMBGM:
+ PollPCM
+
+ ld a, (RAM_Locked+6) ; Check if channel is free
+ or a
+ jp nz, ProcessBGMRun ; Don't stop sample if locked
+
+ call StopPCM ; We're just a wrapper
+ jp ProcessBGMRun ; End of subroutine
+
+StopPCM:
+ ld a, $C9 ; Stop PCM playback
+ ld (UpdatePCM), a
+
+ ld (ix+0), $2B ; Disable DAC
+ ld (ix+1), $00
+
+ ret ; End of subroutine
+
+;****************************************************************************
+; LockChannelPCM [event $EC]
+; Locks the PCM channel
+;****************************************************************************
+
+LockChannelPCM:
+ ld a, $01 ; Lock PCM channel
+ ld (RAM_Locked+6), a
+
+ call StopPCM ; Stop PCM playback
+ jp ProcessSFXRun ; End of subroutine
+
+;****************************************************************************
+; SetPCMRate [command $07]
+; Changes the sample rate of PCM
+;****************************************************************************
+
+SetPCMRate:
+ ld a, (RAM_ComBank) ; Get new rate
+ cpl
+ ld b, a
+
+ xor a ; Parsed command already
+ ld (RAM_Command), a
+
+ ld a, b ; Set high bits of timer
+ ld (ix+0), $24
+ rrca
+ rrca
+ or $C0
+ ld (ix+1), a
+
+ ld a, b ; Set low bits of timer
+ ld (ix+0), $25
+ and $03
+ ld (ix+1), a
+
+ jp IdleLoop ; End of subroutine
diff --git a/src-z80/player/psg.z80 b/src-z80/player/psg.z80
index 6ddaae7..892931a 100644
--- a/src-z80/player/psg.z80
+++ b/src-z80/player/psg.z80
@@ -8,10 +8,10 @@ UpdatePSG:
ld b, 3 ; Go through all channels
.loop:
push bc
+ xor a
+ ld iyl, a
ld a, (hl) ; Get channel volume
-; bit 7, a
-; jr nz, .noskip
or a
jp m, .noskip
ld b, $0F
@@ -74,7 +74,7 @@ UpdatePSG:
.skip:
PollPCM
-
+
ld a, b ; Set PSG channel volume
rlca
rlca
@@ -86,6 +86,63 @@ UpdatePSG:
rrca
or $90
ld ($7F11), a
+
+ PollPCM
+ push bc
+
+ ld a, l ; Get current semitone
+ add 11-1
+ ld l, a
+ ld b, (hl)
+ sub 11-1
+ ld l, a
+
+ ld a, b ; Oh, don't tocuh it?
+ inc a
+ jr z, .notone
+
+ PollPCM
+
+ db $FD,$7D ; ld a, iyl ; Get semitone shift
+ and $F0
+ rrca
+ rrca
+ rrca
+ rrca
+ ex de, hl
+ ld h, PSGShiftTable>>8
+ add PSGShiftTable&$FF
+ ld l, a
+ ld c, (hl)
+ ex de, hl
+
+ PollPCM
+
+ ld a, b ; Compute resulting semitone
+ add c
+
+ ex de, hl ; Get corresponding frequency
+ ld h, PSGFreqTable>>8
+ ld l, a
+ ld c, (hl)
+ inc l
+ ld b, (hl)
+
+ PollPCM
+
+ ld a, e ; Get PSG channel
+ and $30
+ add a
+ or c
+
+ ld hl, $7F11 ; Set new frequency
+ ld (hl), a
+ ld (hl), b
+ ex de, hl
+
+ PollPCM
+.notone:
+ pop bc
ld a, l ; Go for next channel
sub 16+1
@@ -200,31 +257,22 @@ NoteOnPSG:
ld a, (de)
ld (hl), a
+ ld a, e
pop de
pop hl
+ ex af, af'
PollPCM
call GetParam ; Get note
PollPCM
-
- ;pop af
ex af, af'
- push hl
- push de
- ld h, PSGFreqTable>>8 ; Get address of frequency data
- ld l, b
- ld de, $7F11
- rrca ; Set new frequency
- rrca
- rrca
- ld b, (hl)
- or b
- ld (de), a
- inc l
- ld a, (hl)
- ld (de), a
- pop de
+SetSemitonePSG:
+ push hl ; Store new semitone
+ inc a
+ ld h, RAM_PSGData>>8
+ ld l, a
+ ld (hl), b
pop hl
ret ; End of subroutine
@@ -336,6 +384,14 @@ NoteOffPSG:
ld a, (hl)
and $7F
ld (hl), a
+
+ PollPCM
+
+ ld a, l ; Don't waste time with semitone shifting
+ add 11
+ ld l, a
+ ld a, $FF
+ ld (hl), a
pop hl
ret ; End of subroutine
@@ -595,6 +651,27 @@ SetNotePSG:
PollPCM
call GetParam ; Get first byte
PollPCM
+
+ ld a, b ; Select by semitone?
+ add a, a
+ jp c, .freqtone
+ ex af, af'
+
+ push hl ; Mark semitone as not valid
+ ld l, a
+ ex af, af'
+ PollPCM
+ ld a, l
+ rrca
+ rrca
+ rrca
+ rrca
+ add a, 11
+ ld l, a
+ ld h, RAM_PSGData>>8
+ ld (hl), $FF
+ pop hl
+ PollPCM
ex af, af'
push de ; PSG port address
@@ -618,6 +695,19 @@ SetNotePSG:
ret ; End of subroutine
+;----------------------------------------------------------------------------
+
+.freqtone:
+ ld b, a
+ PollPCM
+ ex af, af'
+ rrca
+ rrca
+ rrca
+ rrca
+ add 10
+ jp SetSemitonePSG
+
;****************************************************************************
; SetNoteNoise*
; Sets the note of the noise PSG channel without "note on"