]> git.sur5r.net Git - cc65/blob - libsrc/telestrat/mym.s
Merge telemon24 and telemon30 into telestrat target.
[cc65] / libsrc / telestrat / mym.s
1         .export         _Mym_MusicStart
2                 .importzp sp,tmp2,tmp3,tmp1,ptr1
3                 
4                 .include        "telestrat.inc"
5                 
6 ; To check: AYC
7 ; http://cpcwiki.eu/index.php/AYC
8
9
10
11         
12 _DecodedByte            :=$D0 ; Byte being currently decoded from the MYM stream
13 _DecodeBitCounter       :=$D2           ; Number of bits we can read in the current byte
14 _DecodedResult          :=$D3   ; What is returned by the 'read bits' function
15 _CurrentAYRegister      :=$D4           ; Contains the number of the register being decoded     
16 _RegisterBufferHigh     :=$D5           ; Points to the high byte of the decoded register buffer, increment to move to the next register        
17 _BufferFrameOffset      :=$D6           ; From 0 to 127, used when filling the decoded register buffer
18 _MusicResetCounter      :=$D7           ; 2 bytes Contains the number of rows to play before reseting
19 _CurrentFrame           :=$D9           ; From 0 to 255 and then cycles... the index of the frame to play this vbl
20 _PlayerVbl                      :=$DA
21 _FrameLoadBalancer      :=$DB           ; We depack a new frame every 9 VBLs, this way the 14 registers are evenly depacked over 128 frames
22
23
24 VIA_1                   :=      $30f
25 VIA_2                   :=      $30c
26
27 _MusicData              :=      $c000
28
29 ; mym(char *buf)
30
31
32
33
34 ;
35 ; Current PSG values during unpacking
36 ;
37
38
39 .proc _Mym_MusicStart
40
41         ; The two first bytes of the MYM music is the number of rows in the music
42         ; We decrement that at each frame, and when we reach zero, time to start again.
43         sta ptr1
44         stx ptr1+1
45         
46         ldy #0
47         lda (ptr1),y
48         sta _MusicResetCounter+0
49         iny
50         lda (ptr1),y
51         tax
52         inx
53         stx _MusicResetCounter+1
54         
55         ;ldx _MusicData+0
56         ;stx _MusicResetCounter+0
57         ;ldx _MusicData+1
58         ;inx
59         ;stx _MusicResetCounter+1
60                 
61
62         ; Initialize the read bit counter
63         ldy #2 ; should be useless because we can do iny which earn 1 byte
64         
65         lda ptr1
66         clc
67         adc #2
68         bcc next20
69         inc ptr1+1
70         lda ptr1+1
71         sta __auto_music_ptr+2
72 next20:
73         sta ptr1
74         sta __auto_music_ptr+1
75         
76         
77         
78         ;lda #<(_MusicData+2)
79         ;sta __auto_music_ptr+1
80         ;lda #>(_MusicData+2)
81         ;sta __auto_music_ptr+2
82
83         lda #1
84         sta _DecodeBitCounter
85
86         ; Clear all data
87         lda #0
88         sta _DecodedResult
89         sta _DecodedByte
90         sta _PlayerVbl
91         sta _PlayerRegCurrentValue
92         sta _BufferFrameOffset
93         sta _PlayerCount
94         sta _CurrentAYRegister
95         sta _CurrentFrame
96
97         ldx #14
98 loop_init:
99         dex
100         sta _PlayerRegValues,x
101         bne loop_init
102
103
104         ;
105         ; Unpack the 128 first register frames
106         ;
107         
108         lda #>_PlayerBuffer
109         sta _RegisterBufferHigh
110
111         ldx #0
112 unpack_block_loop:
113         stx _CurrentAYRegister
114         
115         ; Unpack that register
116         jsr _PlayerUnpackRegister2
117
118         ; Next register
119         ldx _CurrentAYRegister
120         inx
121         cpx #14
122         bne unpack_block_loop
123         
124
125         lda #128
126         sta _PlayerVbl+0
127
128         lda #0
129         sta _PlayerCount
130         sta _CurrentAYRegister
131         sta _CurrentFrame
132
133         lda #9
134         sta _FrameLoadBalancer
135
136         lda #1
137         sta _MusicPlaying
138
139         ;
140         ; Install the IRQ
141         ;
142         php
143         sei
144         lda #<_Mym_PlayFrame
145         sta _InterruptCallBack_3+1
146         lda #>_Mym_PlayFrame
147         sta _InterruptCallBack_3+2
148         plp
149
150         rts
151
152
153 _Mym_MusicStop:
154
155         ; Indicate the main code that the music is finished
156         lda #0
157         sta _MusicPlaying
158
159         ; Disable the IRQ so it does not conflict or cause weird things
160         php
161         sei
162         lda #<_DoNothing
163         sta _InterruptCallBack_3+1
164         lda #>_DoNothing
165         sta _InterruptCallBack_3+2
166         plp
167
168         ; Cut the sound so it does not sounds like a dying cat
169
170         ; y=register number
171         ; x=value to write
172         ldy #7 ; Control register
173         ldx #$FF
174         jsr _PsgPlayRegister
175
176         ldy #8  ; Volume A
177         ldx #0
178         jsr _PsgPlayRegister
179
180         ldy #9  ; Volume B
181         ldx #0
182         jsr _PsgPlayRegister
183
184         ldy #10 ; Volume C
185         ldx #0
186         jsr _PsgPlayRegister
187         rts
188
189
190 _Mym_PlayFrame:
191
192         ;
193         ; Check for end of music
194         ; CountZero: $81,$0d
195         dec _MusicResetCounter+0
196         bne music_contines
197         dec _MusicResetCounter+1
198         bne music_contines
199
200 music_resets:
201         jmp _Mym_MusicStop
202         
203 music_contines:
204
205         ;
206         ; Play a frame of 14 registers
207         ;
208         
209         lda _CurrentFrame
210         sta _auto_psg_play_read+1
211         lda #>_PlayerBuffer
212         sta _auto_psg_play_read+2
213
214         ldy #0
215 register_loop:
216
217 _auto_psg_play_read:
218         ldx     _PlayerBuffer
219
220         ; y=register number
221         ; x=value to write
222         jsr _PsgPlayRegister
223
224         inc _auto_psg_play_read+2 
225         iny
226         cpy #14
227         bne register_loop
228         
229
230
231         inc _CurrentFrame
232         inc _PlayerCount
233
234         lda _CurrentAYRegister
235         cmp #14
236         bcs end_reg
237
238         
239         dec _FrameLoadBalancer
240         bne end
241
242         jsr _PlayerUnpackRegister
243         inc _CurrentAYRegister
244         lda #9
245         sta _FrameLoadBalancer
246 end:    
247         rts
248         
249
250 end_reg:
251         
252         lda _PlayerCount
253         cmp #128
254         bcc skip2
255
256         lda #0
257         sta _CurrentAYRegister
258         sta _PlayerCount
259         lda #9
260         sta _FrameLoadBalancer
261         
262         clc
263         lda _PlayerVbl+0
264         adc #128
265         sta _PlayerVbl+0
266 skip2:
267         
268
269         rts
270
271
272
273 ; y=register number
274 ; x=value to write
275 _PsgPlayRegister:
276
277         sty     VIA_1
278         txa
279
280         pha
281         lda     VIA_2
282         ora     #$EE            ; $EE   238     11101110
283         sta     VIA_2
284
285         and     #$11            ; $11   17      00010001
286         ora     #$CC            ; $CC   204     11001100
287         sta     VIA_2
288
289         tax
290         pla
291         sta     VIA_1
292         txa
293         ora     #$EC            ; $EC   236     11101100
294         sta     VIA_2
295
296         and     #$11            ; $11   17      00010001
297         ora     #$CC            ; $CC   204     11001100
298         sta     VIA_2
299
300         rts
301
302
303
304
305 ;
306 ; Initialise X with the number of bits to read
307 ; Y is not modifier
308 ;
309 _ReadBits:
310
311         lda #0
312         sta _DecodedResult
313
314         ; Will iterate X times (number of bits to read)
315 loop_read_bits:
316
317         dec _DecodeBitCounter
318         beq get_next_byte
319
320 shift_bit:
321         asl _DecodedByte
322         rol _DecodedResult
323
324         dex
325         bne loop_read_bits
326         rts
327
328 get_next_byte:
329         ; reset mask
330         lda #8
331         sta _DecodeBitCounter
332
333         ; fetch a new byte, and increment the adress.
334 __auto_music_ptr:
335         lda _MusicData+2
336         sta _DecodedByte
337
338         inc __auto_music_ptr+1
339         bne shift_bit
340         inc __auto_music_ptr+2
341         jmp shift_bit
342
343
344
345
346
347 _PlayerUnpackRegister:
348         lda #>_PlayerBuffer
349         clc
350         adc _CurrentAYRegister
351         sta _RegisterBufferHigh
352 _PlayerUnpackRegister2:
353         ;
354         ; Init register bit count and current value
355         ;        
356         ldx _CurrentAYRegister
357         lda _PlayerRegValues,x
358         sta _PlayerRegCurrentValue  
359         
360
361         ;
362         ; Check if it's packed or not
363         ; and call adequate routine...
364         ;
365         ldx #1
366         jsr _ReadBits
367         ldx _DecodedResult
368         bne DecompressFragment
369
370         
371 UnchangedFragment:
372
373         ;
374         ; No change at all, just repeat '_PlayerRegCurrentValue' 128 times 
375         ;
376         lda _RegisterBufferHigh                         ; highpart of buffer adress + register number
377         sta __auto_copy_unchanged_write+2
378
379         ldx #128                                                        ; 128 iterations
380         lda _PlayerRegCurrentValue                      ; Value to write
381
382         ldy _PlayerVbl
383         
384 repeat_loop:
385 __auto_copy_unchanged_write:
386         sta _PlayerBuffer,y
387         iny     
388         dex
389         bne repeat_loop
390
391
392         jmp player_main_return
393
394         
395 player_main_return:
396         ; Write back register current value
397         ldx _CurrentAYRegister
398         lda _PlayerRegCurrentValue  
399         sta _PlayerRegValues,x
400
401         ; Move to the next register buffer
402         inc _RegisterBufferHigh
403         rts
404
405
406
407
408 DecompressFragment:
409         lda _PlayerVbl                                          ; Either 0 or 128 at this point else we have a problem...
410         sta _BufferFrameOffset
411
412 decompressFragmentLoop:
413         
414 player_copy_packed_loop:
415         ; Check packing method
416         ldx #1
417         jsr _ReadBits
418
419         ldx _DecodedResult
420         bne PlayerNotCopyLast
421
422 UnchangedRegister:
423
424         ; We just copy the current value 128 times
425         lda _RegisterBufferHigh                         ; highpart of buffer adress + register number
426         sta __auto_player_copy_last+2
427
428         ldx _BufferFrameOffset                          ; Value between 00 and 7f
429         lda _PlayerRegCurrentValue                      ; Value to copy
430 __auto_player_copy_last:
431         sta _PlayerBuffer,x
432
433         inc _BufferFrameOffset
434
435
436
437 player_return:
438
439         ; Check end of loop
440         lda _BufferFrameOffset
441         and #127
442         bne decompressFragmentLoop
443
444         jmp player_main_return
445
446
447 PlayerNotCopyLast:
448         ; Check packing method
449         ldx #1
450         jsr _ReadBits
451
452         ldx _DecodedResult
453         beq DecompressWithOffset
454
455 ReadNewRegisterValue:
456         ; Read new register value (variable bit count)
457         ldx _CurrentAYRegister
458         lda _PlayerRegBits,x
459         tax
460         jsr _ReadBits
461         ldx _DecodedResult
462         stx _PlayerRegCurrentValue
463
464         ; Copy to stream
465         lda _RegisterBufferHigh                         ; highpart of buffer adress + register number
466         sta __auto_player_read_new+2
467
468         ldx _BufferFrameOffset                          ; Value between 00 and 7f
469         lda _PlayerRegCurrentValue                      ; New value to write
470 __auto_player_read_new:
471         sta _PlayerBuffer,x
472
473         inc _BufferFrameOffset
474         jmp player_return
475
476
477
478
479 DecompressWithOffset:
480
481         ; Read Offset (0 to 127)
482         ldx #7
483         jsr _ReadBits                                   
484
485         lda _RegisterBufferHigh                 ; highpart of buffer adress + register number
486         sta __auto_write+2                              ; Write adress
487         sta __auto_read+2                               ; Read adress
488
489         ; Compute wrap around offset...
490         lda _BufferFrameOffset                          ; between 0 and 255
491         clc
492         adc _DecodedResult                                      ; + Offset Between 00 and 7f
493         sec
494         sbc #128                                                        ; -128
495         tay
496
497         ; Read count (7 bits)
498         ldx #7
499         jsr _ReadBits
500         
501         inc     _DecodedResult                                  ; 1 to 129
502
503
504         ldx _BufferFrameOffset
505         
506 player_copy_offset_loop:
507
508 __auto_read:
509         lda _PlayerBuffer,y                             ; Y for reading
510         iny
511
512 __auto_write:
513         sta _PlayerBuffer,x                             ; X for writing
514
515         inx
516         dec _DecodedResult
517         bne player_copy_offset_loop 
518
519         stx _BufferFrameOffset
520         sta _PlayerRegCurrentValue
521
522         jmp player_return
523
524
525
526
527 ;
528 ; Size in bits of each PSG register
529 ;
530 _PlayerRegBits:
531         ; Chanel A Frequency
532         .byt 8
533         .byt 4
534
535         ; Chanel B Frequency
536         .byt 8
537         .byt 4 
538
539         ; Chanel C Frequency
540         .byt 8
541         .byt 4
542
543         ; Chanel sound generator
544         .byt 5
545
546         ; select
547         .byt 8 
548
549         ; Volume A,B,C
550         .byt 5
551         .byt 5
552         .byt 5
553
554         ; Wave period
555         .byt 8 
556         .byt 8
557
558         ; Wave form
559         .byt 8
560
561 _PlayerCount:
562         .res 1,0 ; must be equal to 0
563 _MusicPlaying:
564         .res 1,0 ; must be equal to 0
565         
566
567 _PlayerRegValues:
568 _RegisterChanAFrequency:
569         ; Chanel A Frequency
570         .res 1,8
571         .res 1,4
572
573 _RegisterChanBFrequency:
574         ; Chanel B Frequency
575         .res 1,8
576         .res 1,4
577
578 _RegisterChanCFrequency:
579         ; Chanel C Frequency
580         .res 1,8
581         .res 1,4
582
583 _RegisterChanNoiseFrequency:
584         ; Chanel sound generator
585         .res 1,5
586
587         ; select
588         .res 1,8
589
590         ; Volume A,B,C
591 _RegisterChanAVolume:
592         .res 1,5
593 _RegisterChanBVolume:
594         .res 1,5
595 _RegisterChanCVolume:
596         .res 1,5
597
598         ; Wave period
599         .res 1,8
600         .res 1,8
601
602         ; Wave form
603         .res 1,8
604
605 _PlayerRegCurrentValue:
606         .res 1,0
607 _DoNothing:
608         rts     
609
610 _InterruptCallBack_3:           ; Used by the music player
611         jsr _DoNothing                  ; Transformed to "jsr _Mym_PlayFrame" -> 12 cycles
612         
613 ;       jsr MiniScrollLoading   ; -> 338 cycles
614
615         pla
616         tay
617         pla
618         tax
619         pla
620
621         rti
622 _PlayerBuffer:  
623         .res 256*14                     ; About 3.5 kilobytes somewhere in memory, we put the music file in overlay memory
624         
625 .endproc        
626