dos33fsprogs/pt3_player/pt3_lib.s

2578 lines
57 KiB
ArmAsm
Raw Normal View History

2019-05-22 19:52:05 +00:00
;===========================================
; Library to decode Vortex Tracker PT3 files
; in 6502 assembly for Apple ][ Mockingboard
;
; by Vince Weaver <vince@deater.net>
2019-05-22 21:08:52 +00:00
; Roughly based on the Formats.pas Pascal code from Ay_Emul
2019-05-22 19:52:05 +00:00
; Size Optimization -- Mem+Code (pt3_lib_end-note_a)
; + 3407 bytes -- original working implementation
; + 3302 bytes -- autogenerate the volume tables
2019-05-22 21:08:52 +00:00
; + 3297 bytes -- remove some un-needed bytes from struct
; + 3262 bytes -- combine some duplicated code in $1X/$BX env setting
2019-05-24 00:53:41 +00:00
; + 3253 bytes -- remove unnecessary variable
; + 3203 bytes -- combine common code in note decoder
2019-06-02 04:09:49 +00:00
; + 2937 bytes -- qkumba first pass
2019-06-02 05:05:55 +00:00
; + 2879 bytes -- qkumba second pass
; + 2839 bytes -- mask note command in common code
2019-06-05 15:19:09 +00:00
; + 2832 bytes -- combine $D0 and $E0 decode
2019-06-05 15:40:06 +00:00
; + 2816 bytes -- eliminate "decode_done" variable (2.75k)
; + 2817 bytes -- eliminate pt3_version. Slighly faster but also bigger
; + 2828 bytes -- fix some correctness issues
; + 2776 bytes -- init vars with loop (slower, but more correct and smaller)
; + 2739 bytes -- qkumba's crazy SMC everywhere patch
; + 2418+143 = 2561 bytes -- move NOTE structs to page0
; + 2423+143 = 2566 bytes -- fix vibrato code
2019-05-22 19:52:05 +00:00
2019-05-07 04:28:42 +00:00
; TODO
; move some of these flags to be bits rather than bytes?
; enabled could be bit 6 or 7 for fast checking
2019-05-24 00:53:41 +00:00
; NOTE_ENABLED,ENVELOPE_ENABLED,SIMPLE_GLISS,ENV_SLIDING,AMP_SLIDING?
; Header offsets
PT3_VERSION = $0D
PT3_HEADER_FREQUENCY = $63
PT3_SPEED = $64
PT3_LOOP = $66
PT3_PATTERN_LOC_L = $67
PT3_PATTERN_LOC_H = $68
PT3_SAMPLE_LOC_L = $69
PT3_SAMPLE_LOC_H = $6A
PT3_ORNAMENT_LOC_L = $A9
PT3_ORNAMENT_LOC_H = $AA
PT3_PATTERN_TABLE = $C9
2019-05-24 00:53:41 +00:00
2019-05-07 04:28:42 +00:00
; Use memset to set things to 0?
2019-05-22 21:08:52 +00:00
NOTE_VOLUME =0
NOTE_TONE_SLIDING_L =1
NOTE_TONE_SLIDING_H =2
NOTE_ENABLED =3
NOTE_ENVELOPE_ENABLED =4
NOTE_SAMPLE_POINTER_L =5
NOTE_SAMPLE_POINTER_H =6
NOTE_SAMPLE_LOOP =7
NOTE_SAMPLE_LENGTH =8
NOTE_TONE_L =9
NOTE_TONE_H =10
NOTE_AMPLITUDE =11
NOTE_NOTE =12
NOTE_LEN =13
NOTE_LEN_COUNT =14
2019-05-24 00:53:41 +00:00
NOTE_ADDR_L =15
NOTE_ADDR_H =16
NOTE_ORNAMENT_POINTER_L =17
NOTE_ORNAMENT_POINTER_H =18
NOTE_ORNAMENT_LOOP =19
NOTE_ORNAMENT_LENGTH =20
NOTE_ONOFF =21
NOTE_TONE_ACCUMULATOR_L =22
NOTE_TONE_ACCUMULATOR_H =23
NOTE_TONE_SLIDE_COUNT =24
NOTE_ORNAMENT_POSITION =25
NOTE_SAMPLE_POSITION =26
NOTE_ENVELOPE_SLIDING =27
NOTE_NOISE_SLIDING =28
NOTE_AMPLITUDE_SLIDING =29
NOTE_ONOFF_DELAY =30 ;ordering of DELAYs is hard-coded now
NOTE_OFFON_DELAY =31 ;ordering of DELAYs is hard-coded now
2019-05-24 00:53:41 +00:00
NOTE_TONE_SLIDE_STEP_L =32
NOTE_TONE_SLIDE_STEP_H =33
NOTE_TONE_SLIDE_DELAY =34
NOTE_SIMPLE_GLISS =35
NOTE_SLIDE_TO_NOTE =36
NOTE_TONE_DELTA_L =37
NOTE_TONE_DELTA_H =38
NOTE_TONE_SLIDE_TO_STEP =39
NOTE_STRUCT_SIZE=40
2019-05-13 04:36:44 +00:00
note_a = $80
note_b = $80+(NOTE_STRUCT_SIZE*1)
note_c = $80+(NOTE_STRUCT_SIZE*2)
begin_vars=$80
end_vars=$80+(NOTE_STRUCT_SIZE*3)
.if 0
begin_vars:
note_a: ; reset?
.byte $0 ; NOTE_VOLUME ; 0 ; Y
.byte $0 ; NOTE_TONE_SLIDING_L ; 1 ; Y
.byte $0 ; NOTE_TONE_SLIDING_H ; 2 ; Y
.byte $0 ; NOTE_ENABLED ; 3 ; Y
.byte $0 ; NOTE_ENVELOPE_ENABLED ; 4 ; Y
.byte $0 ; NOTE_SAMPLE_POINTER_L ; 5 ; Y
.byte $0 ; NOTE_SAMPLE_POINTER_H ; 6 ; Y
.byte $0 ; NOTE_SAMPLE_LOOP ; 7 ; Y
.byte $0 ; NOTE_SAMPLE_LENGTH ; 8 ; Y
.byte $0 ; NOTE_TONE_L ; 9
.byte $0 ; NOTE_TONE_H ; 10
.byte $0 ; NOTE_AMPLITUDE ; 11
.byte $0 ; NOTE_NOTE ; 12
.byte $0 ; NOTE_LEN ; 13
.byte $0 ; NOTE_LEN_COUNT ; 14
.byte $0 ; NOTE_ADDR_L ; 15
.byte $0 ; NOTE_ADDR_H ; 16
.byte $0 ; NOTE_ORNAMENT_POINTER_L ; 17 ; Y
.byte $0 ; NOTE_ORNAMENT_POINTER_H ; 18 ; Y
.byte $0 ; NOTE_ORNAMENT_LOOP ; 19 ; Y
.byte $0 ; NOTE_ORNAMENT_LENGTH ; 20 ; Y
.byte $0 ; NOTE_ONOFF ; 21
.byte $0 ; NOTE_TONE_ACCUMULATOR_L ; 22
.byte $0 ; NOTE_TONE_ACCUMULATOR_H ; 23
.byte $0 ; NOTE_TONE_SLIDE_COUNT ; 24
.byte $0 ; NOTE_ORNAMENT_POSITION ; 25 ; Y
.byte $0 ; NOTE_SAMPLE_POSITION ; 26 ; Y
.byte $0 ; NOTE_ENVELOPE_SLIDING ; 27
.byte $0 ; NOTE_NOISE_SLIDING ; 28
.byte $0 ; NOTE_AMPLITUDE_SLIDING ; 29
.byte $0 ; NOTE_ONOFF_DELAY ; 30
.byte $0 ; NOTE_OFFON_DELAY ; 31
.byte $0 ; NOTE_TONE_SLIDE_STEP_L ; 32
.byte $0 ; NOTE_TONE_SLIDE_STEP_H ; 33
.byte $0 ; NOTE_TONE_SLIDE_DELAY ; 34
.byte $0 ; NOTE_SIMPLE_GLISS ; 35
.byte $0 ; NOTE_SLIDE_TO_NOTE ; 36
.byte $0 ; NOTE_TONE_DELTA_L ; 37
.byte $0 ; NOTE_TONE_DELTA_H ; 38
.byte $0 ; NOTE_TONE_SLIDE_TO_STEP ; 39
2019-05-09 17:40:54 +00:00
2019-05-07 04:28:42 +00:00
note_b:
.byte $0 ; NOTE_VOLUME
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_TONE_SLIDING_L
.byte $0 ; NOTE_TONE_SLIDING_H
2019-05-07 04:28:42 +00:00
.byte $0 ; NOTE_ENABLED
.byte $0 ; NOTE_ENVELOPE_ENABLED
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_SAMPLE_POINTER_L
.byte $0 ; NOTE_SAMPLE_POINTER_H
2019-05-07 04:28:42 +00:00
.byte $0 ; NOTE_SAMPLE_LOOP
.byte $0 ; NOTE_SAMPLE_LENGTH
2019-05-07 19:11:52 +00:00
.byte $0 ; NOTE_TONE_L
.byte $0 ; NOTE_TONE_H
.byte $0 ; NOTE_AMPLITUDE
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_NOTE
.byte $0 ; NOTE_LEN
.byte $0 ; NOTE_LEN_COUNT
2019-05-10 04:22:17 +00:00
.byte $0 ; NOTE_ADDR_L
.byte $0 ; NOTE_ADDR_H
.byte $0 ; NOTE_ORNAMENT_POINTER_L
.byte $0 ; NOTE_ORNAMENT_POINTER_H
.byte $0 ; NOTE_ORNAMENT_LOOP
.byte $0 ; NOTE_ORNAMENT_LENGTH
2019-05-10 16:20:44 +00:00
.byte $0 ; NOTE_ONOFF
.byte $0 ; NOTE_TONE_ACCUMULATOR_L
.byte $0 ; NOTE_TONE_ACCUMULATOR_H
.byte $0 ; NOTE_TONE_SLIDE_COUNT
.byte $0 ; NOTE_ORNAMENT_POSITION
.byte $0 ; NOTE_SAMPLE_POSITION
.byte $0 ; NOTE_ENVELOPE_SLIDING
.byte $0 ; NOTE_NOISE_SLIDING
.byte $0 ; NOTE_AMPLITUDE_SLIDING
2019-05-11 03:06:56 +00:00
.byte $0 ; NOTE_ONOFF_DELAY
.byte $0 ; NOTE_OFFON_DELAY
.byte $0 ; NOTE_TONE_SLIDE_STEP_L
.byte $0 ; NOTE_TONE_SLIDE_STEP_H
.byte $0 ; NOTE_TONE_SLIDE_DELAY
.byte $0 ; NOTE_SIMPLE_GLISS
.byte $0 ; NOTE_SLIDE_TO_NOTE
.byte $0 ; NOTE_TONE_DELTA_L
.byte $0 ; NOTE_TONE_DELTA_H
.byte $0 ; NOTE_TONE_SLIDE_TO_STEP
2019-05-09 17:40:54 +00:00
2019-05-07 04:28:42 +00:00
note_c:
.byte $0 ; NOTE_VOLUME
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_TONE_SLIDING_L
.byte $0 ; NOTE_TONE_SLIDING_H
2019-05-07 04:28:42 +00:00
.byte $0 ; NOTE_ENABLED
.byte $0 ; NOTE_ENVELOPE_ENABLED
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_SAMPLE_POINTER_L
.byte $0 ; NOTE_SAMPLE_POINTER_H
2019-05-07 04:28:42 +00:00
.byte $0 ; NOTE_SAMPLE_LOOP
.byte $0 ; NOTE_SAMPLE_LENGTH
2019-05-07 19:11:52 +00:00
.byte $0 ; NOTE_TONE_L
.byte $0 ; NOTE_TONE_H
.byte $0 ; NOTE_AMPLITUDE
2019-05-09 17:40:54 +00:00
.byte $0 ; NOTE_NOTE
.byte $0 ; NOTE_LEN
.byte $0 ; NOTE_LEN_COUNT
2019-05-10 04:22:17 +00:00
.byte $0 ; NOTE_ADDR_L
.byte $0 ; NOTE_ADDR_H
.byte $0 ; NOTE_ORNAMENT_POINTER_L
.byte $0 ; NOTE_ORNAMENT_POINTER_H
.byte $0 ; NOTE_ORNAMENT_LOOP
.byte $0 ; NOTE_ORNAMENT_LENGTH
2019-05-10 16:20:44 +00:00
.byte $0 ; NOTE_ONOFF
.byte $0 ; NOTE_TONE_ACCUMULATOR_L
.byte $0 ; NOTE_TONE_ACCUMULATOR_H
.byte $0 ; NOTE_TONE_SLIDE_COUNT
.byte $0 ; NOTE_ORNAMENT_POSITION
.byte $0 ; NOTE_SAMPLE_POSITION
.byte $0 ; NOTE_ENVELOPE_SLIDING
.byte $0 ; NOTE_NOISE_SLIDING
.byte $0 ; NOTE_AMPLITUDE_SLIDING
2019-05-11 03:06:56 +00:00
.byte $0 ; NOTE_ONOFF_DELAY
.byte $0 ; NOTE_OFFON_DELAY
.byte $0 ; NOTE_TONE_SLIDE_STEP_L
.byte $0 ; NOTE_TONE_SLIDE_STEP_H
.byte $0 ; NOTE_TONE_SLIDE_DELAY
.byte $0 ; NOTE_SIMPLE_GLISS
.byte $0 ; NOTE_SLIDE_TO_NOTE
.byte $0 ; NOTE_TONE_DELTA_L
.byte $0 ; NOTE_TONE_DELTA_H
.byte $0 ; NOTE_TONE_SLIDE_TO_STEP
end_vars:
.endif
2019-05-07 04:28:42 +00:00
load_ornament0_sample1:
lda #0 ; 2
jsr load_ornament ; 6
; fall through
2019-06-05 16:18:34 +00:00
;===========================
; Load Sample
;===========================
; sample in A
; which note offset in X
2019-06-05 16:18:34 +00:00
; Sample table pointers are 16-bits little endian
; There are 32 of these pointers starting at $6a:$69
; Our sample starts at address (A*2)+that pointer
; We point SAMPLE_H:SAMPLE_L to this
; then we load the length/data values
; and then leave SAMPLE_H:SAMPLE_L pointing to begnning of
; the sample data
; Optimization:
; see comments on ornament setting
2019-05-07 19:11:52 +00:00
load_sample1:
lda #1 ; 2
2019-05-07 19:11:52 +00:00
load_sample:
sty PT3_TEMP ; 3
2019-05-09 15:27:08 +00:00
;pt3->ornament_patterns[i]=
; (pt3->data[0x6a+(i*2)]<<8)|pt3->data[0x69+(i*2)];
2019-05-09 15:27:08 +00:00
asl ; A*2 ; 2
tay ; 2
2019-06-05 16:18:34 +00:00
; Set the initial sample pointer
; a->sample_pointer=pt3->sample_patterns[a->sample];
2019-05-10 04:22:17 +00:00
lda PT3_LOC+PT3_SAMPLE_LOC_L,Y ; 4+
sta SAMPLE_L ; 3
lda PT3_LOC+PT3_SAMPLE_LOC_L+1,Y ; 4+
2019-05-20 14:11:29 +00:00
; assume pt3 file is at page boundary
adc #>PT3_LOC ; 2
sta SAMPLE_H ; 3
2019-05-20 14:11:29 +00:00
; Set the loop value
; a->sample_loop=pt3->data[a->sample_pointer];
ldy #0 ; 2
lda (SAMPLE_L),Y ; 5+
sta note_a+NOTE_SAMPLE_LOOP,X ; 5
; Set the length value
; a->sample_length=pt3->data[a->sample_pointer];
iny ; 2
lda (SAMPLE_L),Y ; 5+
sta note_a+NOTE_SAMPLE_LENGTH,X ; 5
; Set pointer to beginning of samples
lda SAMPLE_L ; 3
adc #$2 ; 2
sta note_a+NOTE_SAMPLE_POINTER_L,X ; 5
lda SAMPLE_H ; 3
adc #$0 ; 2
sta note_a+NOTE_SAMPLE_POINTER_H,X ; 5
ldy PT3_TEMP ; 3
rts ; 6
;============
; 76
2019-05-10 04:22:17 +00:00
;===========================
; Load Ornament
;===========================
2019-05-11 03:06:56 +00:00
; ornament value in A
2019-05-13 16:47:29 +00:00
; note offset in X
2019-05-07 15:33:07 +00:00
2019-05-20 02:11:56 +00:00
; Ornament table pointers are 16-bits little endian
; There are 16 of these pointers starting at $aa:$a9
; Our ornament starts at address (A*2)+that pointer
; We point ORNAMENT_H:ORNAMENT_L to this
; then we load the length/data values
; and then leave ORNAMENT_H:ORNAMENT_L pointing to begnning of
; the ornament data
; Optimization:
; Loop and length only used once, can be located negative
; from the pointer, but 6502 doesn't make addressing like that
; easy. Can't self modify as channels A/B/C have own copies
; of the var.
2019-05-10 04:22:17 +00:00
2019-05-20 02:11:56 +00:00
load_ornament:
sty PT3_TEMP ; save Y value ; 3
2019-05-11 03:06:56 +00:00
;pt3->ornament_patterns[i]=
; (pt3->data[0xaa+(i*2)]<<8)|pt3->data[0xa9+(i*2)];
2019-05-20 02:11:56 +00:00
asl ; A*2 ; 2
tay ; 2
; a->ornament_pointer=pt3->ornament_patterns[a->ornament];
lda PT3_LOC+PT3_ORNAMENT_LOC_L,Y ; 4+
2019-05-20 02:11:56 +00:00
sta ORNAMENT_L ; 3
lda PT3_LOC+PT3_ORNAMENT_LOC_L+1,Y ; 4+
2019-05-10 04:22:17 +00:00
2019-05-20 02:11:56 +00:00
; we're assuming PT3 is loaded to a page boundary
adc #>PT3_LOC ; 2
sta ORNAMENT_H ; 3
lda #0 ; 2
sta note_a+NOTE_ORNAMENT_POSITION,X ; 5
tay ; 2
; Set the loop value
; a->ornament_loop=pt3->data[a->ornament_pointer];
2019-05-20 02:11:56 +00:00
lda (ORNAMENT_L),Y ; 5+
sta note_a+NOTE_ORNAMENT_LOOP,X ; 5
; Set the length value
; a->ornament_length=pt3->data[a->ornament_pointer];
2019-05-20 02:11:56 +00:00
iny ; 2
lda (ORNAMENT_L),Y ; 5+
sta note_a+NOTE_ORNAMENT_LENGTH,X ; 5
; Set the pointer to the value past the length
2019-05-10 04:22:17 +00:00
2019-05-20 02:11:56 +00:00
lda ORNAMENT_L ; 3
adc #$2 ; 2
sta note_a+NOTE_ORNAMENT_POINTER_L,X ; 5
lda ORNAMENT_H ; 3
adc #$0 ; 2
sta note_a+NOTE_ORNAMENT_POINTER_H,X ; 5
2019-05-10 04:22:17 +00:00
ldy PT3_TEMP ; restore Y value ; 3
2019-05-10 04:22:17 +00:00
2019-05-20 02:11:56 +00:00
rts ; 6
;============
; 83
2019-05-07 04:28:42 +00:00
;====================================
; pt3_init_song
;====================================
;
2019-05-07 04:28:42 +00:00
pt3_init_song:
lda #$0
sta DONE_SONG ; 3
ldx #(end_vars-begin_vars)
zero_song_structs_loop:
dex
sta note_a,X
bne zero_song_structs_loop
sta pt3_noise_period_smc+1 ; 4
sta pt3_noise_add_smc+1 ; 4
sta pt3_envelope_period_l_smc+1 ; 4
sta pt3_envelope_period_h_smc+1 ; 4
sta pt3_envelope_slide_l_smc+1 ; 4
sta pt3_envelope_slide_h_smc+1 ; 4
sta pt3_envelope_slide_add_l_smc+1 ; 4
sta pt3_envelope_slide_add_h_smc+1 ; 4
sta pt3_envelope_add_smc+1 ; 4
sta pt3_envelope_type_smc+1 ; 4
sta pt3_envelope_type_old_smc+1 ; 4
sta pt3_envelope_delay_smc+1 ; 4
sta pt3_envelope_delay_orig_smc+1 ; 4
sta PT3_MIXER_VAL ; 3
sta current_pattern_smc+1 ; 4
sta current_line_smc+1 ; 4
sta current_subframe_smc+1 ; 4
2019-05-20 03:42:13 +00:00
lda #$f ; 2
sta note_a+NOTE_VOLUME ; 4
sta note_b+NOTE_VOLUME ; 4
sta note_c+NOTE_VOLUME ; 4
2019-05-13 16:47:29 +00:00
; default ornament/sample in A
; X is zero coming in here
;ldx #(NOTE_STRUCT_SIZE*0) ; 2
jsr load_ornament0_sample1 ; 6+93
2019-05-13 16:47:29 +00:00
; default ornament/sample in B
2019-05-20 03:42:13 +00:00
ldx #(NOTE_STRUCT_SIZE*1) ; 2
jsr load_ornament0_sample1 ; 6+93
2019-05-13 16:47:29 +00:00
; default ornament/sample in C
2019-05-20 03:42:13 +00:00
ldx #(NOTE_STRUCT_SIZE*2) ; 2
jsr load_ornament0_sample1 ; 6+93
2019-05-07 04:28:42 +00:00
;=======================
; load default speed
lda PT3_LOC+PT3_SPEED ; 4
2019-06-03 02:57:21 +00:00
sta pt3_speed_smc+1 ; 4
;=======================
; load loop
lda PT3_LOC+PT3_LOOP ; 4
2019-06-03 02:57:21 +00:00
sta pt3_loop_smc+1 ; 4
2019-09-09 05:06:21 +00:00
;========================
;========================
; set up note/freq table
; this saves some space and makes things marginally faster longrun
;========================
;========================
; note (heh) that there are separate tables if version 3.3
; but we are going to assume we are only going to be playing
; newer 3.4+ version files so only need the newer tables
2019-09-09 05:06:21 +00:00
ldx PT3_LOC+PT3_HEADER_FREQUENCY ; 4
beq use_freq_table_0
dex
beq use_freq_table_1
dex
beq use_freq_table_2
; fallthrough (freq table 3)
2019-09-09 05:06:21 +00:00
use_freq_table_3:
;=================================================
; Create Table #3, v4+, "PT3NoteTable_REAL_34_35"
;=================================================
2019-09-10 05:37:15 +00:00
ldy #11 ; !2
freq_table_3_copy_loop:
; note, high lookup almost same as 2v4, just need to adjust one value
2019-09-10 05:37:15 +00:00
lda base2_v4_high,Y ; !3
sta NoteTable_high,Y ; !3
lda base3_low,Y ; !3
sta NoteTable_low,Y ; !3
dey ; !1
bpl freq_table_3_copy_loop ; !2
2019-09-10 05:37:15 +00:00
dec NoteTable_high ; adjust to right value
2019-09-10 05:37:15 +00:00
jsr NoteTablePropogate ; !3
2019-09-10 05:37:15 +00:00
lda #<table3_v4_adjust
sta note_table_adjust_smc+1
lda #>table3_v4_adjust
sta note_table_adjust_smc+2
2019-09-10 05:37:15 +00:00
jsr NoteTableAdjust
2019-09-10 05:37:15 +00:00
2019-09-09 05:06:21 +00:00
jmp done_set_freq_table
2019-09-10 05:37:15 +00:00
2019-09-09 05:06:21 +00:00
use_freq_table_2:
;=================================================
; Create Table #2, v4+, "PT3NoteTable_ASM_34_35"
;=================================================
2019-09-10 05:37:15 +00:00
ldy #11
freq_table_2_copy_loop:
lda base2_v4_high,Y
2019-09-10 05:37:15 +00:00
sta NoteTable_high,Y
lda base2_v4_low,Y
2019-09-10 05:37:15 +00:00
sta NoteTable_low,Y
dey
bpl freq_table_2_copy_loop
jsr NoteTablePropogate ; !3
2019-09-10 05:37:15 +00:00
lda #<table2_v4_adjust
sta note_table_adjust_smc+1
lda #>table2_v4_adjust
sta note_table_adjust_smc+2
2019-09-10 05:37:15 +00:00
jsr NoteTableAdjust
2019-09-10 05:37:15 +00:00
jmp done_set_freq_table
2019-09-10 05:37:15 +00:00
use_freq_table_1:
;=================================================
; Create Table #1, "PT3NoteTable_ST"
;=================================================
2019-09-10 05:37:15 +00:00
ldy #11
freq_table_1_copy_loop:
lda base1_high,Y
sta NoteTable_high,Y
lda base1_low,Y
sta NoteTable_low,Y
dey
bpl freq_table_1_copy_loop
2019-09-10 05:37:15 +00:00
jsr NoteTablePropogate ; !3
2019-09-10 05:37:15 +00:00
; last adjustments
lda #$FD ; Tone[23]=$3FD
sta NoteTable_low+23
dec NoteTable_low+46 ; Tone[46]-=1;
2019-09-10 05:37:15 +00:00
jmp done_set_freq_table
2019-09-10 05:37:15 +00:00
use_freq_table_0:
;=================================================
; Create Table #0, "PT3NoteTable_PT_34_35"
;=================================================
2019-09-10 05:37:15 +00:00
ldy #11
freq_table_0_copy_loop:
lda base0_v4_high,Y
sta NoteTable_high,Y
lda base0_v4_low,Y
sta NoteTable_low,Y
2019-09-10 05:37:15 +00:00
dey
bpl freq_table_0_copy_loop
2019-09-10 05:37:15 +00:00
jsr NoteTablePropogate ; !3
lda #<table0_v4_adjust
sta note_table_adjust_smc+1
lda #>table0_v4_adjust
sta note_table_adjust_smc+2
jsr NoteTableAdjust
2019-09-10 05:37:15 +00:00
2019-09-09 05:06:21 +00:00
done_set_freq_table:
2019-09-10 05:37:15 +00:00
2019-09-09 05:06:21 +00:00
;======================
; calculate version
2019-06-01 04:19:44 +00:00
ldx #6 ; 2
2019-05-20 03:42:13 +00:00
lda PT3_LOC+PT3_VERSION ; 4
sec ; 2
sbc #'0' ; 2
2019-06-01 04:19:44 +00:00
cmp #9 ; 2
bcs not_ascii_number ; bge ; 2/3
tax ; 2
not_ascii_number:
; adjust version<6 SMC code in the slide code
; FIXME: I am sure there's a more clever way to do this
lda #$2C ; BIT ; 2
cpx #$6 ; 2
bcc version_less_than_6 ; blt ; 3
; carry is set
adc #$1F ; BIT->JMP 2C->4C ; 2
version_less_than_6:
sta version_smc ; 4
pick_volume_table:
;=======================
; Pick which volume number, based on version
; if (PlParams.PT3.PT3_Version <= 4)
2019-06-01 04:19:44 +00:00
cpx #5 ; 2
2019-05-17 17:19:04 +00:00
; carry clear = 3.3/3.4 table
; carry set = 3.5 table
;==========================
; VolTableCreator
;==========================
; Creates the appropriate volume table
; based on z80 code by Ivan Roshin ZXAYHOBETA/VTII10bG.asm
;
; Called with carry==0 for 3.3/3.4 table
; Called with carry==1 for 3.5 table
; 177f-1932 = 435 bytes, not that much better than 512 of lookup
VolTableCreator:
; Init initial variables
lda #$0
sta z80_d_smc+1
ldy #$11
; Set up self modify
ldx #$2A ; ROL for self-modify
bcs vol_type_35
vol_type_33:
; For older table, we set initial conditions a bit
; different
dey
tya
ldx #$ea ; NOP for self modify
vol_type_35:
sty z80_l_smc+1 ; l=16 or 17
sta z80_e_smc+1 ; e=16 or 0
stx vol_smc ; set the self-modify code
ldy #16 ; skip first row, all zeros
ldx #16 ; c=16
vol_outer:
clc ; add HL,DE
z80_l_smc:
lda #$d1
z80_e_smc:
adc #$d1
sta z80_e_smc+1
2019-06-03 21:42:07 +00:00
lda #0
z80_d_smc:
adc #$d1
sta z80_d_smc+1 ; carry is important
; sbc hl,hl
lda #0
2019-06-03 03:16:52 +00:00
adc #$ff
eor #$ff
vol_write:
sta z80_h_smc+1
pha
vol_inner:
pla
pha
vol_smc:
nop ; nop or ROL depending
z80_h_smc:
lda #$d1
adc #$0 ; a=a+carry;
sta VolumeTable,Y
iny
pla ; add HL,DE
adc z80_e_smc+1
pha
lda z80_h_smc+1
adc z80_d_smc+1
sta z80_h_smc+1
inx ; inc C
txa ; a=c
and #$f
bne vol_inner
pla
lda z80_e_smc+1 ; a=e
cmp #$77
bne vol_m3
inc z80_e_smc+1
vol_m3:
txa ; a=c
bne vol_outer
vol_done:
rts
2019-05-17 17:19:04 +00:00
2019-05-07 04:28:42 +00:00
;=========================================
; copy note table seed to proper location
;=========================================
; faster inlined
;NoteTableCopy:
; ldy #11 ; !2
;note_table_copy_loop:
;ntc_smc1:
; lda base1_high,Y ; !3
; sta NoteTable_high,Y ; !3
;ntc_smc2:
; lda base1_low,Y ; !3
; sta NoteTable_low,Y ; !3
; dey ; !1
; bpl note_table_copy_loop ; !2
; rts ; !1
;==========================================
; propogate the freq down, dividing by two
;==========================================
NoteTablePropogate:
ldy #0
note_table_propogate_loop:
clc
lda NoteTable_high,Y
ror
sta NoteTable_high+12,Y
lda NoteTable_low,Y
ror
sta NoteTable_low+12,Y
iny
cpy #84
bne note_table_propogate_loop
rts
;================================================
; propogation isn't enough, various values
; are ofte off by one, so adjust using a bitmask
;================================================
NoteTableAdjust:
ldx #0
note_table_adjust_outer:
note_table_adjust_smc:
lda table0_v4_adjust,X
sta TEMP
; reset smc
lda #<NoteTable_low
sta ntl_smc+1
lda #>NoteTable_low
sta ntl_smc+2
ldy #7
note_table_adjust_inner:
ror TEMP
bcc note_table_skip_adjust
ntl_smc:
inc NoteTable_low,X
note_table_skip_adjust:
clc
lda #12
adc ntl_smc+1
sta ntl_smc+1
lda #0
adc ntl_smc+2 ; unnecessary if aligned
sta ntl_smc+2
skip_adjust_done:
dey
bpl note_table_adjust_inner
inx
cpx #12
bne note_table_adjust_outer
rts
2019-05-20 14:11:29 +00:00
2019-05-07 15:33:07 +00:00
;=====================================
; Calculate Note
;=====================================
2019-05-13 04:36:44 +00:00
; note offset in X
2019-05-07 19:11:52 +00:00
calculate_note:
2019-05-22 19:52:05 +00:00
lda note_a+NOTE_ENABLED,X ; 4+
bne note_enabled ; 2/3
2019-05-22 19:52:05 +00:00
sta note_a+NOTE_AMPLITUDE,X ; 5
jmp done_note ; 3
note_enabled:
2019-05-07 19:11:52 +00:00
2019-05-22 19:52:05 +00:00
lda note_a+NOTE_SAMPLE_POINTER_H,X ; 4+
sta SAMPLE_H ; 3
lda note_a+NOTE_SAMPLE_POINTER_L,X ; 4+
sta SAMPLE_L ; 3
2019-05-22 19:52:05 +00:00
lda note_a+NOTE_ORNAMENT_POINTER_H,X ; 4+
sta ORNAMENT_H ; 3
lda note_a+NOTE_ORNAMENT_POINTER_L,X ; 4+
sta ORNAMENT_L ; 3
2019-05-22 19:52:05 +00:00
lda note_a+NOTE_SAMPLE_POSITION,X ; 4+
asl ; 2
asl ; 2
tay ; 2
; b0 = pt3->data[a->sample_pointer + a->sample_position * 4];
2019-05-22 21:08:52 +00:00
lda (SAMPLE_L),Y ; 5+
sta sample_b0_smc+1 ; 4
; b1 = pt3->data[a->sample_pointer + a->sample_position * 4 + 1];
2019-05-22 21:08:52 +00:00
iny ; 2
lda (SAMPLE_L),Y ; 5+
sta sample_b1_smc+1 ; 4
2019-05-22 21:08:52 +00:00
; a->tone = pt3->data[a->sample_pointer + a->sample_position*4+2];
; a->tone+=(pt3->data[a->sample_pointer + a->sample_position*4+3])<<8;
2019-06-01 04:26:29 +00:00
; a->tone += a->tone_accumulator;
2019-05-22 21:08:52 +00:00
iny ; 2
lda (SAMPLE_L),Y ; 5+
2019-06-01 04:26:29 +00:00
adc note_a+NOTE_TONE_ACCUMULATOR_L,X ; 4+
2019-05-22 21:08:52 +00:00
sta note_a+NOTE_TONE_L,X ; 4
2019-05-22 21:08:52 +00:00
iny ; 2
lda (SAMPLE_L),Y ; 5+
adc note_a+NOTE_TONE_ACCUMULATOR_H,X ; 4+
2019-06-01 04:26:29 +00:00
sta note_a+NOTE_TONE_H,X ; 4
2019-05-13 20:48:47 +00:00
;=============================
; Accumulate tone if set
2019-05-13 20:48:47 +00:00
; (if sample_b1 & $40)
2019-05-11 03:06:56 +00:00
bit sample_b1_smc+1
2019-06-01 04:26:29 +00:00
bvc no_accum ; (so, if b1&0x40 is zero, skip it)
2019-05-11 03:06:56 +00:00
2019-06-01 04:26:29 +00:00
sta note_a+NOTE_TONE_ACCUMULATOR_H,X
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_L,X ; tone_accumulator=tone
sta note_a+NOTE_TONE_ACCUMULATOR_L,X
2019-05-11 03:06:56 +00:00
no_accum:
;============================
; Calculate tone
; j = a->note + (pt3->data[a->ornament_pointer + a->ornament_position]
2019-06-01 04:26:29 +00:00
clc ;;can be removed if ADC ACCUMULATOR_H cannot overflow
ldy note_a+NOTE_ORNAMENT_POSITION,X
lda (ORNAMENT_L),Y
2019-05-13 04:36:44 +00:00
adc note_a+NOTE_NOTE,X
; if (j < 0) j = 0;
bpl note_not_negative
lda #0
; if (j > 95) j = 95;
note_not_negative:
cmp #96
2019-05-13 20:48:47 +00:00
bcc note_not_too_high ; blt
lda #95
note_not_too_high:
; w = GetNoteFreq(j,pt3->frequency_table);
jsr GetNoteFreq
; a->tone = (a->tone + a->tone_sliding + w) & 0xfff;
clc
2019-06-03 21:42:07 +00:00
ldy note_a+NOTE_TONE_SLIDING_L,X
tya
adc note_a+NOTE_TONE_L,X
sta temp_word_l1_smc+1
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_H,X
adc note_a+NOTE_TONE_SLIDING_H,X
sta temp_word_h1_smc+1
2019-06-01 04:26:29 +00:00
clc ;;can be removed if ADC SLIDING_H cannot overflow
temp_word_l1_smc:
lda #$d1
freq_l_smc:
adc #$d1
2019-05-13 04:36:44 +00:00
sta note_a+NOTE_TONE_L,X
temp_word_h1_smc:
lda #$d1
freq_h_smc:
adc #$d1
and #$0f
2019-05-13 04:36:44 +00:00
sta note_a+NOTE_TONE_H,X
;=====================
; handle tone sliding
2019-05-07 19:11:52 +00:00
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_SLIDE_COUNT,X
bmi no_tone_sliding ; if (a->tone_slide_count > 0) {
2019-05-13 21:09:01 +00:00
beq no_tone_sliding
2019-05-13 04:36:44 +00:00
dec note_a+NOTE_TONE_SLIDE_COUNT,X ; a->tone_slide_count--;
bne no_tone_sliding ; if (a->tone_slide_count==0) {
; a->tone_sliding+=a->tone_slide_step
2019-06-01 04:26:29 +00:00
clc ;;can be removed if ADC freq_h cannot overflow
2019-06-03 21:42:07 +00:00
tya
2019-05-13 04:36:44 +00:00
adc note_a+NOTE_TONE_SLIDE_STEP_L,X
sta note_a+NOTE_TONE_SLIDING_L,X
2019-06-03 21:42:07 +00:00
tay
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_SLIDING_H,X
adc note_a+NOTE_TONE_SLIDE_STEP_H,X
sta note_a+NOTE_TONE_SLIDING_H,X
; a->tone_slide_count = a->tone_slide_delay;
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_SLIDE_DELAY,X
sta note_a+NOTE_TONE_SLIDE_COUNT,X
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_SIMPLE_GLISS,X
bne no_tone_sliding ; if (!a->simplegliss) {
; FIXME: do these need to be signed compares?
check1:
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_SLIDE_STEP_H,X
bpl check2 ; if ( ((a->tone_slide_step < 0) &&
2019-05-13 21:09:01 +00:00
; (a->tone_sliding <= a->tone_delta) ||
; 16 bit signed compare
2019-06-03 21:42:07 +00:00
tya ; NUM1-NUM2
cmp note_a+NOTE_TONE_DELTA_L,X ;
lda note_a+NOTE_TONE_SLIDING_H,X
sbc note_a+NOTE_TONE_DELTA_H,X
bvc sc_loser1 ; N eor V
eor #$80
sc_loser1:
bmi slide_to_note ; then A (signed) < NUM (signed) and BMI will branch
2019-05-14 05:02:41 +00:00
; equals case
2019-06-03 21:42:07 +00:00
tya
2019-05-14 05:02:41 +00:00
cmp note_a+NOTE_TONE_DELTA_L,X
bne check2
lda note_a+NOTE_TONE_SLIDING_H,X
cmp note_a+NOTE_TONE_DELTA_H,X
beq slide_to_note
check2:
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_TONE_SLIDE_STEP_H,X
bmi no_tone_sliding ; ((a->tone_slide_step >= 0) &&
2019-05-13 21:09:01 +00:00
; (a->tone_sliding >= a->tone_delta)
; 16 bit signed compare
2019-06-03 21:42:07 +00:00
tya ; NUM1-NUM2
cmp note_a+NOTE_TONE_DELTA_L,X ;
lda note_a+NOTE_TONE_SLIDING_H,X
sbc note_a+NOTE_TONE_DELTA_H,X
bvc sc_loser2 ; N eor V
eor #$80
sc_loser2:
bmi no_tone_sliding ; then A (signed) < NUM (signed) and BMI will branch
slide_to_note:
2019-05-14 05:02:41 +00:00
; a->note = a->slide_to_note;
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_SLIDE_TO_NOTE,X
2019-05-14 05:02:41 +00:00
sta note_a+NOTE_NOTE,X
lda #0
2019-05-13 04:36:44 +00:00
sta note_a+NOTE_TONE_SLIDE_COUNT,X
sta note_a+NOTE_TONE_SLIDING_L,X
sta note_a+NOTE_TONE_SLIDING_H,X
no_tone_sliding:
2019-05-13 21:09:01 +00:00
;=========================
; Calculate the amplitude
;=========================
calc_amplitude:
2019-05-13 21:09:01 +00:00
; get base value from the sample (bottom 4 bits of sample_b1)
2019-05-11 04:11:53 +00:00
sample_b1_smc:
lda #$d1 ; a->amplitude= (b1 & 0xf);
2019-05-11 03:06:56 +00:00
and #$f
2019-05-13 21:09:01 +00:00
;========================================
2019-05-22 19:52:05 +00:00
; if b0 top bit is set, it means sliding
2019-05-13 21:09:01 +00:00
2019-05-11 04:11:53 +00:00
; adjust amplitude sliding
bit sample_b0_smc+1 ; if ((b0 & 0x80)!=0) {
2019-06-01 04:29:56 +00:00
bpl done_amp_sliding ; so if top bit not set, skip
2019-06-03 03:24:25 +00:00
tay
2019-05-11 04:11:53 +00:00
2019-05-13 21:09:01 +00:00
;================================
; if top bits 0b11 then slide up
2019-06-03 03:24:25 +00:00
; if top bits 0b10 then slide down
2019-05-13 21:09:01 +00:00
2019-06-01 04:29:56 +00:00
; if ((b0 & 0x40)!=0) {
2019-06-03 03:24:25 +00:00
lda note_a+NOTE_AMPLITUDE_SLIDING,X
sec
2019-06-01 04:29:56 +00:00
bvc amp_slide_down
2019-05-13 21:09:01 +00:00
2019-05-11 04:11:53 +00:00
amp_slide_up:
; if (a->amplitude_sliding < 15) {
; a pain to do signed compares
sbc #15
bvc asu_signed
eor #$80
asu_signed:
bpl done_amp_sliding ; skip if A>=15
inc note_a+NOTE_AMPLITUDE_SLIDING,X ; a->amplitude_sliding++;
2019-06-03 03:24:25 +00:00
bne done_amp_sliding_y
2019-05-13 21:09:01 +00:00
2019-05-11 04:11:53 +00:00
amp_slide_down:
; if (a->amplitude_sliding > -15) {
; a pain to do signed compares
sbc #$f1 ; -15
bvc asd_signed
eor #$80
asd_signed:
bmi done_amp_sliding ; if A < -15, skip subtract
dec note_a+NOTE_AMPLITUDE_SLIDING,X ; a->amplitude_sliding--;
2019-05-11 04:11:53 +00:00
2019-06-03 03:24:25 +00:00
done_amp_sliding_y:
tya
2019-05-11 04:11:53 +00:00
done_amp_sliding:
; a->amplitude+=a->amplitude_sliding;
clc
2019-05-13 04:36:44 +00:00
adc note_a+NOTE_AMPLITUDE_SLIDING,X
2019-05-07 19:11:52 +00:00
; clamp amplitude to 0 - 15
check_amp_lo:
2019-06-03 03:24:25 +00:00
bmi write_clamp_amplitude
check_amp_hi:
cmp #16
2019-06-03 03:24:25 +00:00
bcc write_amplitude ; blt
lda #15
2019-06-03 03:24:25 +00:00
.byte $2C
write_clamp_amplitude:
2019-06-03 03:24:25 +00:00
lda #0
write_amplitude:
sta note_amp_smc+1
2019-05-13 21:09:01 +00:00
done_clamp_amplitude:
2019-05-07 19:11:52 +00:00
; We generate the proper table at runtime now
; so always in Volume Table
2019-05-13 21:09:01 +00:00
; a->amplitude = PT3VolumeTable_33_34[a->volume][a->amplitude];
; a->amplitude = PT3VolumeTable_35[a->volume][a->amplitude];
2019-05-13 17:36:24 +00:00
lda note_a+NOTE_VOLUME,X ; 4+
asl ; 2
asl ; 2
asl ; 2
asl ; 2
2019-06-03 03:24:25 +00:00
note_amp_smc:
ora #$d1 ; 4+
2019-05-13 17:36:24 +00:00
tay ; 2
lda VolumeTable,Y ; 4+
sta note_a+NOTE_AMPLITUDE,X ; 5
2019-05-13 04:36:44 +00:00
2019-05-13 17:36:24 +00:00
done_table:
2019-05-11 03:06:56 +00:00
2019-05-13 21:09:01 +00:00
check_envelope_enable:
; Bottom bit of b0 indicates our sample has envelope
; Also make sure envelopes are enabled
; if (((b0 & 0x1) == 0) && ( a->envelope_enabled)) {
sample_b0_smc:
lda #$d1
lsr
tay
bcs envelope_slide
2019-05-11 03:06:56 +00:00
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_ENVELOPE_ENABLED,X
beq envelope_slide
2019-05-11 03:06:56 +00:00
2019-05-13 21:09:01 +00:00
; Bit 4 of the per-channel AY-3-8910 amplitude specifies
; envelope enabled
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_AMPLITUDE,X ; a->amplitude |= 16;
2019-05-11 03:06:56 +00:00
ora #$10
2019-05-13 04:36:44 +00:00
sta note_a+NOTE_AMPLITUDE,X
2019-05-07 19:11:52 +00:00
envelope_slide:
2019-06-01 04:36:03 +00:00
; Envelope slide
; If b1 top bits are 10 or 11
lda sample_b0_smc+1
2019-06-03 03:37:05 +00:00
asl
asl
asl ; b0 bit 5 to carry flag
lda #$20
bit sample_b1_smc+1 ; b1 bit 7 to sign flag, bit 5 to zero flag
php
2019-06-03 03:37:05 +00:00
bpl else_noise_slide ; if ((b1 & 0x80) != 0) {
2019-06-01 04:36:03 +00:00
tya
ora #$f0
2019-06-03 03:37:05 +00:00
bcs envelope_slide_down ; if ((b0 & 0x20) == 0) {
envelope_slide_up:
; j = ((b0>>1)&0xF) + a->envelope_sliding;
and #$0f
clc
2019-06-03 03:37:05 +00:00
envelope_slide_down:
; j = ((b0>>1)|0xF0) + a->envelope_sliding
2019-05-13 04:36:44 +00:00
adc note_a+NOTE_ENVELOPE_SLIDING,X
sta e_slide_amount_smc+1 ; j
envelope_slide_done:
2019-06-01 04:36:03 +00:00
plp
beq last_envelope ; if (( b1 & 0x20) != 0) {
; a->envelope_sliding = j;
sta note_a+NOTE_ENVELOPE_SLIDING,X
last_envelope:
; pt3->envelope_add+=j;
clc
e_slide_amount_smc:
lda #$d1
adc pt3_envelope_add_smc+1
sta pt3_envelope_add_smc+1
jmp noise_slide_done ; skip else
else_noise_slide:
; Noise slide
; else {
; pt3->noise_add = (b0>>1) + a->noise_sliding;
2019-06-01 04:36:03 +00:00
tya
clc
2019-05-13 04:36:44 +00:00
adc note_a+NOTE_NOISE_SLIDING,X
sta pt3_noise_add_smc+1
2019-06-01 04:36:03 +00:00
plp
2019-06-01 01:30:05 +00:00
beq noise_slide_done ; if ((b1 & 0x20) != 0) {
; noise_sliding = pt3_noise_add
sta note_a+NOTE_NOISE_SLIDING,X
2019-05-07 19:11:52 +00:00
noise_slide_done:
2019-05-11 04:11:53 +00:00
;======================
; set mixer
lda sample_b1_smc+1 ; pt3->mixer_value = ((b1 >>1) & 0x48) | pt3->mixer_value;
2019-05-11 04:11:53 +00:00
lsr
and #$48
ora PT3_MIXER_VAL ; 3
sta PT3_MIXER_VAL ; 3
2019-05-11 04:11:53 +00:00
2019-05-07 19:11:52 +00:00
;========================
; increment sample position
2019-05-07 19:11:52 +00:00
2019-05-13 04:36:44 +00:00
inc note_a+NOTE_SAMPLE_POSITION,X ; a->sample_position++;
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_SAMPLE_POSITION,X
cmp note_a+NOTE_SAMPLE_LENGTH,X
bcc sample_pos_ok ; blt
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_SAMPLE_LOOP,X
sta note_a+NOTE_SAMPLE_POSITION,X
sample_pos_ok:
;========================
; increment ornament position
2019-05-13 04:36:44 +00:00
inc note_a+NOTE_ORNAMENT_POSITION,X ; a->ornament_position++;
lda note_a+NOTE_ORNAMENT_POSITION,X
cmp note_a+NOTE_ORNAMENT_LENGTH,X
bcc ornament_pos_ok ; blt
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_ORNAMENT_LOOP,X
sta note_a+NOTE_ORNAMENT_POSITION,X
ornament_pos_ok:
2019-05-11 03:06:56 +00:00
2019-05-07 19:11:52 +00:00
done_note:
; set mixer value
; this is a bit complex (from original code)
; after 3 calls it is set up properly
lsr PT3_MIXER_VAL
2019-05-07 19:11:52 +00:00
2019-05-11 03:06:56 +00:00
handle_onoff:
2019-06-18 18:00:43 +00:00
ldy note_a+NOTE_ONOFF,X ;if (a->onoff>0) {
2019-05-11 03:06:56 +00:00
beq done_onoff
2019-06-18 18:00:43 +00:00
dey ; a->onoff--;
2019-05-11 03:06:56 +00:00
2019-06-18 18:00:43 +00:00
bne put_offon ; if (a->onoff==0) {
2019-05-13 04:36:44 +00:00
lda note_a+NOTE_ENABLED,X
eor #$1 ; toggle note_enabled
2019-05-13 04:36:44 +00:00
sta note_a+NOTE_ENABLED,X
2019-05-11 03:06:56 +00:00
beq do_offon
2019-05-11 03:06:56 +00:00
do_onoff:
ldy note_a+NOTE_ONOFF_DELAY,X ; if (a->enabled) a->onoff=a->onoff_delay;
jmp put_offon
2019-05-11 03:06:56 +00:00
do_offon:
2019-06-18 18:00:43 +00:00
ldy note_a+NOTE_OFFON_DELAY,X ; else a->onoff=a->offon_delay;
2019-05-11 03:06:56 +00:00
put_offon:
2019-06-18 18:00:43 +00:00
sty note_a+NOTE_ONOFF,X
2019-05-07 19:11:52 +00:00
2019-05-11 03:06:56 +00:00
done_onoff:
2019-05-07 15:33:07 +00:00
2019-05-22 19:52:05 +00:00
rts ; 6
2019-05-07 15:33:07 +00:00
2019-05-20 14:11:29 +00:00
2019-05-09 17:40:54 +00:00
2019-05-22 21:08:52 +00:00
2019-05-07 15:33:07 +00:00
;=====================================
; Decode Note
;=====================================
; X points to the note offset
2019-05-07 15:33:07 +00:00
2019-06-05 15:40:06 +00:00
; Note! These timings are out of date (FIXME)
2019-05-22 21:08:52 +00:00
; Timings (from ===>)
; 00: 14+30
; 0X: 14+15
; 10: 14+5 +124
; 1X: 14+5 +193
; 2X/3X: 14+5 +17
; 4X: 14+5+5 + 111
2019-06-05 15:40:06 +00:00
; 5X-BX: 14+5+5+ 102
; CX:
; DX/EX:
; FX:
2019-05-22 21:08:52 +00:00
stop_decoding:
; we are still running, decrement and early return
dec note_a+NOTE_LEN_COUNT,X ; 7
rts ; 6
;=====================================
; Decode Line
;=====================================
pt3_decode_line:
; decode_note(&pt3->a,&(pt3->a_addr),pt3);
ldx #(NOTE_STRUCT_SIZE*0)
jsr decode_note
; decode_note(&pt3->b,&(pt3->b_addr),pt3);
ldx #(NOTE_STRUCT_SIZE*1)
jsr decode_note
; decode_note(&pt3->c,&(pt3->c_addr),pt3);
ldx #(NOTE_STRUCT_SIZE*2)
;;jsr decode_note ; fall through
; if (pt3->a.all_done && pt3->b.all_done && pt3->c.all_done) {
; return 1;
; }
2019-05-07 19:11:52 +00:00
decode_note:
2019-05-07 15:33:07 +00:00
2019-05-09 17:40:54 +00:00
; Init vars
ldy #0 ; 2
sty spec_command_smc+1 ; 4
2019-05-09 17:40:54 +00:00
; Skip decode if note still running
2019-05-22 21:08:52 +00:00
lda note_a+NOTE_LEN_COUNT,X ; 4+
cmp #2 ; 2
bcs stop_decoding ; blt, assume not negative ; 2/3
2019-05-09 17:40:54 +00:00
keep_decoding:
2019-05-22 21:08:52 +00:00
lda note_a+NOTE_NOTE,X ; store prev note ; 4+
sta prev_note_smc+1 ; 4
2019-05-09 17:40:54 +00:00
2019-05-22 21:08:52 +00:00
lda note_a+NOTE_TONE_SLIDING_H,X ; store prev sliding ; 4+
sta prev_sliding_h_smc+1 ; 4
2019-05-22 21:08:52 +00:00
lda note_a+NOTE_TONE_SLIDING_L,X ; 4+
sta prev_sliding_l_smc+1 ; 4
2019-05-09 17:40:54 +00:00
2019-05-11 03:06:56 +00:00
2019-05-22 21:08:52 +00:00
;============
; 24
2019-05-11 03:06:56 +00:00
2019-05-09 17:40:54 +00:00
note_decode_loop:
2019-05-22 21:08:52 +00:00
lda note_a+NOTE_LEN,X ; re-up length count ; 4+
sta note_a+NOTE_LEN_COUNT,X ; 5
lda note_a+NOTE_ADDR_L,X ; 4+
sta PATTERN_L ; 3
lda note_a+NOTE_ADDR_H,X ; 4+
sta PATTERN_H ; 3
;===>
2019-05-10 14:57:08 +00:00
; get next value
2019-05-22 21:08:52 +00:00
lda (PATTERN_L),Y ; 5+
sta note_command_smc+1 ; save termporarily ; 4
and #$0f ; 2
sta note_command_bottom_smc+1 ; 4
note_command_smc:
lda #$d1 ; 2
2019-05-10 14:57:08 +00:00
2019-05-10 16:20:44 +00:00
; FIXME: use a jump table??
2019-05-22 21:08:52 +00:00
; further reflection, that would require 32-bytes of addresses
; in addition to needing X or Y to index the jump table. hmmm
2019-05-09 17:40:54 +00:00
2019-05-22 21:08:52 +00:00
and #$f0 ; 2
2019-05-10 16:20:44 +00:00
2019-05-22 21:08:52 +00:00
; cmp #$00
bne decode_case_1X ; 2/3
;=============
; 14
2019-05-10 16:20:44 +00:00
decode_case_0X:
2019-05-10 17:09:05 +00:00
;==============================
; $0X set special effect
;==============================
2019-05-22 21:08:52 +00:00
; -1
note_command_bottom_smc:
lda #$d1 ; 2
2019-05-10 17:09:05 +00:00
2019-05-22 21:08:52 +00:00
; we can always store spec as 0 means no spec
; FIXME: what if multiple spec commands?
; Doesn't seem to happen in practice
; But AY_emul has code to handle it
2019-05-10 17:09:05 +00:00
sta spec_command_smc+1 ; 4
2019-05-10 17:09:05 +00:00
2019-05-22 21:08:52 +00:00
bne decode_case_0X_not_zero ; 2/3
;=============
; 8
2019-05-20 13:50:49 +00:00
; 00 case
; means end of pattern
2019-05-22 21:08:52 +00:00
; -1
sta note_a+NOTE_LEN_COUNT,X ; len_count=0; ; 5
2019-05-10 17:09:05 +00:00
dec pt3_pattern_done_smc+1 ; 6
2019-05-10 17:09:05 +00:00
2019-06-05 15:40:06 +00:00
jmp note_done_decoding ; 3
2019-05-10 16:20:44 +00:00
decode_case_1X:
2019-05-10 17:09:05 +00:00
;==============================
; $1X -- Set Envelope Type
;==============================
2019-05-22 21:08:52 +00:00
cmp #$10 ; 2
bne decode_case_2X ; 2/3
;============
; 5
2019-05-10 16:20:44 +00:00
2019-05-22 21:08:52 +00:00
; -1
lda note_command_bottom_smc+1 ; 4
bne decode_case_not_10 ; 3
2019-05-09 17:40:54 +00:00
2019-05-10 17:09:05 +00:00
decode_case_10:
; 10 case - disable ; -1
2019-05-22 21:08:52 +00:00
sta note_a+NOTE_ENVELOPE_ENABLED,X ; A is 0 ; 5
beq decode_case_1x_common ; branch always ; 3
2019-05-09 17:40:54 +00:00
2019-05-10 17:09:05 +00:00
decode_case_not_10:
; -1
2019-05-22 21:08:52 +00:00
jsr set_envelope ; 6+64
2019-05-10 17:09:05 +00:00
decode_case_1x_common:
iny ; 2
lda (PATTERN_L),Y ; 5+
lsr ; 2
jsr load_sample ; 6+86
2019-05-10 17:09:05 +00:00
lda #0 ; 2
sta note_a+NOTE_ORNAMENT_POSITION,X ; ornament_position=0 ; 5
2019-05-09 17:40:54 +00:00
decode_case_0X_not_zero:
2019-06-05 15:40:06 +00:00
jmp done_decode_loop ; 3
2019-05-10 16:38:41 +00:00
2019-05-10 16:20:44 +00:00
decode_case_2X:
decode_case_3X:
;==============================
; $2X/$3X set noise period
2019-05-10 16:20:44 +00:00
;==============================
cmp #$40 ; 2
bcs decode_case_4X ; branch greater/equal ; 3
; -1
lda note_command_smc+1 ; 4
adc #$e0 ; same as subtract $20 ; 2
sta pt3_noise_period_smc+1 ; 3
2019-05-10 16:20:44 +00:00
2019-06-05 15:40:06 +00:00
jmp done_decode_loop ; 3
;===========
; 16
2019-05-10 16:20:44 +00:00
decode_case_4X:
;==============================
2019-05-10 16:38:41 +00:00
; $4X -- set ornament
2019-05-10 16:20:44 +00:00
;==============================
; cmp #$40 ; already set ;
bne decode_case_5X ; 3
; -1
lda note_command_bottom_smc+1; set ornament to bottom nibble; 4
jsr load_ornament ; 6+93
2019-05-10 16:38:41 +00:00
2019-06-05 15:40:06 +00:00
jmp done_decode_loop ; 3
;============
; 110
2019-05-10 16:38:41 +00:00
2019-05-10 16:20:44 +00:00
decode_case_5X:
;==============================
; $5X-$AX set note
;==============================
cmp #$B0 ; 2
bcs decode_case_bX ; branch greater/equal ; 3
2019-05-10 16:20:44 +00:00
; -1
lda note_command_smc+1 ; 4
adc #$b0 ; 2
sta note_a+NOTE_NOTE,X ; note=(current_val-0x50); ; 5
2019-05-10 16:20:44 +00:00
jsr reset_note ; 6+69
2019-05-10 16:20:44 +00:00
lda #1 ; 2
sta note_a+NOTE_ENABLED,X ; enabled=1 ; 5
2019-06-05 15:40:06 +00:00
bne note_done_decoding ; 3
2019-05-10 16:20:44 +00:00
decode_case_bX:
2019-05-10 16:38:41 +00:00
;============================================
; $BX -- note length or envelope manipulation
;============================================
; cmp #$b0 ; already set from before
bne decode_case_cX ; 3
; -1
lda note_command_bottom_smc+1 ; 4
beq decode_case_b0 ; 3
; -1
sbc #1 ; envelope_type=(current_val&0xf)-1; ; 2
bne decode_case_bx_higher ; 3
2019-05-10 17:09:05 +00:00
decode_case_b1:
; Set Length
; get next byte
iny ; 2
lda (PATTERN_L),Y ; 5
2019-05-10 17:09:05 +00:00
sta note_a+NOTE_LEN,X ; 5
sta note_a+NOTE_LEN_COUNT,X ; 5
2019-06-05 15:40:06 +00:00
bcs done_decode_loop ; branch always ; 3
2019-05-10 17:09:05 +00:00
2019-06-01 04:40:25 +00:00
decode_case_b0:
; Disable envelope
sta note_a+NOTE_ENVELOPE_ENABLED,X ; 5
sta note_a+NOTE_ORNAMENT_POSITION,X ; 5
2019-06-05 15:40:06 +00:00
beq done_decode_loop ; 3
2019-06-01 04:40:25 +00:00
2019-05-10 17:09:05 +00:00
decode_case_bx_higher:
2019-05-22 21:08:52 +00:00
jsr set_envelope ; 6+64
2019-06-05 15:40:06 +00:00
bcs done_decode_loop ; branch always ; 3
2019-05-10 16:38:41 +00:00
2019-05-10 16:20:44 +00:00
decode_case_cX:
;==============================
2019-05-10 16:38:41 +00:00
; $CX -- set volume
2019-05-10 16:20:44 +00:00
;==============================
2019-06-05 15:19:09 +00:00
cmp #$c0 ; check top nibble $C ; 2
bne decode_case_dX ; 3
; -1
lda note_command_bottom_smc+1 ; 4
bne decode_case_cx_not_c0 ; 3
; -1
2019-05-10 16:38:41 +00:00
decode_case_c0:
; special case $C0 means shut down the note
2019-06-05 15:22:12 +00:00
sta note_a+NOTE_ENABLED,X ; enabled=0 ; 5
2019-05-10 16:38:41 +00:00
jsr reset_note ; 6+69
2019-05-10 16:38:41 +00:00
2019-06-05 15:40:06 +00:00
beq note_done_decoding ; branch always ; 3
2019-05-10 16:38:41 +00:00
decode_case_cx_not_c0:
2019-06-05 15:22:12 +00:00
sta note_a+NOTE_VOLUME,X ; volume=current_val&0xf; 5
2019-06-05 15:40:06 +00:00
bne done_decode_loop ; branch always ; 3
2019-05-10 16:38:41 +00:00
2019-05-10 16:20:44 +00:00
decode_case_dX:
;==============================
2019-06-05 04:56:52 +00:00
; $DX/$EX -- change sample
2019-05-10 16:20:44 +00:00
;==============================
2019-06-05 15:19:09 +00:00
; D0 = special case (end note)
; D1-EF = set sample to (value - $D0)
2019-05-10 16:38:41 +00:00
2019-06-05 15:19:09 +00:00
cmp #$f0 ; check top nibble $D/$E ; 2
beq decode_case_fX ; 3
2019-06-05 04:56:52 +00:00
; -1
lda note_command_smc+1 ; 4
2019-06-05 15:19:09 +00:00
sec ; 2
2019-06-05 15:40:06 +00:00
sbc #$d0 ; 2
beq note_done_decoding ; 3
2019-06-05 04:56:52 +00:00
2019-06-05 15:19:09 +00:00
decode_case_not_d0:
2019-06-05 15:40:06 +00:00
; -1
2019-06-05 15:19:09 +00:00
jsr load_sample ; load sample in bottom nybble ; 6+??
2019-06-05 15:40:06 +00:00
bcc done_decode_loop; branch always ; 3
2019-05-10 16:38:41 +00:00
;========================
; d0 case means end note
2019-06-05 15:40:06 +00:00
;decode_case_d0:
; jmp note_done_decoding
2019-05-10 16:38:41 +00:00
2019-06-05 04:56:52 +00:00
2019-05-10 16:20:44 +00:00
;==============================
; $FX - change ornament/sample
;==============================
2019-06-05 04:56:52 +00:00
decode_case_fX:
2019-05-10 16:20:44 +00:00
; disable envelope
2019-06-05 15:22:12 +00:00
lda #0 ; 2
sta note_a+NOTE_ENVELOPE_ENABLED,X ; 5
2019-05-10 16:20:44 +00:00
; Set ornament to low byte of command
lda note_command_bottom_smc+1 ; 4
2019-06-05 15:22:12 +00:00
jsr load_ornament ; ornament to load in A ; 6+?
2019-05-10 16:20:44 +00:00
; Get next byte
2019-06-05 15:22:12 +00:00
iny ; point to next byte ; 2
lda (PATTERN_L),Y ; 5
2019-05-10 16:20:44 +00:00
; Set sample to value/2
2019-06-05 15:22:12 +00:00
lsr ; divide by two ; 2
jsr load_sample ; sample to load in A ; 6+?
2019-05-10 16:20:44 +00:00
; fallthrough
2019-05-09 17:40:54 +00:00
2019-06-05 15:40:06 +00:00
done_decode_loop:
2019-05-10 16:20:44 +00:00
2019-06-05 15:22:12 +00:00
iny ; point to next byte ; 2
2019-05-10 16:20:44 +00:00
2019-06-05 15:22:12 +00:00
jmp note_decode_loop ; 3
2019-05-10 16:20:44 +00:00
2019-06-05 15:40:06 +00:00
note_done_decoding:
iny ; point to next byte ; 2
2019-05-13 02:14:07 +00:00
;=================================
; handle effects
;=================================
; Note, the AYemul code has code to make sure these are applied
; In the same order they appear. We don't bother?
2019-05-10 16:20:44 +00:00
handle_effects:
2019-05-13 02:14:07 +00:00
spec_command_smc:
lda #$d1 ; 2
2019-05-13 02:14:07 +00:00
;==============================
; Effect #1 -- Tone Down
;==============================
effect_1:
2019-06-05 21:00:47 +00:00
cmp #$1 ; 2
bne effect_2 ; 3
; -1
sta note_a+NOTE_SIMPLE_GLISS,X ; 5
lsr ; 2
sta note_a+NOTE_ONOFF,X ; 5
2019-06-01 04:40:25 +00:00
2019-06-05 21:00:47 +00:00
lda (PATTERN_L),Y ; load byte, set as slide delay ; 5
iny ; 2
2019-06-05 21:00:47 +00:00
sta note_a+NOTE_TONE_SLIDE_DELAY,X ; 5
sta note_a+NOTE_TONE_SLIDE_COUNT,X ; 5
2019-06-05 21:00:47 +00:00
lda (PATTERN_L),Y ; load byte, set as slide step low ; 5
iny ; 2
sta note_a+NOTE_TONE_SLIDE_STEP_L,X ; 5
2019-06-05 21:00:47 +00:00
lda (PATTERN_L),Y ; load byte, set as slide step high ; 5
iny ; 2
sta note_a+NOTE_TONE_SLIDE_STEP_H,X ; 5
2019-06-05 21:00:47 +00:00
jmp no_effect ; 3
2019-05-13 02:14:07 +00:00
;==============================
; Effect #2 -- Portamento
;==============================
effect_2:
2019-06-05 21:00:47 +00:00
cmp #$2 ; 2
beq effect_2_small ; 3
; -1
jmp effect_3 ; 3
effect_2_small: ; FIXME: make smaller
2019-06-05 21:00:47 +00:00
lda #0 ; 2
sta note_a+NOTE_SIMPLE_GLISS,X ; 5
sta note_a+NOTE_ONOFF,X ; 5
2019-06-05 21:00:47 +00:00
lda (PATTERN_L),Y ; load byte, set as delay ; 5
iny ; 2
2019-06-05 21:00:47 +00:00
sta note_a+NOTE_TONE_SLIDE_DELAY,X ; 5
sta note_a+NOTE_TONE_SLIDE_COUNT,X ; 5
2019-06-05 21:00:47 +00:00
iny ; 2
iny ; 2
iny ; 2
2019-06-05 21:00:47 +00:00
lda (PATTERN_L),Y ; load byte, set as slide_step high ; 5
php ; 3
2019-05-13 02:14:07 +00:00
; 16-bit absolute value
2019-06-05 21:00:47 +00:00
bpl slide_step_positive1 ; 3
;-1
eor #$ff ; 2
2019-06-03 03:37:05 +00:00
slide_step_positive1:
2019-06-05 21:00:47 +00:00
sta note_a+NOTE_TONE_SLIDE_STEP_H,X ; 5
dey ; 2
lda (PATTERN_L),Y ; load byte, set as slide_step low ; 5
2019-06-08 04:51:51 +00:00
plp ; 4
clc ; 2
2019-06-05 21:00:47 +00:00
bpl slide_step_positive2 ; 3
;-1
eor #$ff ; 2
2019-06-08 04:51:51 +00:00
sec ; 2
2019-06-03 03:37:05 +00:00
slide_step_positive2:
adc #$0 ; 2
2019-06-05 21:00:47 +00:00
sta note_a+NOTE_TONE_SLIDE_STEP_L,X ; 5
bcc skip_step_inc1 ; 3
inc note_a+NOTE_TONE_SLIDE_STEP_H,X ; 7
2019-06-01 04:40:25 +00:00
skip_step_inc1:
2019-06-05 21:00:47 +00:00
iny ; moved here as it messed with flags ; 2
iny ; 2
2019-05-14 05:02:41 +00:00
; a->tone_delta=GetNoteFreq(a->note,pt3)-
; GetNoteFreq(prev_note,pt3);
prev_note_smc:
lda #$d1
jsr GetNoteFreq
lda freq_l_smc+1
sta temp_word_l2_smc+1
lda freq_h_smc+1
sta temp_word_h2_smc+1
lda note_a+NOTE_NOTE,X
jsr GetNoteFreq
sec
temp_word_l2_smc:
sbc #$d1
sta note_a+NOTE_TONE_DELTA_L,X
lda freq_h_smc+1
temp_word_h2_smc:
sbc #$d1
sta note_a+NOTE_TONE_DELTA_H,X
2019-05-14 03:27:44 +00:00
; a->slide_to_note=a->note;
lda note_a+NOTE_NOTE,X
2019-05-14 03:27:44 +00:00
sta note_a+NOTE_SLIDE_TO_NOTE,X
2019-05-14 03:27:44 +00:00
; a->note=prev_note;
lda prev_note_smc+1
2019-05-14 03:27:44 +00:00
sta note_a+NOTE_NOTE,X
; implement file version 6 and above slide behavior
; this is done by SMC at song init time
version_smc:
jmp weird_version ; (JMP to BIT via smc) ; 3
prev_sliding_l_smc:
lda #$d1
sta note_a+NOTE_TONE_SLIDING_L,X
prev_sliding_h_smc:
lda #$d1
sta note_a+NOTE_TONE_SLIDING_H,X
weird_version:
; annoying 16-bit subtract, only care if negative
; if ((a->tone_delta - a->tone_sliding) < 0) {
sec
lda note_a+NOTE_TONE_DELTA_L,X
sbc note_a+NOTE_TONE_SLIDING_L,X
lda note_a+NOTE_TONE_DELTA_H,X
sbc note_a+NOTE_TONE_SLIDING_H,X
bpl no_effect
; a->tone_slide_step = -a->tone_slide_step;
lda note_a+NOTE_TONE_SLIDE_STEP_L,X
eor #$ff
2019-05-14 03:27:44 +00:00
clc
adc #$1
sta note_a+NOTE_TONE_SLIDE_STEP_L,X
lda note_a+NOTE_TONE_SLIDE_STEP_H,X
eor #$ff
adc #$0
sta note_a+NOTE_TONE_SLIDE_STEP_H,X
jmp no_effect
2019-05-13 02:14:07 +00:00
;==============================
; Effect #3 -- Sample Position
;==============================
effect_3:
cmp #$3
bne effect_4
lda (PATTERN_L),Y ; load byte, set as sample position
iny
sta note_a+NOTE_SAMPLE_POSITION,X
bne no_effect ; branch always
2019-05-13 02:14:07 +00:00
;==============================
; Effect #4 -- Ornament Position
;==============================
effect_4:
cmp #$4
bne effect_5
lda (PATTERN_L),Y ; load byte, set as ornament position
iny
sta note_a+NOTE_ORNAMENT_POSITION,X
bne no_effect ; branch always
2019-05-13 02:14:07 +00:00
;==============================
; Effect #5 -- Vibrato
;==============================
effect_5:
cmp #$5
bne effect_8
lda (PATTERN_L),Y ; load byte, set as onoff delay
iny
sta note_a+NOTE_ONOFF_DELAY,X
sta note_a+NOTE_ONOFF,X
2019-05-13 02:14:07 +00:00
lda (PATTERN_L),Y ; load byte, set as offon delay
iny
sta note_a+NOTE_OFFON_DELAY,X
2019-05-09 17:40:54 +00:00
lda #0
sta note_a+NOTE_TONE_SLIDE_COUNT,X
sta note_a+NOTE_TONE_SLIDING_L,X
sta note_a+NOTE_TONE_SLIDING_H,X
2019-05-09 17:40:54 +00:00
beq no_effect ; branch always
2019-05-13 02:14:07 +00:00
;==============================
; Effect #8 -- Envelope Down
;==============================
effect_8:
cmp #$8
bne effect_9
; delay
lda (PATTERN_L),Y ; load byte, set as speed
iny
sta pt3_envelope_delay_smc+1
sta pt3_envelope_delay_orig_smc+1
2019-05-09 17:40:54 +00:00
; low value
lda (PATTERN_L),Y ; load byte, set as low
iny
sta pt3_envelope_slide_add_l_smc+1
2019-05-09 17:40:54 +00:00
; high value
lda (PATTERN_L),Y ; load byte, set as high
iny
sta pt3_envelope_slide_add_h_smc+1
2019-05-09 17:40:54 +00:00
bne no_effect ; branch always
2019-05-13 02:14:07 +00:00
;==============================
; Effect #9 -- Set Speed
;==============================
effect_9:
cmp #$9
bne no_effect
lda (PATTERN_L),Y ; load byte, set as speed
iny
2019-06-03 02:57:21 +00:00
sta pt3_speed_smc+1
2019-05-09 17:40:54 +00:00
2019-05-13 02:14:07 +00:00
no_effect:
;================================
; add y into the address pointer
clc
tya
adc note_a+NOTE_ADDR_L,X
sta note_a+NOTE_ADDR_L,X
lda #0
adc note_a+NOTE_ADDR_H,X
sta note_a+NOTE_ADDR_H,X
sta PATTERN_H
2019-05-13 02:14:07 +00:00
2019-05-07 15:33:07 +00:00
rts
2019-05-22 21:08:52 +00:00
;=======================================
; Set Envelope
;=======================================
; pulls out common code from $1X and $BX
; commands
; A = new envelope type
set_envelope:
sta pt3_envelope_type_smc+1 ; 4
2019-05-22 21:08:52 +00:00
; give fake old to force update? maybe only needed if printing?
; pt3->envelope_type_old=0x78;
lda #$78 ; 2
sta pt3_envelope_type_old_smc+1 ; 4
2019-05-22 21:08:52 +00:00
; get next byte
iny ; 2
lda (PATTERN_L),Y ; 5+
sta pt3_envelope_period_h_smc+1 ; 4
2019-05-22 21:08:52 +00:00
iny ; 2
lda (PATTERN_L),Y ; 5+
sta pt3_envelope_period_l_smc+1 ; 4
2019-05-22 21:08:52 +00:00
2019-06-01 04:45:24 +00:00
lda #1 ; 2
sta note_a+NOTE_ENVELOPE_ENABLED,X ; envelope_enabled=1 ; 5
lsr ; 2
2019-05-22 21:08:52 +00:00
sta note_a+NOTE_ORNAMENT_POSITION,X ; ornament_position=0 ; 5
sta pt3_envelope_delay_smc+1 ; envelope_delay=0 ; 4
sta pt3_envelope_slide_l_smc+1 ; envelope_slide=0 ; 4
sta pt3_envelope_slide_h_smc+1 ; 4
2019-05-22 21:08:52 +00:00
rts ; 6
;===========
; 64
;========================
; reset note
;========================
; common code from the decode note code
reset_note:
lda #0 ; 2
sta note_a+NOTE_SAMPLE_POSITION,X ; sample_position=0 ; 5
sta note_a+NOTE_AMPLITUDE_SLIDING,X ; amplitude_sliding=0 ; 5
sta note_a+NOTE_NOISE_SLIDING,X ; noise_sliding=0 ; 5
sta note_a+NOTE_ENVELOPE_SLIDING,X ; envelope_sliding=0 ; 5
sta note_a+NOTE_ORNAMENT_POSITION,X ; ornament_position=0 ; 5
sta note_a+NOTE_TONE_SLIDE_COUNT,X ; tone_slide_count=0 ; 5
sta note_a+NOTE_TONE_SLIDING_L,X ; tone_sliding=0 ; 5
sta note_a+NOTE_TONE_SLIDING_H,X ; 5
sta note_a+NOTE_TONE_ACCUMULATOR_L,X ; tone_accumulator=0 ; 5
sta note_a+NOTE_TONE_ACCUMULATOR_H,X ; 5
sta note_a+NOTE_ONOFF,X ; onoff=0; ; 5
rts ; 6
;============
; 69
2019-05-10 04:22:17 +00:00
;=====================================
; Set Pattern
;=====================================
2019-05-20 14:11:29 +00:00
; FIXME: inline this? we do call it from outside
; in the player note length code
is_done:
; done with song, set it to non-zero
sta DONE_SONG ; 3
rts ; 6
pt3_set_pattern:
2019-05-20 14:11:29 +00:00
; Lookup current pattern in pattern table
current_pattern_smc:
ldy #$d1 ; 2
2019-05-20 14:11:29 +00:00
lda PT3_LOC+PT3_PATTERN_TABLE,Y ; 4+
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
; if value is $FF we are at the end of the song
cmp #$ff ; 2
beq is_done ; 2/3
2019-05-14 03:27:44 +00:00
2019-05-20 14:11:29 +00:00
;============
; 20 if end
2019-05-14 03:27:44 +00:00
not_done:
2019-05-20 14:11:29 +00:00
; set up the three pattern address pointers
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
asl ; mul pattern offset by two, as word sized ; 2
tay ; 2
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
; point PATTERN_H/PATTERN_L to the pattern address table
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
clc ; 2
lda PT3_LOC+PT3_PATTERN_LOC_L ; 4
sta PATTERN_L ; 3
lda PT3_LOC+PT3_PATTERN_LOC_H ; 4
adc #>PT3_LOC ; assume page boundary ; 2
sta PATTERN_H ; 3
; First 16-bits points to the Channel A address
lda (PATTERN_L),Y ; 5+
sta note_a+NOTE_ADDR_L ; 4
iny ; 2
lda (PATTERN_L),Y ; 5+
adc #>PT3_LOC ; assume page boundary ; 2
sta note_a+NOTE_ADDR_H ; 4
iny ; 2
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
; Next 16-bits points to the Channel B address
lda (PATTERN_L),Y ; 5+
sta note_b+NOTE_ADDR_L ; 4
iny ; 2
lda (PATTERN_L),Y ; 5+
adc #>PT3_LOC ; assume page boundary ; 2
sta note_b+NOTE_ADDR_H ; 4
iny ; 2
2019-05-20 14:11:29 +00:00
; Next 16-bits points to the Channel C address
lda (PATTERN_L),Y ; 5+
sta note_c+NOTE_ADDR_L ; 4
iny ; 2
lda (PATTERN_L),Y ; 5+
adc #>PT3_LOC ; assume page boundary ; 2
sta note_c+NOTE_ADDR_H ; 4
2019-05-20 14:11:29 +00:00
; clear out the noise channel
lda #0 ; 2
sta pt3_noise_period_smc+1 ; 4
2019-05-20 14:11:29 +00:00
; Set all three channels as active
; FIXME: num_channels, may need to be 6 if doing 6-channel pt3?
lda #3 ; 2
sta pt3_pattern_done_smc+1 ; 4
2019-05-10 04:22:17 +00:00
2019-05-20 14:11:29 +00:00
rts ; 6
2019-05-07 19:11:52 +00:00
;=====================================
; pt3 make frame
;=====================================
2019-05-20 14:11:29 +00:00
; update pattern or line if necessary
; then calculate the values for the next frame
2019-05-07 19:11:52 +00:00
2019-06-01 04:45:24 +00:00
;==========================
; pattern done early!
2019-05-10 14:57:08 +00:00
2019-06-01 04:45:24 +00:00
early_end:
inc current_pattern_smc+1 ; increment pattern ; 6
sta current_line_smc+1 ; 4
sta current_subframe_smc+1 ; 4
2019-05-20 14:11:29 +00:00
2019-06-01 04:45:24 +00:00
check_subframe:
lda current_subframe_smc+1 ; 4
2019-05-20 14:11:29 +00:00
bne pattern_good ; 2/3
2019-05-10 14:57:08 +00:00
; load a new pattern in
2019-05-20 14:11:29 +00:00
jsr pt3_set_pattern ;6+?
2019-05-10 14:57:08 +00:00
2019-05-20 16:40:35 +00:00
lda DONE_SONG ; 3
beq pattern_good ; 2/3
rts ; 6
2019-05-14 03:27:44 +00:00
2019-06-01 04:45:24 +00:00
pt3_make_frame:
; see if we need a new pattern
; we do if line==0 and subframe==0
; allow fallthrough where possible
current_line_smc:
lda #$d1 ; 2
2019-06-01 04:45:24 +00:00
beq check_subframe ; 2/3
2019-05-10 14:57:08 +00:00
pattern_good:
; see if we need a new line
current_subframe_smc:
lda #$d1 ; 2
2019-05-20 16:40:35 +00:00
bne line_good ; 2/3
2019-05-10 14:57:08 +00:00
; decode a new line
2019-05-20 16:40:35 +00:00
jsr pt3_decode_line ; 6+?
; check if pattern done early
pt3_pattern_done_smc:
lda #$d1 ; 2
2019-06-01 04:45:24 +00:00
beq early_end ; 2/3
2019-05-10 14:57:08 +00:00
line_good:
; Increment everything
inc current_subframe_smc+1 ; subframe++ ; 6
lda current_subframe_smc+1 ; 4
2019-05-20 16:40:35 +00:00
; if we hit pt3_speed, move to next
2019-06-03 02:57:21 +00:00
pt3_speed_smc:
eor #$d1 ; 2
2019-05-20 16:40:35 +00:00
bne do_frame ; 2/3
next_line:
sta current_subframe_smc+1 ; reset subframe to 0 ; 4
inc current_line_smc+1 ; and increment line ; 6
lda current_line_smc+1 ; 4
2019-06-01 04:45:24 +00:00
eor #64 ; always end at 64. ; 2
2019-05-20 16:40:35 +00:00
bne do_frame ; is this always needed? ; 2/3
next_pattern:
sta current_line_smc+1 ; reset line to 0 ; 4
2019-05-10 14:57:08 +00:00
inc current_pattern_smc+1 ; increment pattern ; 6
do_frame:
2019-05-07 19:11:52 +00:00
; AY-3-8910 register summary
;
; R0/R1 = A period low/high
; R2/R3 = B period low/high
; R4/R5 = C period low/high
2019-05-20 03:42:13 +00:00
; R6 = Noise period
; R7 = Enable XX Noise=!CBA Tone=!CBA
2019-05-07 19:11:52 +00:00
; R8/R9/R10 = Channel A/B/C amplitude M3210, M=envelope enable
; R11/R12 = Envelope Period low/high
; R13 = Envelope Shape, 0xff means don't write
; R14/R15 = I/O (ignored)
ldx #0 ; needed ; 2
stx PT3_MIXER_VAL ; 3
stx pt3_envelope_add_smc+1 ; 4
2019-05-07 19:11:52 +00:00
;;ldx #(NOTE_STRUCT_SIZE*0) ; Note A ; 2
2019-05-20 16:40:35 +00:00
jsr calculate_note ; 6+?
ldx #(NOTE_STRUCT_SIZE*1) ; Note B ; 2
jsr calculate_note ; 6+?
ldx #(NOTE_STRUCT_SIZE*2) ; Note C ; 2
jsr calculate_note ; 6+?
2019-05-07 19:11:52 +00:00
2019-06-03 02:57:21 +00:00
convert_177_smc1:
sec ; 2
2019-05-07 19:11:52 +00:00
; Load up the Frequency Registers
lda note_a+NOTE_TONE_L ; Note A Period L ; 4
sta AY_REGISTERS+0 ; into R0 ; 3
2019-05-20 16:40:35 +00:00
lda note_a+NOTE_TONE_H ; Note A Period H ; 4
sta AY_REGISTERS+1 ; into R1 ; 3
lda note_a+NOTE_TONE_L ; Note A Period L ; 4
bcc no_scale_a ; 2/3
; Convert from 1.77MHz to 1MHz by multiplying by 9/16
2019-05-20 16:40:35 +00:00
; conversion costs 100 cycles!
; first multiply by 8
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+1 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+1 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+1 ; 5
; add in original to get 9
2019-05-20 16:40:35 +00:00
clc ; 2
adc note_a+NOTE_TONE_L ; 4
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+0 ; 3
lda note_a+NOTE_TONE_H ; 4
adc AY_REGISTERS+1 ; 3
; divide by 16 to get proper value
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+0 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+0 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+0 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+0 ; 5
and #$0f ; 2
sta AY_REGISTERS+1 ; 3
no_scale_a:
2019-06-03 02:57:21 +00:00
convert_177_smc2:
sec ; 2
lda note_b+NOTE_TONE_L ; Note B Period L ; 4
sta AY_REGISTERS+2 ; into R2 ; 3
2019-05-20 16:40:35 +00:00
lda note_b+NOTE_TONE_H ; Note B Period H ; 4
sta AY_REGISTERS+3 ; into R3 ; 3
lda note_b+NOTE_TONE_L ; Note B Period L ; 4
bcc no_scale_b ; 2/3
; Convert from 1.77MHz to 1MHz by multiplying by 9/16
; first multiply by 8
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+3 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+3 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+3 ; 5
; add in original to get 9
2019-05-20 16:40:35 +00:00
clc ; 2
adc note_b+NOTE_TONE_L ; 4
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+2 ; 3
lda note_b+NOTE_TONE_H ; 4
adc AY_REGISTERS+3 ; 3
; divide by 16 to get proper value
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+2 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+2 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+2 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+2 ; 5
and #$0f ; 2
sta AY_REGISTERS+3 ; 3
no_scale_b:
2019-06-03 02:57:21 +00:00
convert_177_smc3:
sec ; 2
lda note_c+NOTE_TONE_L ; Note C Period L ; 4
sta AY_REGISTERS+4 ; into R4 ; 3
2019-05-20 16:40:35 +00:00
lda note_c+NOTE_TONE_H ; Note C Period H ; 4
sta AY_REGISTERS+5 ; into R5 ; 3
lda note_c+NOTE_TONE_L ; Note C Period L ; 4
bcc no_scale_c ; 2/3
; Convert from 1.77MHz to 1MHz by multiplying by 9/16
; first multiply by 8
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+5 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+5 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+5 ; 5
; add in original to get 9
2019-05-20 16:40:35 +00:00
clc ; 2
adc note_c+NOTE_TONE_L ; 4
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+4 ; 3
lda note_c+NOTE_TONE_H ; 4
adc AY_REGISTERS+5 ; 3
; divide by 16 to get proper value
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+4 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+4 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+4 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+4 ; 5
and #$0f ; 2
sta AY_REGISTERS+5 ; 3
no_scale_c:
2019-05-07 19:11:52 +00:00
; Noise
; frame[6]= (pt3->noise_period+pt3->noise_add)&0x1f;
2019-05-20 16:40:35 +00:00
clc ; 2
pt3_noise_period_smc:
lda #$d1 ; 2
pt3_noise_add_smc:
adc #$d1 ; 2
2019-05-20 16:40:35 +00:00
and #$1f ; 2
sta AY_REGISTERS+6 ; 3
2019-06-03 02:57:21 +00:00
convert_177_smc4:
sec ; 2
bcc no_scale_n ; 2/3
; Convert from 1.77MHz to 1MHz by multiplying by 9/16
; first multiply by 8
asl ; 2
asl ; 2
asl ; 2
; add in original to get 9
2019-06-03 02:57:21 +00:00
adc AY_REGISTERS+6 ; 3
; divide by 16 to get proper value
ror ; 2
ror ; 2
ror ; 2
ror ; 2
2019-05-20 16:40:35 +00:00
and #$1f ; 2
no_scale_n:
2019-06-02 04:04:28 +00:00
sta AY_REGISTERS+6 ; 3
2019-05-20 16:40:35 +00:00
;=======================
2019-05-07 19:11:52 +00:00
; Mixer
; PT3_MIXER_VAL is already in AY_REGISTERS+7
2019-05-20 16:40:35 +00:00
;=======================
2019-05-07 19:11:52 +00:00
; Amplitudes
lda note_a+NOTE_AMPLITUDE ; 3
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+8 ; 3
lda note_b+NOTE_AMPLITUDE ; 3
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+9 ; 3
lda note_c+NOTE_AMPLITUDE ; 3
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+10 ; 3
;======================================
2019-05-07 19:11:52 +00:00
; Envelope period
2019-05-09 15:27:08 +00:00
; result=period+add+slide (16-bits)
2019-05-20 16:40:35 +00:00
clc ; 2
pt3_envelope_period_l_smc:
lda #$d1 ; 2
pt3_envelope_add_smc:
adc #$d1 ; 2
2019-06-03 02:57:21 +00:00
tay ; 2
pt3_envelope_period_h_smc:
lda #$d1 ; 2
2019-05-20 16:40:35 +00:00
adc #0 ; 2
tax ; 2
2019-05-09 15:27:08 +00:00
2019-05-20 16:40:35 +00:00
clc ; 2
2019-06-03 02:57:21 +00:00
tya ; 2
pt3_envelope_slide_l_smc:
adc #$d1 ; 2
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+11 ; 3
txa ; 2
pt3_envelope_slide_h_smc:
adc #$d1 ; 2
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+12 ; 3
2019-06-03 02:57:21 +00:00
convert_177_smc5:
sec
bcc no_scale_e ; 2/3
; Convert from 1.77MHz to 1MHz by multiplying by 9/16
2019-06-03 02:57:21 +00:00
tay ; 2
; first multiply by 8
lda AY_REGISTERS+11 ; 3
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+12 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+12 ; 5
asl ; 2
2019-05-20 16:40:35 +00:00
rol AY_REGISTERS+12 ; 5
; add in original to get 9
2019-05-20 16:40:35 +00:00
clc ; 2
adc AY_REGISTERS+11 ; 3
sta AY_REGISTERS+11 ; 3
2019-06-03 02:57:21 +00:00
tya ; 2
2019-05-20 16:40:35 +00:00
adc AY_REGISTERS+12 ; 3
; divide by 16 to get proper value
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+11 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+11 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+11 ; 5
ror ; 2
2019-05-20 16:40:35 +00:00
ror AY_REGISTERS+11 ; 5
and #$0f ; 2
sta AY_REGISTERS+12 ; 3
no_scale_e:
2019-05-20 16:40:35 +00:00
;========================
; Envelope shape
2019-05-20 16:40:35 +00:00
pt3_envelope_type_smc:
lda #$d1 ; 2
pt3_envelope_type_old_smc:
cmp #$d1 ; 2
sta pt3_envelope_type_old_smc+1; copy old to new ; 4
2019-05-20 16:40:35 +00:00
bne envelope_diff ; 2/3
envelope_same:
2019-05-20 16:40:35 +00:00
lda #$ff ; if same, store $ff ; 2
envelope_diff:
2019-05-20 16:40:35 +00:00
sta AY_REGISTERS+13 ; 3
2019-05-20 16:40:35 +00:00
;==============================
; end-of-frame envelope update
;==============================
pt3_envelope_delay_smc:
lda #$d1 ; 2
2019-05-20 16:40:35 +00:00
beq done_do_frame ; assume can't be negative? ; 2/3
2019-05-09 15:27:08 +00:00
; do this if envelope_delay>0
dec pt3_envelope_delay_smc+1 ; 6
2019-05-20 16:40:35 +00:00
bne done_do_frame ; 2/3
2019-05-09 15:27:08 +00:00
; only do if we hit 0
pt3_envelope_delay_orig_smc:
lda #$d1 ; reset envelope delay ; 2
sta pt3_envelope_delay_smc+1 ; 4
2019-05-09 15:27:08 +00:00
2019-05-20 16:40:35 +00:00
clc ; 16-bit add ; 2
lda pt3_envelope_slide_l_smc+1 ; 4
pt3_envelope_slide_add_l_smc:
adc #$d1 ; 2
sta pt3_envelope_slide_l_smc+1 ; 4
lda pt3_envelope_slide_h_smc+1 ; 4
pt3_envelope_slide_add_h_smc:
adc #$d1 ; 2
sta pt3_envelope_slide_h_smc+1 ; 4
2019-05-09 15:27:08 +00:00
done_do_frame:
2019-05-07 19:11:52 +00:00
2019-05-20 16:40:35 +00:00
rts ; 6
2019-05-07 15:33:07 +00:00
;======================================
; GetNoteFreq
;======================================
; Return frequency from lookup table
; Which note is in A
; return in freq_l/freq_h
2019-05-20 16:40:35 +00:00
GetNoteFreq:
2019-05-07 15:33:07 +00:00
sty PT3_TEMP ; 3
2019-05-20 16:40:35 +00:00
tay ; 2
2019-05-07 15:33:07 +00:00
2019-09-10 05:37:15 +00:00
lda NoteTable_high,Y ; 4+
sta freq_h_smc+1 ; 4
2019-09-10 05:37:15 +00:00
lda NoteTable_low,Y ; 4+
sta freq_l_smc+1 ; 4
ldy PT3_TEMP ; 3
2019-05-20 16:40:35 +00:00
rts ; 6
;===========
;base0_v3_high:
;.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06
;base0_v3_low:
;.byte $21,$73,$CE,$33,$A0,$16,$93,$18,$A4,$36,$CE,$6D
; note: same as base0_v3_high
base0_v4_high:
.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06
base0_v4_low:
.byte $22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF,$6D
base1_high:
.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07
base1_low:
.byte $F8,$10,$60,$80,$D8,$28,$88,$F0,$60,$E0,$58,$E0
;base2_v3_high:
;.byte $0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07,$07,$07
;base2_v3_low:
;.byte $3E,$80,$CC,$22,$82,$EC,$5C,$D6,$58,$E0,$6E,$04
; note almost same as above
base2_v4_high:
.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06
base2_v4_low:
.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8,$3B,$C5,$55,$EC
; note almost same as above
;base3_high:
;.byte $0C,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06
base3_low:
.byte $DA,$22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF
; Adjustment factors
table0_v4_adjust:
.byte $40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c,$5a
table2_v4_adjust:
.byte $20,$a8,$40,$f8,$bc,$90,$78,$70,$74,$08,$2a,$50
table3_v4_adjust:
.byte $B4,$40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c
NoteTable_high:
.res 96,0
NoteTable_low:
.res 96,0
VolumeTable:
.res 256,0
pt3_lib_end:
2019-05-07 04:43:20 +00:00
; Table #1 of Pro Tracker 3.3x - 3.5x
2019-09-10 05:37:15 +00:00
;PT3NoteTable_ST_high:
;.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09
;.byte $09,$08,$08,$07,$07,$07,$06,$06
;.byte $05,$05,$05,$04,$04,$04,$04,$03
;.byte $03,$03,$03,$03,$02,$02,$02,$02
;.byte $02,$02,$02,$01,$01,$01,$01,$01
;.byte $01,$01,$01,$01,$01,$01,$01,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;PT3NoteTable_ST_low:
;.byte $F8,$10,$60,$80,$D8,$28,$88,$F0
;.byte $60,$E0,$58,$E0,$7C,$08,$B0,$40
;.byte $EC,$94,$44,$F8,$B0,$70,$2C,$FD
;.byte $BE,$84,$58,$20,$F6,$CA,$A2,$7C
;.byte $58,$38,$16,$F8,$DF,$C2,$AC,$90
;.byte $7B,$65,$51,$3E,$2C,$1C,$0A,$FC
;.byte $EF,$E1,$D6,$C8,$BD,$B2,$A8,$9F
;.byte $96,$8E,$85,$7E,$77,$70,$6B,$64
;.byte $5E,$59,$54,$4F,$4B,$47,$42,$3F
;.byte $3B,$38,$35,$32,$2F,$2C,$2A,$27
;.byte $25,$23,$21,$1F,$1D,$1C,$1A,$19
;.byte $17,$16,$15,$13,$12,$11,$10,$0F
2019-05-07 04:43:20 +00:00
2019-05-07 15:17:46 +00:00
; Table #2 of Pro Tracker 3.4x - 3.5x
2019-09-10 05:37:15 +00:00
;PT3NoteTable_ASM_34_35_high:
;.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08
;.byte $08,$07,$07,$06,$06,$06,$05,$05
;.byte $05,$04,$04,$04,$04,$03,$03,$03
;.byte $03,$03,$02,$02,$02,$02,$02,$02
;.byte $02,$01,$01,$01,$01,$01,$01,$01
;.byte $01,$01,$01,$01,$01,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00
;PT3NoteTable_ASM_34_35_low:
;.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8
;.byte $3B,$C5,$55,$EC,$88,$2A,$D2,$7E
;.byte $2F,$E5,$9E,$5C,$1D,$E2,$AB,$76
;.byte $44,$15,$E9,$BF,$98,$72,$4F,$2E
;.byte $0F,$F1,$D5,$BB,$A2,$8B,$74,$60
;.byte $4C,$39,$28,$17,$07,$F9,$EB,$DD
;.byte $D1,$C5,$BA,$B0,$A6,$9D,$94,$8C
;.byte $84,$7C,$75,$6F,$69,$63,$5D,$58
;.byte $53,$4E,$4A,$46,$42,$3E,$3B,$37
;.byte $34,$31,$2F,$2C,$29,$27,$25,$23
;.byte $21,$1F,$1D,$1C,$1A,$19,$17,$16
;.byte $15,$14,$12,$11,$10,$0F,$0E,$0D
2019-05-07 15:17:46 +00:00
;PT3VolumeTable_33_34:
;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1
;.byte $0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2
;.byte $0,$0,$0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3
;.byte $0,$0,$0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4
;.byte $0,$0,$0,$1,$1,$1,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5
;.byte $0,$0,$0,$1,$1,$2,$2,$3,$3,$3,$4,$4,$5,$5,$6,$6
;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7
;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$5,$5,$6,$6,$7,$7,$8
;.byte $0,$0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$6,$7,$8,$8,$9
;.byte $0,$0,$1,$2,$2,$3,$4,$4,$5,$6,$6,$7,$8,$8,$9,$A
;.byte $0,$0,$1,$2,$3,$3,$4,$5,$6,$6,$7,$8,$9,$9,$A,$B
;.byte $0,$0,$1,$2,$3,$4,$4,$5,$6,$7,$8,$8,$9,$A,$B,$C
;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D
;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E
;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F
;PT3VolumeTable_35:
;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1
;.byte $0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1,$2,$2,$2,$2
;.byte $0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2,$3,$3,$3
;.byte $0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3,$4,$4
;.byte $0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5
;.byte $0,$0,$1,$1,$2,$2,$2,$3,$3,$4,$4,$4,$5,$5,$6,$6
;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7
;.byte $0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7,$8
;.byte $0,$1,$1,$2,$2,$3,$4,$4,$5,$5,$6,$7,$7,$8,$8,$9
;.byte $0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$7,$7,$8,$9,$9,$A
;.byte $0,$1,$1,$2,$3,$4,$4,$5,$6,$7,$7,$8,$9,$A,$A,$B
;.byte $0,$1,$2,$2,$3,$4,$5,$6,$6,$7,$8,$9,$A,$A,$B,$C
;.byte $0,$1,$2,$3,$3,$4,$5,$6,$7,$8,$9,$A,$A,$B,$C,$D
;.byte $0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D,$E
;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F