diff options
| author | Javier Degirolmo | 2012-04-29 15:57:47 -0300 |
|---|---|---|
| committer | Javier Degirolmo | 2012-04-29 15:57:47 -0300 |
| commit | 2902fc7a532edff250460bfbd8e7a31eedaa980b (patch) | |
| tree | 6b5251e29551271c633cad21c87dbfea666295ca /src-z80 | |
| parent | 49bde702d51519e676389e9445b2acdde42c3841 (diff) | |
FM loader code optimized (Oerg's work), also some FM-related bugfixes around
Diffstat (limited to 'src-z80')
| -rw-r--r-- | src-z80/core/bgm.z80 | 27 | ||||
| -rw-r--r-- | src-z80/core/sfx.z80 | 34 | ||||
| -rw-r--r-- | src-z80/player/fm (copia).z80 | 837 | ||||
| -rw-r--r-- | src-z80/player/fm.z80 | 106 |
4 files changed, 880 insertions, 124 deletions
diff --git a/src-z80/core/bgm.z80 b/src-z80/core/bgm.z80 index ea245a1..e5d9892 100644 --- a/src-z80/core/bgm.z80 +++ b/src-z80/core/bgm.z80 @@ -241,26 +241,45 @@ ClearBGM: .resetfm: PollPCM - ;xor a ; Reset BGM volume - ld a, $7F + ld a, $7F ; Reset BGM volume ld (de), a dec e + PollPCM + ld a, (hl) ; Kill FM channel if not locked or a jp nz, .nofmkill + dec b + + ld a, b + call KillFM PollPCM + ld a, b ; Reset panning + and $04 + ld iyl, a ld a, b - dec a - call KillFM + and $03 + add $B4 + ld (iy+0), a + ld (iy+1), $C0 + inc b .nofmkill: dec l djnz .resetfm ;---------------------------------------------------------------------------- + + ld hl, RAM_BGMFMPan ; Reset panning status (for restoring) + ld a, $C0 + ld b, 8 +.initpanstat: + ld (hl), a + inc l + djnz .initpanstat ret ; End of subroutine diff --git a/src-z80/core/sfx.z80 b/src-z80/core/sfx.z80 index 6eb844d..0e140e8 100644 --- a/src-z80/core/sfx.z80 +++ b/src-z80/core/sfx.z80 @@ -262,21 +262,9 @@ ClearSFX: xor a ld (de), a - dec b ; Mute FM channel - ld (ix+0), $28 - ld (ix+1), b - PollPCM - ld a, b - and $04 ; Determine which port to write - rrca - ld iyl, a - - ld a, b ; Kill ADSR - call KillFM - - PollPCM + dec b ld a, b ; Restore BGM FM instrument ld h, RAM_BGMFMInstr>>8 @@ -292,31 +280,23 @@ ClearSFX: PollPCM push bc - ld a, b ; Restore BGM FM volume - add RAM_BGMFMVol&$FF + ld a, l ; Restore BGM FM volume + add 8 ld l, a ld a, b ld b, (hl) call SetFMVolLoad pop bc - ld a, b - and $04 - rrca - ld iyl, a - - push bc ; Restore BGM FM panning - ld a, b - ld h, RAM_BGMFMPan>>8 - add RAM_BGMFMPan&$FF + ld a, l ; Restore BGM FM panning + add 8 ld l, a ld a, b - ld b, (hl) and $03 add $B4 - ld (iy+0), b + ld (iy+0), a + ld a, (hl) ld (iy+1), a - pop bc PollPCM inc b diff --git a/src-z80/player/fm (copia).z80 b/src-z80/player/fm (copia).z80 new file mode 100644 index 0000000..4c0b565 --- /dev/null +++ b/src-z80/player/fm (copia).z80 @@ -0,0 +1,837 @@ +;**************************************************************************** +; NoteOnFM +; Does a "note on" for a FM channel +;**************************************************************************** + +NoteOnFMSFX: + call NoteOnFM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +NoteOnFMBGM: + ld b, a + PollPCM + + push hl + ld a, b + and $07 ; Check if channel is free + ld hl, RAM_Locked + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip1 ; Don't play if locked + + ld a, b + call NoteOnFM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +NoteOnFM: + and $07 ; Get channel ID + ld (ix+0), $28 ; Note off + ld (ix+1), a + + ld b, a + ex af, af' + PollPCM + + ld a, b ; Determine which port to write + and $04 + rrca + ld iyl, a + + PollPCM + call GetParam ; Get note + PollPCM + + ex af, af' + push de + push hl + + ld d, a + and $03 ; Index of first frequency register + add $A4 + ld e, a + + PollPCM + + ld h, FMFreqTable>>8 ; Get address of note + ld a, b + and $1F + add FMFreqTable&$FF + ld l, a + + PollPCM + + ld a, b ; Set new frequency + and $E0 + rrca + rrca + ld b, a + ld a, (hl) + or b + ld (iy+0), e + ld (iy+1), a + + PollPCM + + ld a, e + sub 4 + ld e, a + dec l + ld a, (hl) + ld (iy+0), e + ld (iy+1), a + + PollPCM + + ld a, d ; Note on! + or $F0 + ld (ix+0), $28 + ld (ix+1), a + + pop hl + pop de + ret ; End of subroutine + +;**************************************************************************** +; NoteOffFM +; Does a "note off" for a FM channel +;**************************************************************************** + +NoteOffFMSFX: + call NoteOffFM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +NoteOffFMBGM: + ld b, a + PollPCM + ld a, b + + push hl + and $07 ; Check if channel is free + ld hl, RAM_Locked + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip ; Don't stop if locked + + ld a, b + call NoteOffFM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +NoteOffFM: + and $07 ; Get channel ID + ld (ix+0), $28 ; Note off + ld (ix+1), a + ret ; End of subroutine + +;**************************************************************************** +; SetFMNote* +; Sets the note of a FM channel without "note on" +;**************************************************************************** + +SetNoteFMSFX: + call SetNoteFM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +SetNoteFMBGM: + ld b, a + PollPCM + ld a, b + + push hl + and $07 ; Check if channel is free + ld hl, RAM_Locked + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip2 ; Don't change if locked + + ld a, b + call SetNoteFM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +SetNoteFM: + push af + ld b, a + PollPCM + + ld a, b ; Determine which port to write + and $04 + rrca + ld iyl, a + + PollPCM + call GetParam ; Get high byte + PollPCM + + pop af + push de + + and $07 + ld d, a + and $03 ; Index of first frequency register + add $A4 + ld e, a + + PollPCM + + ld (iy+0), e ; Load high byte + ld (iy+1), b + + PollPCM ; Load low byte + call GetParam + PollPCM + + ld a, e + sub 4 + ld e, a + + ld (iy+0), e + ld (iy+1), b + + PollPCM + pop de + ret ; End of subroutine + +;**************************************************************************** +; LoadFM* +; Loads a FM instrument +;**************************************************************************** + +LoadFMSFX: + call LoadFMEvent ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +LoadFMBGM: + and $07 ; Get channel ID + ld b, a + PollPCM + + push de + push bc + ld a, b + ld de, RAM_BGMFMInstr ; Store instrument ID + add e + ld e, a + PollPCM + call GetParam + PollPCM + ld a, b + ld (de), a + + ld a, e ; Reset volume + add 8 + ld e, a + xor a + ld (de), a + + ld e, c + pop bc + ld c, e + pop de + + PollPCM + + push hl ; Check if channel is free + ld a, b + ld h, RAM_Locked>>8 + add RAM_Locked&$FF + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip ; Don't load if locked + + PollPCM + + ld a, b ; Get back instrument ID + push hl + ld hl, RAM_BGMFMInstr + add l + ld l, a + ld b, (hl) + pop hl + + ex af, af' + PollPCM + ex af, af' + + call LoadFMDirect ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +LoadFMEvent: + and $07 ; Get channel ID + + ex af, af' + PollPCM + call GetParam ; Get instrument ID + PollPCM + ex af, af' +LoadFMDirect: + + push af + and $04 ; Determine which port to write + rrca + ld iyl, a + PollPCM + pop af + + push bc + push de + push hl + + ld h, RAM_PointerList>>8 ; Get instrument address + ld l, b + ld d, (hl) + inc h + ld e, (hl) + inc h + ld c, (hl) + ex de, hl + + push af + PollPCM + + ld b, 28/4 ; Load FM instrument into our scratch buffer, + ld de, RAM_Scratch ; so we don't conflict with PCM bank +.getinstr: ; switch (which would slow down A LOT) + ld a, b + ex af, af' + call GetParam + ex de, hl + ld (hl), b + ex de, hl + inc e + call GetParam + ex de, hl + ld (hl), b + ex de, hl + inc e + call GetParam + ex de, hl + ld (hl), b + ex de, hl + inc e + call GetParam + ex de, hl + ld (hl), b + ex de, hl + inc e + ex af, af' + ld b, a + djnz .getinstr + call GetParam + ex de, hl + ld (hl), b + ex de, hl + + PollPCM + + pop af ; Kill ADSR + ld b, a + call KillFM + ld a, b + + ld de, RAM_FMData ; Get address of FM data + and $07 + add e + ld e, a + + push af + and $03 ; Register index for operator + add $B0 + + ld hl, RAM_Scratch ; Get address of buffer with the instrument + ; data + ex af, af' + PollPCM ; Write operator + ex af, af' + ld (iy+0), a + ld b, (hl) + inc l + ld (iy+1), b + + ex af, af' ; Store $B0 register in FM data buffer + ld a, b + ld (de), a + ld a, e + add 8 + ld e, a + PollPCM + ex af, af' + + sub $B0-$30 + + ex af, af' ; Write registers $30-$3C + PollPCM + ex af, af' + + ld (iy+0), a + ld b, (hl) + nop + ld (iy+1), b + add 4 + inc l + nop + + ld (iy+0), a + ld b, (hl) + nop + ld (iy+1), b + add 4 + inc l + nop + + ld (iy+0), a + ld b, (hl) + nop + ld (iy+1), b + add 4 + inc l + nop + + ld (iy+0), a + ld b, (hl) + nop + ld (iy+1), b + add 4 + inc l + nop + + ld b, 4 ; Write registers $40-$4C +.reg40: + ld c, a + push af + PollPCM + + ld (iy+0), c + ld a, (hl) + ld (de), a + ld (iy+1), a + ld a, e + add 8 + ld e, a + + pop af + add 4 + inc l + djnz .reg40 + + ld b, 20/4 ; Write registers $50-$5C +.reg50: + ex af, af' + PollPCM + ex af, af' + + ld (iy+0), a + ld c, (hl) + nop + ld (iy+1), c + add 4 + inc l + nop + + ld (iy+0), a + ld c, (hl) + nop + ld (iy+1), c + add 4 + inc l + nop + + ld (iy+0), a + ld c, (hl) + nop + ld (iy+1), c + add 4 + inc l + nop + + ld (iy+0), a + ld c, (hl) + nop + ld (iy+1), c + add 4 + inc l + + djnz .reg50 + + PollPCM + + ex de, hl + ld a, l + sub 8*6 + ld l, a + ld b, (hl) + add 8 + ld l, a + + PollPCM + + pop af + pop hl + pop de + pop bc + ret + +;**************************************************************************** +; SetFMVol* +; Sets the volume of a FM channel +;**************************************************************************** + +SetFMVolSFX: + call SetFMVolSFXEvent ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +SetFMVolBGM: + and $07 + ld b, a + + PollPCM + + push de + push bc + ld a, b + ld d, RAM_BGMFMVol>>8 ; Store BGM volume + add RAM_BGMFMVol&$FF + ld e, a + PollPCM + call GetParam + PollPCM + ex de, hl + ld (hl), b + ex de, hl + ld e, c + pop bc + ld c, e + pop de + + PollPCM + + push hl + ld a, b ; Check if channel is free + ld hl, RAM_Locked + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip ; Don't change if locked + + PollPCM + + ld a, b + push hl + ld hl, RAM_BGMFMVol + add l + ld l, a + ld b, (hl) + pop hl + + push af + PollPCM + pop af + + call SetFMVolLoad ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +SetFMVolSFXEvent: + push af + PollPCM + call GetParam ; Get new volume + PollPCM + pop af + +SetFMVolLoad: + push bc + push de + push hl + + and $07 + + push af + ld h, RAM_FMData>>8 ; Get address of FM data + add RAM_FMData&$FF + ld l, a + + ex af, af' + PollPCM + ex af, af' + + and $04 ; Determine which port to write + rrca + ld iyl, a + PollPCM + pop af + + and $03 ; Index of first volume register + add $40 + ld c, a + + ld a, (hl) ; Get algorithm + and $07 + ld e, a + + PollPCM + + ld a, l + add 8 + ld l, a + ld a, e ; Process operator #1 + cp $07 + jr c, .noop1 + ld (iy+0), c + ld a, (hl) + add b + cp $7F + jr c, .notooloud1 + ld a, $7F +.notooloud1: + ld (iy+1), a +.noop1: + ld a, c + add 4 + ld c, a + + PollPCM + + ld a, l + add 8 + ld l, a + ld a, e ; Process operator #2 + cp $05 + jr c, .noop2 + ld (iy+0), c + ld a, (hl) + add b + cp $7F + jr c, .notooloud2 + ld a, $7F +.notooloud2: + ld (iy+1), a +.noop2: + ld a, c + add 4 + ld c, a + + PollPCM + + ld a, l + add 8 + ld l, a + ld a, e ; Process operator #3 + cp $04 + jr c, .noop3 + ld (iy+0), c + ld a, (hl) + add b + cp $7F + jr c, .notooloud3 + ld a, $7F +.notooloud3: + ld (iy+1), a +.noop3: + ld a, c + add 4 + ld c, a + + PollPCM + + ld a, l + add 8 + ld l, a + ld (iy+0), c + ld a, (hl) ; Process operator #4 + add b + cp $7F + jr c, .notooloud4 + ld a, $7F +.notooloud4: + ld (iy+1), a + + PollPCM + + pop hl + pop de + pop bc + ret ; End of subroutine + +;**************************************************************************** +; SetFMParam* +; Sets the different parameters of a FM channel +;**************************************************************************** + +SetFMParamSFX: + ld b, a + PollPCM + + ld a, b ; Determine which port to write + and $04 + rrca + ld iyl, a + + ld a, b + ex af, af' + PollPCM + call GetParam ; Get parameters + PollPCM + ex af, af' + + and $03 ; Get channel ID + add $B4 + ld (iy+0), a ; Set new parameters + ld (iy+1), b + + jp ProcessSFXRun ; End of subroutine + +SetFMParamBGM: + ld b, a + PollPCM + ld a, b + + ld a, b ; Determine which port to write + and $04 + rrca + ld iyl, a + + ex af, af' + PollPCM + call GetParam ; Get parameters + PollPCM + ex af, af' + + push hl + and $07 ; Store parameters + ld h, RAM_BGMFMPan>>8 + add RAM_BGMFMPan&$FF + ld l, h + ld (hl), b + + ex af, af' + PollPCM + ex af, af' + + and $07 ; Check if channel is free + add RAM_Locked&$FF + ld l, a + ex af, af' + ld a, (hl) + or a + pop hl + jp nz, ProcessBGMRun ; Don't modify if locked + + PollPCM + ex af, af' + + and $03 ; Get channel ID + add $B4 + ld (iy+0), a ; Set new parameters + ld (iy+1), b + + jp ProcessBGMRun ; End of subroutine + +;**************************************************************************** +; LockChannelFM [events $E0-$E7] +; Locks a FM channel +;**************************************************************************** + +LockChannelFM: + and $07 + ld b, a + PollPCM + + push hl + ld h, RAM_Locked>>8 ; Get address of channel to lock + ld a, b + add RAM_Locked&$FF + ld l, a + ld (hl), $01 ; Lock channel + pop hl + + PollPCM + + ld a, b ; Determine which port to write + and $04 + rrca + ld iyl, a + + ld a, b ; Reset FM parameters + and $03 + add a + add a + add $B4 + ld (iy+0), a + ld (iy+1), $C0 + + jp ProcessSFXRun ; End of subroutine + +;**************************************************************************** +; KillFM +; Kills a FM channel +;**************************************************************************** + +KillFM: + and $07 ; Get channel ID + + push af + push de + push hl + + ld c, a ; Determine to which port to write + and $04 + rrca + ld iyl, a + ld a, c + + and $03 ; Load dummy FM instrument + add $40 + ld c, 6 + ld hl, DummyFMInstr +.loaddummy: + ex af, af' + PollPCM + ex af, af' + ld e, (hl) + + ld (iy+0), a + add 4 + ld (iy+1), e + nop + ld (iy+0), a + add 4 + ld (iy+1), e + nop + ld (iy+0), a + add 4 + ld (iy+1), e + nop + ld (iy+0), a + add 4 + ld (iy+1), e + + inc l + dec c + jp nz, .loaddummy + + pop hl + pop de + PollPCM + pop af + + ld c, a ; Cause the ADSR to reset + or $F0 + ld (ix+0), $28 + ld (ix+1), c + ld (ix+0), $28 + ld (ix+1), a + ld (ix+0), $28 + ld (ix+1), c + + PollPCM + ret ; End of subroutine diff --git a/src-z80/player/fm.z80 b/src-z80/player/fm.z80 index 4c0b565..ddfef66 100644 --- a/src-z80/player/fm.z80 +++ b/src-z80/player/fm.z80 @@ -367,110 +367,30 @@ LoadFMDirect: ex af, af' sub $B0-$30 - - ex af, af' ; Write registers $30-$3C - PollPCM - ex af, af' - - ld (iy+0), a - ld b, (hl) - nop - ld (iy+1), b - add 4 - inc l - nop + ld b, 7*4 ; Load operator registers into the YM2612 +.loadfmloop: ld (iy+0), a - ld b, (hl) - nop - ld (iy+1), b - add 4 - inc l - nop - - ld (iy+0), a - ld b, (hl) - nop - ld (iy+1), b + ld c, (hl) + ld (iy+1), c add 4 inc l - nop + djnz .loadfmloop - ld (iy+0), a - ld b, (hl) - nop - ld (iy+1), b - add 4 - inc l - nop - - ld b, 4 ; Write registers $40-$4C -.reg40: - ld c, a - push af PollPCM - ld (iy+0), c + ld a, l ; Store operator TLs (needed to set the + sub 24 ; volume properly when it changes) + ld l, a + ld b, 4 +.loadfmsavetl: ld a, (hl) ld (de), a - ld (iy+1), a ld a, e add 8 ld e, a - - pop af - add 4 - inc l - djnz .reg40 - - ld b, 20/4 ; Write registers $50-$5C -.reg50: - ex af, af' - PollPCM - ex af, af' - - ld (iy+0), a - ld c, (hl) - nop - ld (iy+1), c - add 4 - inc l - nop - - ld (iy+0), a - ld c, (hl) - nop - ld (iy+1), c - add 4 - inc l - nop - - ld (iy+0), a - ld c, (hl) - nop - ld (iy+1), c - add 4 - inc l - nop - - ld (iy+0), a - ld c, (hl) - nop - ld (iy+1), c - add 4 - inc l - - djnz .reg50 - - PollPCM - - ex de, hl - ld a, l - sub 8*6 - ld l, a - ld b, (hl) - add 8 - ld l, a + inc l + djnz .loadfmsavetl PollPCM @@ -553,7 +473,7 @@ SetFMVolLoad: push de push hl - and $07 + and $07 ; Get channel ID push af ld h, RAM_FMData>>8 ; Get address of FM data |
