From dd392a2cc6d94ddc92d1b165203bba2132375df9 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Thu, 9 May 2019 13:40:54 -0400 Subject: [PATCH] pt3: start adding note decoding --- pt3_player/pt3_lib.s | 384 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 366 insertions(+), 18 deletions(-) diff --git a/pt3_player/pt3_lib.s b/pt3_player/pt3_lib.s index 8d1ecac7..7e05dcb6 100644 --- a/pt3_player/pt3_lib.s +++ b/pt3_player/pt3_lib.s @@ -6,52 +6,85 @@ NOTE_WHICH=0 NOTE_VOLUME=1 -NOTE_TONE_SLIDING=2 -NOTE_ENABLED=3 -NOTE_ENVELOPE_ENABLED=4 -NOTE_SAMPLE_POINTER=5 -NOTE_SAMPLE_LOOP=7 -NOTE_SAMPLE_LENGTH=8 -NOTE_TONE_L=9 -NOTE_TONE_H=10 -NOTE_AMPLITUDE=11 +NOTE_TONE_SLIDING_L=2 +NOTE_TONE_SLIDING_H=3 +NOTE_ENABLED=4 +NOTE_ENVELOPE_ENABLED=5 +NOTE_SAMPLE_POINTER_L=6 +NOTE_SAMPLE_POINTER_H=7 +NOTE_SAMPLE_LOOP=8 +NOTE_SAMPLE_LENGTH=9 +NOTE_TONE_L=10 +NOTE_TONE_H=11 +NOTE_AMPLITUDE=12 +NOTE_NOTE=13 +NOTE_LEN=14 +NOTE_LEN_COUNT=15 +NOTE_SPEC_COMMAND=16 ; is this one needed? +NOTE_NEW_NOTE=17 + note_a: .byte 'A' ; NOTE_WHICH .byte $0 ; NOTE_VOLUME - .byte $0 ; NOTE_TONE_SLIDING + .byte $0 ; NOTE_TONE_SLIDING_L + .byte $0 ; NOTE_TONE_SLIDING_H .byte $0 ; NOTE_ENABLED .byte $0 ; NOTE_ENVELOPE_ENABLED - .word $0 ; NOTE_SAMPLE_POINTER + .byte $0 ; NOTE_SAMPLE_POINTER_L + .byte $0 ; NOTE_SAMPLE_POINTER_H .byte $0 ; NOTE_SAMPLE_LOOP .byte $0 ; NOTE_SAMPLE_LENGTH .byte $0 ; NOTE_TONE_L .byte $0 ; NOTE_TONE_H .byte $0 ; NOTE_AMPLITUDE + .byte $0 ; NOTE_NOTE + .byte $0 ; NOTE_LEN + .byte $0 ; NOTE_LEN_COUNT + .byte $0 ; NOTE_SPEC_COMMAND + .byte $0 ; NOTE_NEW_NOTE + + note_b: .byte 'B' ; NOTE_WHICH .byte $0 ; NOTE_VOLUME - .byte $0 ; NOTE_TONE_SLIDING + .byte $0 ; NOTE_TONE_SLIDING_L + .byte $0 ; NOTE_TONE_SLIDING_H .byte $0 ; NOTE_ENABLED .byte $0 ; NOTE_ENVELOPE_ENABLED - .word $0 ; NOTE_SAMPLE_POINTER + .byte $0 ; NOTE_SAMPLE_POINTER_L + .byte $0 ; NOTE_SAMPLE_POINTER_H .byte $0 ; NOTE_SAMPLE_LOOP .byte $0 ; NOTE_SAMPLE_LENGTH .byte $0 ; NOTE_TONE_L .byte $0 ; NOTE_TONE_H .byte $0 ; NOTE_AMPLITUDE + .byte $0 ; NOTE_NOTE + .byte $0 ; NOTE_LEN + .byte $0 ; NOTE_LEN_COUNT + .byte $0 ; NOTE_SPEC_COMMAND + .byte $0 ; NOTE_NEW_NOTE + note_c: .byte 'C' ; NOTE_WHICH .byte $0 ; NOTE_VOLUME - .byte $0 ; NOTE_TONE_SLIDING + .byte $0 ; NOTE_TONE_SLIDING_L + .byte $0 ; NOTE_TONE_SLIDING_H .byte $0 ; NOTE_ENABLED .byte $0 ; NOTE_ENVELOPE_ENABLED - .word $0 ; NOTE_SAMPLE_POINTER + .byte $0 ; NOTE_SAMPLE_POINTER_L + .byte $0 ; NOTE_SAMPLE_POINTER_H .byte $0 ; NOTE_SAMPLE_LOOP .byte $0 ; NOTE_SAMPLE_LENGTH .byte $0 ; NOTE_TONE_L .byte $0 ; NOTE_TONE_H .byte $0 ; NOTE_AMPLITUDE + .byte $0 ; NOTE_NOTE + .byte $0 ; NOTE_LEN + .byte $0 ; NOTE_LEN_COUNT + .byte $0 ; NOTE_SPEC_COMMAND + .byte $0 ; NOTE_NEW_NOTE + pt3_version: .byte $0 pt3_frequency_table: .byte $0 @@ -98,9 +131,12 @@ pt3_init_song: sta note_b+NOTE_VOLUME sta note_c+NOTE_VOLUME lda #$0 - sta note_a+NOTE_TONE_SLIDING - sta note_b+NOTE_TONE_SLIDING - sta note_c+NOTE_TONE_SLIDING + sta note_a+NOTE_TONE_SLIDING_L + sta note_b+NOTE_TONE_SLIDING_L + sta note_c+NOTE_TONE_SLIDING_L + sta note_a+NOTE_TONE_SLIDING_H + sta note_b+NOTE_TONE_SLIDING_H + sta note_c+NOTE_TONE_SLIDING_H sta note_a+NOTE_ENABLED sta note_b+NOTE_ENABLED sta note_c+NOTE_ENABLED @@ -275,12 +311,312 @@ done_note: rts +prev_note: .byte $0 +prev_sliding_l: .byte $0 +prev_sliding_h: .byte $0 + ;===================================== ; Decode Note ;===================================== decode_note: +; int a_done=0; +; int current_val; + + ; Init vars + + lda #0 + sta note_a+NOTE_NEW_NOTE ; for printing notes? + sta note_a+NOTE_SPEC_COMMAND ; These are only if printing? + + ; Skip decode if note still running + lda note_a+NOTE_LEN_COUNT + beq keep_decoding ; assume not negative + + ; we are still running, decrement and early return + dec note_a+NOTE_LEN_COUNT + rts + +keep_decoding: + + lda note_a+NOTE_NOTE ; store prev note + sta prev_note + + lda note_a+NOTE_TONE_SLIDING_H ; store prev sliding + sta prev_sliding_h + lda note_a+NOTE_TONE_SLIDING_L + sta prev_sliding_l + + +note_decode_loop: +; a->len_count=a->len; + +; current_val=pt3->data[*addr]; +; switch((current_val>>4)&0xf) { +; case 0: +; if (current_val==0x0) { +; a->len_count=0; +; a->all_done=1; +; a_done=1; +; } +; else { /* FIXME: what if multiple spec commands? */ +; /* Doesn't seem to happen in practice */ +; /* But AY_emul has code to handle it */ +; a->spec_command=current_val&0xf; +; } +; break; +; case 1: +; if ((current_val&0xf)==0x0) { +; a->envelope_enabled=0; +; } +; else { +; pt3->envelope_type_old=0x78; +; pt3->envelope_type=(current_val&0xf); + +; (*addr)++; +; current_val=pt3->data[*addr]; +; pt3->envelope_period=(current_val<<8); + +; (*addr)++; + +; current_val=pt3->data[(*addr)]; +; pt3->envelope_period|=(current_val&0xff$ + +; a->envelope_enabled=1; +; pt3->envelope_slide=0; +; pt3->envelope_delay=0; +; } +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->sample=(current_val/2); +; pt3_load_sample(pt3,a->which); + +; a->ornament_position=0; + +; break; +; case 2: +; pt3->noise_period=(current_val&0xf); +; break; +; case 3: +; pt3->noise_period=(current_val&0xf)+0x10; +; break; +; case 4: +; a->ornament=(current_val&0xf); +; pt3_load_ornament(pt3,a->which); +; a->ornament_position=0; +; break; +; case 5: +; case 6: +; case 7: +; case 8: +; case 9: +; case 0xa: +; a->new_note=1; +; a->note=(current_val-0x50); +; a->sample_position=0; +; a->amplitude_sliding=0; +; a->noise_sliding=0; +; a->envelope_sliding=0; +; a->ornament_position=0; +; a->tone_slide_count=0; +; a->tone_sliding=0; +; a->tone_accumulator=0; +; a->onoff=0; +; a->enabled=1; +; a_done=1; +; break; +; case 0xb: +; /* Disable envelope */ +; if (current_val==0xb0) { +; a->envelope_enabled=0; +; a->ornament_position=0; +; } +; /* set len */ +; else if (current_val==0xb1) { +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->len=current_val; +; a->len_count=a->len; +; } +; else { +; a->envelope_enabled=1; +; pt3->envelope_type_old=0x78; +; pt3->envelope_type=(current_val&0xf)-1; +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; pt3->envelope_period=(current_val<<8); +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; pt3->envelope_period|=(current_val&0xff$ +; a->ornament_position=0; +; pt3->envelope_slide=0; +; pt3->envelope_delay=0; +; } +; break; +; case 0xc: /* volume */ +; if ((current_val&0xf)==0) { +; a->sample_position=0; +; a->amplitude_sliding=0; +; a->noise_sliding=0; +; a->envelope_sliding=0; +; a->ornament_position=0; +; a->tone_slide_count=0; +; a->tone_sliding=0; +; a->tone_accumulator=0; +; a->onoff=0; +; a->enabled=0; +; a_done=1; +; } +; else { +; a->volume=current_val&0xf; +; } +; break; +; case 0xd: +; if (current_val==0xd0) { +; a_done=1; +; } +; else { +; a->sample=(current_val&0xf); +; pt3_load_sample(pt3,a->which); +; } +; break; +; case 0xe: +; a->sample=(current_val-0xd0); +; pt3_load_sample(pt3,a->which); +; break; +; case 0xf: +; a->envelope_enabled=0; +; a->ornament=(current_val&0xf); +; pt3_load_ornament(pt3,a->which); +; (*addr)++; +; current_val=pt3->data[*addr]; + +; a->sample=current_val/2; +; a->sample_pointer=pt3->sample_patterns[a->sampl$ +; pt3_load_sample(pt3,a->which); +; break; +; } + +; (*addr)++; +; /* Note, the AYemul code has code to make sure these are applied */ +; /* In the same order they appear. We don't bother? */ +; if (a_done) { +; if (a->spec_command==0x0) { +; } +; /* Tone Down */ +; else if (a->spec_command==0x1) { +; current_val=pt3->data[(*addr)]; +; a->spec_delay=current_val; +; a->tone_slide_delay=current_val; +; a->tone_slide_count=a->tone_slide_delay; +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->spec_lo=(current_val); +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->spec_hi=(current_val); +; a->tone_slide_step=(a->spec_lo)|(a->spec_hi<<8); +; /* Sign Extend */ +; a->tone_slide_step=(a->tone_slide_step<<16)>>16; +; a->simplegliss=1; +; a->onoff=0; +; (*addr)++; +; } +; /* port */ +; else if (a->spec_command==0x2) { +; a->simplegliss=0; +; a->onoff=0; + +; current_val=pt3->data[(*addr)]; +; a->spec_delay=current_val; + +; a->tone_slide_delay=current_val; +; a->tone_slide_count=a->tone_slide_delay; + +; (*addr)++; +; (*addr)++; +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->spec_lo=current_val; + +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->spec_hi=current_val; +; (*addr)++; + +; a->tone_slide_step=(a->spec_hi<<8)|(a->spec_lo); +; /* sign extend */ +; a->tone_slide_step=(a->tone_slide_step<<16)>>16; +; /* abs() */ +; if (a->tone_slide_step<0) a->tone_slide_step=-a$ +; a->tone_delta=GetNoteFreq(a->note,pt3)- +; GetNoteFreq(prev_note,pt3); +; a->slide_to_note=a->note; +; a->note=prev_note; +; if (pt3->version >= 6) { +; a->tone_sliding = prev_sliding; +; } +; if ((a->tone_delta - a->tone_sliding) < 0) { +; a->tone_slide_step = -a->tone_slide_ste$ +; } +; } +; /* Position in Sample */ +; else if (a->spec_command==0x3) { +; current_val=pt3->data[(*addr)]; +; a->sample_position=current_val; +; (*addr)++; +; } +; /* Position in Ornament */ +; else if (a->spec_command==0x4) { +; current_val=pt3->data[(*addr)]; +; a->ornament_position=current_val; +; (*addr)++; +; } +; /* Vibrato */ +; else if (a->spec_command==0x5) { +; current_val=pt3->data[(*addr)]; +; a->onoff_delay=current_val; +; (*addr)++; +; current_val=pt3->data[(*addr)]; +; a->offon_delay=current_val; +; (*addr)++; + +; a->onoff=a->onoff_delay; +; a->tone_slide_count=0; +; a->tone_sliding=0; + +; } +; /* Envelope Down */ +; else if (a->spec_command==0x8) { + +; /* delay? */ +; current_val=pt3->data[(*addr)]; +; pt3->envelope_delay=current_val; +; pt3->envelope_delay_orig=current_val; +; a->spec_delay=current_val; +; (*addr)++; + +; /* Low? */ +; current_val=pt3->data[(*addr)]; +; a->spec_lo=current_val&0xff; +; (*addr)++; + +; /* High? */ +; current_val=pt3->data[(*addr)]; +; a->spec_hi=current_val&0xff; +; (*addr)++; +; pt3->envelope_slide_add=(a->spec_hi<<8)|(a->spe$ +; /* Set Speed */ +; else if (a->spec_command==0x9) { +; current_val=pt3->data[(*addr)]; +; a->spec_lo=current_val; +; pt3->speed=current_val; +; (*addr)++; +; } +; break; +; } + rts ;===================================== @@ -288,6 +624,18 @@ decode_note: ;===================================== pt3_decode_line: + ; decode_note(&pt3->a,&(pt3->a_addr),pt3); + jsr decode_note + + ; decode_note(&pt3->b,&(pt3->b_addr),pt3); + jsr decode_note + + ; decode_note(&pt3->c,&(pt3->c_addr),pt3); + jsr decode_note + +; if (pt3->a.all_done && pt3->b.all_done && pt3->c.all_done) { +; return 1; +; } rts