Skip to content

Commit

Permalink
Refactor period limit subroutine
Browse files Browse the repository at this point in the history
Fixes #276.
  • Loading branch information
Gumball2415 committed Jul 20, 2024
1 parent bdf33eb commit 4ce047d
Show file tree
Hide file tree
Showing 12 changed files with 3,004 additions and 3,006 deletions.
33 changes: 33 additions & 0 deletions Source/drivers/asm/driver.s
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,39 @@ bit_mask: ;;; ;; ; general-purpose bit mask
.include "vibrato.s"
.endif

LIMIT_PERIOD_2A03 = $7FF
LIMIT_PERIOD_VRC6 = $FFF
; VRC7: period is between 0 to (1 << (VRC7_PITCH_RESOLUTION + 9)) - 1 or $7FF
LIMIT_PERIOD_VRC7 = LIMIT_PERIOD_2A03
LIMIT_PERIOD_N163 = $FFFF
LIMIT_PERIOD_LINEAR = (95<<5)

ft_limit_freq_lo:
.byte >LIMIT_PERIOD_2A03 ; 2A03
.byte >LIMIT_PERIOD_2A03 ; 2A03
.byte >0 ; 2A03 noise
.byte >0 ; 2A03 dpcm
.byte >LIMIT_PERIOD_VRC6 ; VRC6
.byte >LIMIT_PERIOD_VRC6 ; VRC6
.byte >LIMIT_PERIOD_2A03 ; VRC7
.byte >LIMIT_PERIOD_VRC6 ; FDS
.byte >LIMIT_PERIOD_2A03 ; MMC5
.byte >LIMIT_PERIOD_N163 ; N163
.byte >LIMIT_PERIOD_VRC6 ; S5B
ft_limit_freq_hi:
.byte <LIMIT_PERIOD_2A03 ; 2A03
.byte <LIMIT_PERIOD_2A03 ; 2A03
.byte <0 ; 2A03 noise
.byte <0 ; 2A03 dpcm
.byte <LIMIT_PERIOD_VRC6 ; VRC6
.byte <LIMIT_PERIOD_VRC6 ; VRC6
.byte <LIMIT_PERIOD_2A03 ; VRC7
.byte <LIMIT_PERIOD_VRC6 ; FDS
.byte <LIMIT_PERIOD_2A03 ; MMC5
.byte <LIMIT_PERIOD_N163 ; N163
.byte <LIMIT_PERIOD_VRC6 ; S5B


;
; An example of including music follows
;
Expand Down
76 changes: 46 additions & 30 deletions Source/drivers/asm/effects.s
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ ft_calc_period:
sta var_ch_PeriodCalcHi, x
@Skip:

; apply vibrato and tremolo
jsr ft_vibrato
jsr ft_tremolo

Expand All @@ -330,35 +331,57 @@ ft_calc_period:
beq :+
cmp #CHAN_DPCM
beq :+
; TODO: implement VRC7 linear pitch?
.if .defined(USE_VRC7)
cmp #CHAN_VRC7
beq :+
.endif
jsr ft_load_freq_table
jsr ft_linear_fetch_pitch
:
.endif ; ;; ;;;

; apply frequency multiplication
.if .defined(USE_FDS)
lda ft_channel_type, x
cmp #CHAN_FDS
bne :+
; copy unmultiplied period to FDS carrier
jsr @CopyPeriodToCarrier
:
.endif

lda var_ch_Harmonic, x
beq @MaxPeriod ; K00 results in lowest possible frequency

; K00 results in lowest possible frequency
beq @MaxPeriod

; skip calculation if it's not affecting pitch
cmp #$01
beq @SkipHarmonic ; skip calculation if it's not affecting pitch
beq @EndHarmonic

lda ft_channel_type, x
; noise does not use this
cmp #CHAN_NOI
beq @SkipHarmonic
beq @EndHarmonic

.if .defined(USE_VRC7)
; VRC7 not yet implemented
cmp #CHAN_VRC7
beq @SkipHarmonic
beq @EndHarmonic
.endif

; FDS and N163 use angular frequency
.if .defined(USE_FDS)
cmp #CHAN_FDS
beq @HarmonicMultiplyFDS
beq @HarmonicMultiply
.endif

.if .defined(USE_N163)
cmp #CHAN_N163
beq @HarmonicMultiply
.endif

@HarmonicDivide:
lda var_ch_PeriodCalcLo, x
sta ACC
Expand All @@ -369,11 +392,7 @@ ft_calc_period:
lda #$00
sta AUX + 1
jsr DIV
jmp @HarmonicEnd
.if .defined(USE_FDS)
@HarmonicMultiplyFDS:
jsr @CopyPeriodToCarrier
.endif
jmp @HarmonicEpilogue
@HarmonicMultiply:
lda var_ch_PeriodCalcLo, x
sta var_Temp16
Expand All @@ -388,30 +407,21 @@ ft_calc_period:
lda var_ch_Harmonic, x
sta var_Temp
jsr MUL
@HarmonicEnd:
@HarmonicEpilogue:
lda ACC
sta var_ch_PeriodCalcLo, x
lda ACC + 1
sta var_ch_PeriodCalcHi, x
jmp @JumpHarmonicEnd
@SkipHarmonic:
.if .defined(USE_FDS)
lda ft_channel_type, x
cmp #CHAN_FDS
bne @JumpHarmonicEnd
jsr @CopyPeriodToCarrier
.endif
@JumpHarmonicEnd:
rts
jmp @EndHarmonic

@MaxPeriod:
; no limits for noise
lda ft_channel_type, x
cmp #CHAN_NOI
beq @EndCalcPeriod
beq @EndHarmonic
.if .defined(USE_VRC7)
cmp #CHAN_VRC7
beq @EndCalcPeriod
beq @EndHarmonic
.endif
.if .defined(USE_N163)
cmp #CHAN_N163
Expand All @@ -421,19 +431,25 @@ ft_calc_period:
cmp #CHAN_FDS
beq @InvertedPeriod
.endif
; 12-bit/11-bit period
; will be handled in their respective chip handlers
lda #$FF
sta var_ch_PeriodCalcHi, x
lda #$0F
sta var_ch_PeriodCalcLo, x
jmp @EndCalcPeriod
lda #$0F
sta var_ch_PeriodCalcHi, x
jmp @EndHarmonic
@InvertedPeriod:
lda #$00
sta var_ch_PeriodCalcHi, x
sta var_ch_PeriodCalcLo, x
@EndCalcPeriod:
rts
@EndHarmonic:


; CChannelHandler::LimitRawPeriod()
jmp ft_limit_final_freq_raw
; we're done here
; in the case of CChannelHandlerVRC7::CalculatePeriod() and
; CChannelHandlerN163::CalculatePeriod(), the freq bitshifts will be applied
; in their respective chip handlers (see n163.s, vrc7.s)
; rts

.if .defined(USE_FDS)
@CopyPeriodToCarrier:
Expand Down
176 changes: 0 additions & 176 deletions Source/drivers/asm/instrument.s
Original file line number Diff line number Diff line change
Expand Up @@ -621,179 +621,3 @@ ft_load_instrument_vrc7:

ldy var_Temp ;;; ;; ;
rts

; Make sure the period doesn't exceed max or min
ft_limit_freq:

.if .defined(USE_LINEARPITCH)
; linear pitch mode has different bounds check
lda var_SongFlags
and #FLAG_LINEARPITCH
beq :+
lda ft_channel_type, x
asl
tay
lda ft_limit_linear_pointers, y
sta var_Temp16
iny
lda ft_limit_linear_pointers, y
sta var_Temp16 + 1
ldy #$00
jmp (var_Temp16)
:
.endif

; Jump to the instrument setup routine
lda ft_channel_type, x
asl ;;; ;; ;
tay
lda ft_limit_pointers, y
sta var_Temp16
iny
lda ft_limit_pointers, y
sta var_Temp16 + 1
ldy #$00
jmp (var_Temp16)


ft_limit_pointers: ;;; ;; ; 0CC: optimize this
.word ft_limit_period_2a03 ; 2A03
.word ft_limit_period_2a03 ; 2A03
.word ft_limit_period_no ; 2A03 noise
.word ft_limit_period_no ; 2A03 dpcm
.word ft_limit_period_vrc6 ; VRC6
.word ft_limit_period_vrc6 ; VRC6
.word ft_limit_period_no ; VRC7
.word ft_limit_period_vrc6 ; FDS
.word ft_limit_period_2a03 ; MMC5
.word ft_limit_period_no ; N163
.word ft_limit_period_vrc6 ;;; ;; ; S5B

ft_limit_period_no:
ft_limit_linear_period_no:
rts

; 2A03: period is between 0 to $7FF
ft_limit_period_2a03:
lda var_ch_TimerPeriodHi, x
bmi @LimitMin
cmp #$08
bcc @NoLimit
lda #$07
sta var_ch_TimerPeriodHi, x
lda #$FF
sta var_ch_TimerPeriodLo, x
@NoLimit:
rts
@LimitMin:
lda #$00
sta var_ch_TimerPeriodLo, x
sta var_ch_TimerPeriodHi, x
rts

; VRC6: period is between 0 to $FFF
ft_limit_period_vrc6:
lda var_ch_TimerPeriodHi, x
bmi @LimitMin
cmp #$10
bcc @NoLimit
lda #$0F
sta var_ch_TimerPeriodHi, x
lda #$FF
sta var_ch_TimerPeriodLo, x
@NoLimit:
rts
@LimitMin:
lda #$00
sta var_ch_TimerPeriodLo, x
sta var_ch_TimerPeriodHi, x
rts

ft_limit_linear_pointers: ;;; ;; ; 0CC: optimize this
.word ft_limit_linear_period_2a03 ; 2A03
.word ft_limit_linear_period_2a03 ; 2A03
.word ft_limit_linear_period_no ; 2A03 noise
.word ft_limit_linear_period_no ; 2A03 dpcm
.word ft_limit_linear_period_vrc6 ; VRC6
.word ft_limit_linear_period_vrc6 ; VRC6
.word ft_limit_linear_period_no ; VRC7
.word ft_limit_linear_period_vrc6 ; FDS
.word ft_limit_linear_period_2a03 ; MMC5
.word ft_limit_linear_period_no ; N163
.word ft_limit_linear_period_vrc6 ;;; ;; ; S5B

; std::min(std::max(Period, 0), (NOTE_COUNT - 1) << LINEAR_PITCH_AMOUNT);
; even though this is a virtual function,
; nothing seems to override this in linear pitch mode
ft_limit_linear_period_2a03:
ft_limit_linear_period_vrc6:
lda var_ch_TimerPeriodHi, x
bmi @LimitMin
sec
lda var_ch_TimerPeriodLo, x
sbc #<(95<<5)
lda var_ch_TimerPeriodHi, x
sbc #>(95<<5)
bcc @NoLimit
lda #>(95<<5)
sta var_ch_TimerPeriodHi, x
lda #<(95<<5)
sta var_ch_TimerPeriodLo, x
@NoLimit:
rts
@LimitMin:
lda #$00
sta var_ch_TimerPeriodLo, x
sta var_ch_TimerPeriodHi, x
rts

.if 0

lda var_ch_TimerPeriodHi, x
bmi @LimitMin ; period < 0
.if .defined(USE_VRC6)
pha ;;; ;; ;
lda ft_channel_type, x
cmp #CHAN_VRC6
beq :+
cmp #CHAN_SAW
beq :+
pla
bpl :++ ; always
: pla ; ;; ;;;
cmp #$10 ; period > $FFF
bcc @NoLimit
lda #$0F
sta var_ch_TimerPeriodHi, x
lda #$FF
sta var_ch_TimerPeriodLo, x
rts
:
.endif
.if .defined(USE_FDS)
cpx #FDS_OFFSET
bne :+
cmp #$11 ; period > $1000?
bcc @NoLimit
lda #$10
sta var_ch_TimerPeriodHi, x
lda #$FF
sta var_ch_TimerPeriodLo, x
rts
:
.endif
cmp #$08 ; period > $7FF
bcc @NoLimit
lda #$07
sta var_ch_TimerPeriodHi, x
lda #$FF
sta var_ch_TimerPeriodLo, x
@NoLimit:
rts
@LimitMin:
lda #$00
sta var_ch_TimerPeriodLo, x
sta var_ch_TimerPeriodHi, x
rts

.endif
Loading

0 comments on commit 4ce047d

Please sign in to comment.