27
27
. equ CH_STREAM_SAVED , (state_ch_stream_saved_pos - state_ch_stream)
28
28
. equ CH_STREAM_START , (state_ch_stream_start - state_ch_stream)
29
29
. equ CH_STREAM_POS , (state_ch_stream_pos - state_ch_stream)
30
+ . equ CH_STREAM_ENTRIES , (state_ch_stream_entries - state_ch_stream)
30
31
. equ CH_STREAM_SIZE , (state_ch_stream_end - state_ch_stream)
31
32
. equ NB_YM2610_CHANNELS , 14
32
33
@@ -75,6 +76,13 @@ state_ch_ctx_switch:: .blkb NB_YM2610_CHANNELS
75
76
;;; the NSS data gets a dedicated wait state
76
77
state_ch_wait_rows:: .blkb NB_YM2610_CHANNELS
77
78
79
+ ;;; per-channel wait opcode cache
80
+ ;;; ---
81
+ ;;; Wait value used by the last wait opcode.
82
+ ;;; When multiple streams are used, each YM2610 channel used in
83
+ ;;; the NSS data gets a dedicated wait state
84
+ state_ch_wait_op_val:: .blkb NB_YM2610_CHANNELS
85
+
78
86
;;; per-channel playback state
79
87
;;; ---
80
88
;;; Keep track of positional information for streams.
@@ -87,15 +95,24 @@ state_ch_stream:
87
95
state_ch_stream_saved_pos:: .blkb 2
88
96
state_ch_stream_start:: .blkb 2
89
97
state_ch_stream_pos:: .blkb 2
98
+ state_ch_stream_entries:: .blkb 1
90
99
state_ch_stream_end:
91
100
.blkb CH_STREAM_SIZE * (NB_YM2610_CHANNELS - 1 )
92
101
93
102
;;; addresses/indices that points to state of the currently processed stream
94
103
state_current_ch_ctx:: .blkb 2
95
104
state_current_ch_wait_rows:: .blkb 2
105
+ state_current_ch_wait_op_val:: .blkb 2
96
106
state_current_ch_stream:: .blkb 2
97
107
state_stream_idx:: .blkb 1
98
108
109
+ ;;; generic function pointer for current NSS processing function
110
+ state_nss_process::
111
+ .blkb 1 ; jp
112
+ state_nss_process_func::
113
+ .blkb 2 ; func offset in ROM
114
+
115
+
99
116
;; FIXME: temporary padding to ensures the next data sticks into
100
117
;; a single 256 byte boundary to make 16bit arithmetic faster
101
118
.blkb 70
@@ -109,6 +126,8 @@ init_stream_state_tracker::
109
126
ld (state_stream_in_use) , a
110
127
ld bc , # 0
111
128
ld (state_stream_instruments) , bc
129
+ ld a , # 0xc3 ; jp
130
+ ld (state_nss_process) , a
112
131
;; init nss subsystems that may get called prior to playing music
113
132
call init_nss_fm_state_tracker
114
133
ret
@@ -151,6 +170,8 @@ process_streams_opcodes::
151
170
ld (state_stream_idx) , a
152
171
ld bc , #state_ch_wait_rows
153
172
ld (state_current_ch_wait_rows) , bc
173
+ ld bc , #state_ch_wait_op_val
174
+ ld (state_current_ch_wait_op_val) , bc
154
175
ld bc , #state_ch_ctx_switch
155
176
ld (state_current_ch_ctx) , bc
156
177
ld bc , #state_ch_stream
@@ -175,7 +196,7 @@ _loop_chs:
175
196
ld l , CH_STREAM_POS(iy)
176
197
ld h , CH_STREAM_POS + 1 (iy)
177
198
_loop_opcode:
178
- call process_nss_opcode
199
+ call state_nss_process
179
200
or a
180
201
jp nz , _loop_opcode
181
202
;; no more opcodes can be processed, save stream's new pos
@@ -193,6 +214,9 @@ _post_ch_process:
193
214
ld hl , (state_current_ch_wait_rows)
194
215
inc hl
195
216
ld (state_current_ch_wait_rows) , hl
217
+ ld hl , (state_current_ch_wait_op_val)
218
+ inc hl
219
+ ld (state_current_ch_wait_op_val) , hl
196
220
ld hl , (state_current_ch_ctx)
197
221
inc hl
198
222
ld (state_current_ch_ctx) , hl
@@ -397,6 +421,10 @@ stream_play_multi::
397
421
push iy
398
422
pop hl
399
423
424
+ ;; setup the generic NSS processing function
425
+ ld bc , #process_nss_opcode
426
+ ld (state_nss_process_func) , bc
427
+
400
428
;; init streams state
401
429
ld iy , #state_ch_stream
402
430
ld de , #CH_STREAM_SIZE
@@ -460,13 +488,13 @@ nss_opcodes:
460
488
.nss_op nss_jmp
461
489
.nss_op nss_end
462
490
.nss_op timer_tempo
463
- .nss_op wait_rows
491
+ .nss_op wait_n_rows
464
492
.nss_op nss_call
465
493
.nss_op nss_ret
466
494
.nss_op nss_nop
467
495
.nss_op row_speed
468
496
.nss_op row_groove
469
- .nss_op nss_nop2
497
+ .nss_op wait_last_rows
470
498
.nss_op adpcm_b_instrument
471
499
.nss_op adpcm_b_note_on
472
500
.nss_op adpcm_b_note_off
@@ -533,6 +561,10 @@ nss_opcodes:
533
561
.nss_op adpcm_a_pan
534
562
.nss_op adpcm_b_pan
535
563
.nss_op adpcm_b_vibrato
564
+ .nss_op nss_call_table
565
+ .nss_op fm_note_on_and_wait
566
+ .nss_op ssg_note_on_and_wait
567
+ .nss_op adpcm_a_on_and_wait
536
568
537
569
538
570
@@ -630,16 +662,19 @@ nss_end::
630
662
ret
631
663
632
664
633
- ;;; WAIT_ROWS
665
+ ;;; WAIT_N_ROWS
634
666
;;; Suspend stream playback, resume after a number of rows
635
667
;;; worth of time has passed (Timer B interrupts * speed).
636
668
;;; ------
637
669
;;; [hl]: number of interrupts until playback resumes
638
- wait_rows ::
670
+ wait_n_rows ::
639
671
push bc
640
672
;; how many interrupts to wait for before moving on
641
673
ld a , (hl)
642
674
inc hl
675
+ ;; recall this wait value for this channel
676
+ ld bc , (state_current_ch_wait_op_val)
677
+ ld (bc) , a
643
678
;; register the wait for this channel
644
679
ld bc , (state_current_ch_wait_rows)
645
680
ld (bc) , a
@@ -654,6 +689,22 @@ _post_wait_rows:
654
689
ret
655
690
656
691
692
+ ;;; WAIT_LAST_ROWS
693
+ ;;; Suspend stream playback, resume after a number of rows
694
+ ;;; worth of time has passed (same as the last wait_n_rows)
695
+ ;;; ------
696
+ wait_last_rows::
697
+ push bc
698
+ ;; last wait for this channel
699
+ ld bc , (state_current_ch_wait_op_val)
700
+ ld a , (bc)
701
+ ;; register the wait for this channel
702
+ ld bc , (state_current_ch_wait_rows)
703
+ ld (bc) , a
704
+
705
+ jp _post_wait_rows
706
+
707
+
657
708
;;; NSS_CALL
658
709
;;; Continue playback to a new position in the stream
659
710
;;; Recall the current position so that a NSS_RET opcode
@@ -687,6 +738,82 @@ nss_call::
687
738
ret
688
739
689
740
741
+ ;;; NSS_CALL_TABLE
742
+ ;;; Set up a series of calls to different locations in the stream
743
+ ;;; ------
744
+ ;;; [ hl ]: number of calls
745
+ nss_call_table::
746
+ ;; bc: number of calls
747
+ ld a , (hl)
748
+ inc hl
749
+
750
+ ;; recall the number of entries in the call table
751
+ ld iy , (state_current_ch_stream)
752
+ ld CH_STREAM_ENTRIES(iy) , a
753
+
754
+ push bc
755
+ ld bc , #process_table_entry
756
+ ld (state_nss_process_func) , bc
757
+ pop bc
758
+
759
+ ld a , # 1
760
+ ret
761
+
762
+
763
+ ;;; Continue playback to a new position in the stream
764
+ ;;; Recall the current position so that a NSS_RET opcode
765
+ ;;; continues execution from there.
766
+ ;;; Note: no CALL entry can be processed again before a NSS_RET
767
+ ;;; ------
768
+ ;;; [ hl ]: pattern offset in the entry table
769
+ process_table_entry::
770
+ push bc
771
+
772
+ ;; a: entry
773
+ ld a , (hl)
774
+ inc hl
775
+
776
+ ld iy , (state_current_ch_stream)
777
+
778
+ ;; save current stream pos
779
+ ld CH_STREAM_SAVED(iy) , l
780
+ ld CH_STREAM_SAVED + 1 (iy) , h
781
+
782
+ ;; hl: start of stream
783
+ ld l , CH_STREAM_START(iy)
784
+ ld h , CH_STREAM_START + 1 (iy)
785
+
786
+ ;; hl: offset in entry table
787
+ ld b , # 0xff
788
+ ld c , a
789
+ add hl , bc
790
+ add hl , bc
791
+
792
+ ;; bc: pattern offset
793
+ ld c , (hl)
794
+ inc hl
795
+ ld b , (hl)
796
+
797
+ ;; hl: start of stream
798
+ ld l , CH_STREAM_START(iy)
799
+ ld h , CH_STREAM_START + 1 (iy)
800
+
801
+ ;; hl: new pos (call offset)
802
+ add hl , bc
803
+ ld CH_STREAM_POS(iy) , l
804
+ ld CH_STREAM_POS + 1 (iy) , h
805
+
806
+ ;; record that one call entry has been processed
807
+ dec CH_STREAM_ENTRIES(iy)
808
+
809
+ ld bc , #process_nss_opcode
810
+ ld (state_nss_process_func) , bc
811
+
812
+ pop bc
813
+ ld a , # 1
814
+ ret
815
+
816
+
690
817
;;; NSS_RET
691
818
;;; Continue playback past the previous NSS_CALL statement
692
819
;;; ------
@@ -699,6 +826,16 @@ nss_ret::
699
826
ld CH_STREAM_POS(iy) , l
700
827
ld CH_STREAM_POS + 1 (iy) , h
701
828
829
+ push bc
830
+ ld bc , #process_nss_opcode
831
+ xor a
832
+ cp CH_STREAM_ENTRIES(iy)
833
+ jr z , _ret_set_process
834
+ ld bc , #process_table_entry
835
+ _ret_set_process:
836
+ ld (state_nss_process_func) , bc
837
+ pop bc
838
+
702
839
ld a , # 1
703
840
ret
704
841
0 commit comments