; ---------------------------------------------------------------------------
; ReSeT #10 YMZ Test
; ---------------------------------------------------------------------------
    LIST
    include "firmware.i"
    include "hardware.i"
    include "supergrafx.i"
    include "macros.i"

; ---------------------------------------------------------------------------
start
    ; Get active disk drive and save it for later
    LD   HL,(AMSDOS_RESERVED_AREA)
    LD   A,(HL)                 ; Active disk drive for Amsdos (0 = A / 1 = B)
    LD   (disk_drive + 1),A
restart
    LD   C,$FF                  ; Disable ROMs
    LD   HL,main_program        ; HL = Start program address
    CALL MC_START_PROGRAM       ; Run program

main_program
    CALL TXT_VDU_DISABLE        ; Disable VDU
    CALL KL_ROM_WALK            ; Enable ROMS
    CALL TXT_VDU_ENABLE         ; Enable VDU

    ; Set active diskdrive for the Amsdos (the same used for load this program)
disk_drive
    LD   A,0
    LD   HL,(AMSDOS_RESERVED_AREA)
    LD   (HL),A

    ; Load the songs using the firmware
    CALL load_songs

    ; Show menu
    CALL print_text

    CALL $BD19
    HALT
    
    ; Set a null interrupt handler
    DI
    LD   A,$FB              ; EI (1)
    LD   HL,$4DED           ; RETI (4)
    LD   ($0038),A
    LD   ($0039),HL
    EI

    ; Set ZX PSG frequency in the YMZs
    LD   BC,CTC_TIM0
    LD   HL,CTC_START_COUNTER * 256 + 4
    OUT  (C),H                      ; Set Timer 0 as clock for the YMZs
    OUT  (C),L                      ; Set the clock to 1,75 MHz (ZX frequency)

    CALL select_song_02

main_loop
    ; Wait until not key is pressed
    CALL no_key_press

    ; Select RAM page
.ram_page
    LD   BC,GATE_ARRAY
    OUT  (C),C

    ; Initialize Song
    LD   A,%00010000    ; 2 x PT3 TS | ABC | Loop Song
    LD   (TS_SETUP),A   ; Set the TS_SETUP variable

.val_1st_song
    LD   HL,$0000       ; Pointer to the song or the first song in 2xPT3

.val_2nd_song
    LD   DE,$0000       ; Pointer to the second song in 2xPT3
    CALL TS_Init

.play_loop    
    ; Wait refresh
    CALL wait_vblank
    HALT
    
    ; Read function keys
    CALL read_function_keys

    ; Process function keys
    CALL process_function_keys
    JR   Z,main_loop

    ; Center Raster
    HALT
    HALT

    LD   BC,GATE_ARRAY + BORDER
    OUT  (C),C
    LD   A,R
    AND  $1F
    OR   INK
    OUT  (C),A

    ; Play Song
    CALL TS_Play

    LD   A,BORDER
    LD   BC,GATE_ARRAY + INK + NEGRO
    OUT  (C),A
    OUT  (C),C

    ; Update Vumeters
    CALL update_vumeters

    JP   .play_loop

; ---------------------------------------------------------------------------
update_vumeters
    LD   A,(VARS1+VRS.AYREGS+AmplA)
    LD   DE,$EF80
    CALL set_vumeter

    LD   A,(VARS1+VRS.AYREGS+AmplB)
    LD   DE,$F780
    CALL set_vumeter

    LD   A,(VARS1+VRS.AYREGS+AmplC)
    LD   DE,$FF80
    CALL set_vumeter

    LD   A,(VARS2+VRS.AYREGS+AmplA)
    LD   DE,$EF86
    CALL set_vumeter

    LD   A,(VARS2+VRS.AYREGS+AmplB)
    LD   DE,$F786
    CALL set_vumeter

    LD   A,(VARS2+VRS.AYREGS+AmplC)
    LD   DE,$FF86
    CALL set_vumeter

    RET

set_vumeter
    CP   16
    JR   C,.continue
    LD   A,16
.continue
    ADD  A,A
    ADD  A,A
    LD   HL,vumeter_table
    ADD  A,L
    JR   NC,.no_carry
    INC  H
.no_carry
    LD   L,A
    LD   BC,4
    LDIR
    RET

vumeter_table
    DEFB $00,$00,$00,$00    ; 0
    DEFB $08,$00,$00,$00    ; 1
    DEFB $0C,$00,$00,$00    ; 2
    DEFB $0E,$00,$00,$00    ; 3

    DEFB $0F,$00,$00,$00    ; 4
    DEFB $0F,$08,$00,$00    ; 5
    DEFB $0F,$0C,$00,$00    ; 6
    DEFB $0F,$0E,$00,$00    ; 7

    DEFB $0F,$0F,$00,$00    ; 8
    DEFB $0F,$0F,$08,$00    ; 9
    DEFB $0F,$0F,$0C,$00    ; 10
    DEFB $0F,$0F,$0E,$00    ; 11

    DEFB $0F,$0F,$0F,$00    ; 12
    DEFB $0F,$0F,$0F,$08    ; 13
    DEFB $0F,$0F,$0F,$0C    ; 14
    DEFB $0F,$0F,$0F,$0E    ; 15

    DEFB $0F,$0F,$0F,$0F    ; 16

; ---------------------------------------------------------------------------
; Wait refresh
wait_vblank
    LD   B,>PPI_B
.loop_wait_vblank
    IN   A,(C)
    RRA
    JR   NC,.loop_wait_vblank
    RET

; ---------------------------------------------------------------------------
; Turbo Sound Player
    include "PTSPlay_CPC.asm"

; ---------------------------------------------------------------------------
    ; "PT3!" + First song length + "PT3!" + Second song length + "02TS"
;    $C4
;    insane      $4000, $4000 + $11A0
;    turbodance  $4000 + 9545, $4000 + 9545 + $0D36
select_song_02
    LD   A,$C4                  ; RAM page
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000               ; First Song
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + $11A0       ; Second Song
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_01
    LD   A,$C4
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000 + 9545
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + 9545 + $0D36
    LD   (main_loop.val_2nd_song + 1),HL
    RET

;    $C5
;    lgwbyb      $4000, $4000 + $1446
;    dncdick     $4000 + 9477, $4000 + 9477 + $0BB6
select_song_03
    LD   A,$C5
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + $1446
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_04
    LD   A,$C5
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000 + 9477
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + 9477 + $0BB6
    LD   (main_loop.val_2nd_song + 1),HL
    RET
    
;    $C6
;    goddy       $4000, $4000 + $1505
;    trotil      $4000 + 9292, $4000 + 9292 + $0EF5
select_song_06
    LD   A,$C6
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + $1505
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_05
    LD   A,$C6
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000 + 9292
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + 9292 + $0EF5
    LD   (main_loop.val_2nd_song + 1),HL
    RET

;    $C7
;    raketa      $4000, $4000 + $0BBE
;    over        $4000 + 5907, $4000 + 5907 + $0BF5
;    krwrk       $4000 + 5907 + 5643, $4000 + 5907 + 5643 + $07B0
select_song_07
    LD   A,$C7
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + $0BBE
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_09
    LD   A,$C7
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000 + 5907
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + 5907 + $0BF5
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_08
    LD   A,$C7
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000 + 5907 + 5643
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + 5907 + 5643 + $07B0
    LD   (main_loop.val_2nd_song + 1),HL
    RET

select_song_10
    LD   A,$C0
    LD   (main_loop.ram_page + 1),A
    LD   HL,$4000
    LD   (main_loop.val_1st_song + 1),HL
    LD   HL,$4000 + $2073
    LD   (main_loop.val_2nd_song + 1),HL
    RET

; ---------------------------------------------------------------------------
; Read function keys
; ---------------------------------------------------------------------------
read_function_keys
    LD   HL,fkeys_buffer                        ; Storage functions keys

    ; Select the PSG IOPORT_A
    LD   BC,PPI_A + PSG_IOPORT_A
    OUT  (C),C

    ; Select PSG Register
    LD   BC,PPI_C + PPI_PSG_SELECT
    OUT  (C),C

    ; PSG Inactive
    OUT  (C),0                                  ; DEFB ($ED,$71)

    ; Set the PPI_A in input mode
    LD   BC,PPI_CONTROL + PPI_A_INPUT
    OUT  (C),C

    ; Check function keys
    LD   BC,PPI_C + PPI_PSG_READ + KEY_LINE0
    OUT  (C),C                  
    LD   B,>PPI_A
    IN   B,(C)                                  ; B = byte received
    LD   (HL),B                                 ; Save Key line 0
    INC  HL

    LD   BC,PPI_C + PPI_PSG_READ + KEY_LINE1
    OUT  (C),C                  
    LD   B,>PPI_A
    IN   B,(C)                                  ; B = byte received
    LD   (HL),B                                 ; Save Key line 1
    INC  HL

    LD   BC,PPI_C + PPI_PSG_READ + KEY_LINE2
    OUT  (C),C                  
    LD   B,>PPI_A
    IN   B,(C)                                  ; B = byte received
    LD   (HL),B                                 ; Save Key line 2

    ; Set the PPI_A in output mode
    LD   BC,PPI_CONTROL + PPI_A_OUTPUT
    OUT  (C),C

    ; PSG Inactive (Needed in CPC+)
    DEC  B                                      ; B = PPI_C
    OUT  (C),0                                  ; DEFB $ED,$71
    
    RET

fkeys_buffer
    DEFS 3

; ---------------------------------------------------------------------------
; Test if any key is pressed, except SHIFT & COPY. And marking in Carry flag.
; ---------------------------------------------------------------------------
anykey_press
    INIT_PSG_FOR_SCANKEYS
    LD   D,%01000000            ; Key line 0 - 9
.loop_anykey_press
    LD   B,>PPI_C
    OUT  (C),D                  ; Send Key line
    LD   B,>PPI_A
    IN   C,(C)                  ; Read Key line
    LD   A,D
.test_copy_key
    CP   %01000001              ; Is the COPY line?
    JR   NZ,.test_shift_key
.skip_copy_key
    SET  KEY_COPY,C
    JR   .no_more_special_keys
.test_shift_key
    CP   %01000010              ; Is the SHIFT line?
    JR   NZ,.test_joy0_fire1
.skip_shift_key
    SET  KEY_SHIFT,C
    JR   .no_more_special_keys
.test_joy0_fire1
    CP   %01001001              ; Is the JOY0 line?
    JR   NZ,.no_more_special_keys
.skip_joy0_fire1
    SET  JOY_FIRE1,C
.no_more_special_keys
    LD   A,C
    CPL
    AND  A
    JR   NZ,.key_press
    INC  D
    LD   A,%01001010
    CP   D
    JR   NZ,.loop_anykey_press
    JR   .no_key_press
.key_press
    SCF
    JR   .end_anykey_press
.no_key_press
    AND  A
.end_anykey_press
    RESTORE_PSG_OF_SCANKEYS
    RET

; ---------------------------------------------------------------------------
; Wait until no key is pressed
; ---------------------------------------------------------------------------
no_key_press
    CALL anykey_press
    JR   C,no_key_press
    RET

; ---------------------------------------------------------------------------
; Process function keys
; ---------------------------------------------------------------------------
process_function_keys
    LD   HL,fkeys_buffer
.test_line_0
    LD   A,(HL)
    LD   (HL),$FF
    INC  HL
    CPL
    AND  %00111000
    JR   Z,.test_line_1
.test_f3
    BIT  KEY_F3,A
    JR   Z,.test_f6
.is_f3
    LD   HL,select_song_03
    JR   .change_song
.test_f6
    BIT  KEY_F6,A
    JR   Z,.test_f9
.is_f6
    LD   HL,select_song_06
    JR   .change_song
.test_f9
    BIT  KEY_F9,A
    JR   Z,.test_line_1
.is_f9
    LD   HL,select_song_09
    JR   .change_song

.test_line_1
    LD   A,(HL)
    LD   (HL),$FF
    INC  HL
    CPL
    AND  %11111100
    JR   Z,.test_line_2

.test_f0
    RLA
    JR   NC,.test_f2
.is_f0
    LD   HL,select_song_10
    JR   .change_song
.test_f2
    RLA
    JR   NC,.test_f1
.is_f2
    LD   HL,select_song_02
    JR   .change_song
.test_f1
    RLA
    JR   NC,.test_f5
.is_f1
    LD   HL,select_song_01
    JR   .change_song
.test_f5
    RLA
    JR   NC,.test_f8
.is_f5
    LD   HL,select_song_05
    JR   .change_song
.test_f8
    RLA
    JR   NC,.test_f7
.is_f8
    LD   HL,select_song_08
    JR   .change_song
.test_f7
    RLA
    JR   NC,.test_line_2
.is_f7
    LD   HL,select_song_07
    JR   .change_song

.test_line_2
    LD   A,(HL)
    LD   (HL),$FF
    BIT  KEY_F4,A
    RET  NZ             ; NZ = Function key no pressed
.is_f4
    LD   HL,select_song_04

.change_song
    LD   (.sm_select_song + 1),HL

    ; Stop song and select a new one
    CALL TS_Stop
.sm_select_song
    CALL $0000

    XOR  A              ; Z
    RET

; ---------------------------------------------------------------------------
decrunch
    include "aplib_cpc_old.s"

; ---------------------------------------------------------------------------
; Imprime una cadena terminada en $FF usando el firmware
; Entradas:
;    HL : Puntero a la cadena
; ---------------------------------------------------------------------------
print_text
    LD   HL,texto_menu
    LD   A,(HL)
.loop_print_text
    CALL TXT_OUTPUT
    INC  HL
    LD   A,(HL)
.continue_print_text
    CP   $FF
    JR   NZ,.loop_print_text
    RET

texto_menu
    DEFB $1C,$00,$00,$00    ; INK 0,0,0     (Negro)
    DEFB $1C,$01,$00,$00    ; INK 1,0,0     (Negro)
    DEFB $1C,$02,$00,$00    ; INK 2,0,0     (Negro)
    DEFB $1C,$03,$00,$00    ; INK 3,0,0     (Negro)
    DEFB $1D,$00,$00        ; BORDER 0,0
    DEFB $04,$01            ; MODE 1
    ; Textos
    DEFB $1F,1,1            ; LOCATE x,y 40 - 22 / 2
    DEFB $0F,3              ; Pen 3
    DEFB "- 6 Channels Music Player  (ReSeT #10) -"
    DEFB $1F,28 / 2,3
    DEFB $0F,2,"SELECT MUSIC"
    DEFB $1F,28 / 2,4
    DEFB $0F,2,"------------"
    DEFB $1F,2,6
    DEFB $0F,$01,"F1.-",$0F,$02," Meat Grinder"
    DEFB $1F,27,6
    DEFB $0F,$01,"F2.-",$0F,$02," Insane"

    DEFB $1F,2,8
    DEFB $0F,$01,"F3.-",$0F,$02," Little Girl"
    DEFB $1F,27,8
    DEFB $0F,$01,"F4.-",$0F,$02," Dancing"

    DEFB $1F,2,10
    DEFB $0F,$01,"F5.-",$0F,$02," Trotyl Sausage"
    DEFB $1F,27,10
    DEFB $0F,$01,"F6.-",$0F,$02," Goddy"

    DEFB $1F,2,12
    DEFB $0F,$01,"F7.-",$0F,$02," Lichu Naroketi!"
    DEFB $1F,27,12
    DEFB $0F,$01,"F8.-",$0F,$02," Krwrk"

    DEFB $1F,2,14
    DEFB $0F,$01,"F9.-",$0F,$02," Overloaded"

    DEFB $1F,6,18
    DEFB $0F,$02,"ORIGINAL ZX SONGS BY ",$0F,$01,"Karbofos"
    DEFB $1F,7,20
    DEFB $0F,$02,"HARDWARE CONCEPT BY ",$0F,$01,"TotO"
    DEFB $1F,11,22
    DEFB $0F,$02,"MUSIC PLAYER BY ",$0F,$01,"SyX"

    DEFB $1C,$01,$1A,$1A    ; INK 1,26,26   (Blanco)
    DEFB $1C,$02,$12,$12    ; INK 2,18,18   (Verde)
    DEFB $1C,$03,$18,$18    ; INK 3,24,24   (Amarillo)
    DEFB $FF 

; ---------------------------------------------------------------------------
load_songs
    LD   BC,GATE_ARRAY + $C4
.loop_load_songs
    ; Page RAM
    OUT  (C),C
    PUSH BC

    CALL load_and_decrunch

    ; Update filename
    LD   HL,fin_cancion - 1
    INC  (HL)
    
    ; Check loop
    POP  BC
    INC  C
    LD   A,C
    CP   $C8
    JR   NZ,.loop_load_songs
    LD   C,$C0
    OUT  (C),C
;    RET

load_and_decrunch
    ; Load file
    LD   HL,cancion                             ; HL = address filename
    LD   B,fin_cancion - cancion                ; B = length filename
    CALL CAS_IN_OPEN
    LD   HL,$8000                               ; HL = load address
    CALL CAS_IN_DIRECT
    CALL CAS_IN_CLOSE 

    ; Decrunch file
    LD   HL,$8000
    LD   DE,$4000
    CALL decrunch
    RET
    
cancion
    DEFB "MUSIC.001"
fin_cancion

; ---------------------------------------------------------------------------
    END
