15700
GAME -> Reflexion
© cpc-power.com (2019)
19.50 / 20.00
 
 
Clevermind
cpc
 
 

Last Update : Saturday 04 April 2020 at 20 h 28

Manual n° 1

SPRITE_HAUTEUR EQU 77 SPRITE_LARGEUR EQU 19 SPRITE_ADR_ECRAN EQU &5B30 tailleraster1 EQU 200 gfx_fonte EQU &7F00 TEMPO EQU 3 TEMPO2 EQU 2 FRAME1 EQU &C000 FRAME2 EQU &C000+1463 FRAME3 EQU &C000+2926 FRAME4 EQU &C000+4389 FRAME5 EQU &C000+5852 FRAME6 EQU &C000+7315 FRAME7 EQU &C000+8778 FRAME8 EQU &C000+10241 ORG &7F80 ;WRITE DIRECT "PRS.BIN" CALL AFF_COULEURS CALL OUT_OVERSCAN CALL EFFET_RIDEAU_R6_VERS_LE_BAS CALL TIR_LANGUE:LD A,25:CALL DELAY CALL LESRASTERS CALL TIR_LANGUE:LD A,25:CALL DELAY CALL EFFET_RIDEAU_R6_VERS_LE_HAUT CALL FRAME CALL OUT_NORMAL RET ;------------------------------------------------------------------------------ ; LES RASTERS ;------------------------------------------------------------------------------ LESRASTERS CALL &BB00 DI ; Desactiver les interruptions LD HL,(&38) ; Lire l'ancienne interruption LD (Sauver),HL ; Sauvegarder la valeur 16 bits LD HL,&C9FB ; Registre 16 bits EI (&FB) + RET (&C9) LD (&38),HL ; Ecrire en &0038 et &0039 le contenu du registre HL EI ; Interruption autorisees .Programme ;raster rotation vers le bas LD A,(Raster1+tailleraster1-1) LD HL,Raster1+tailleraster1-2 LD DE,Raster1+tailleraster1-1 LD BC,tailleraster1-1 LDDR LD (Raster1),A LD B,&F5 ; Se connecter au PPI/8255 port B accessible via &F5xx .Balayage IN A,(C) ; Lire le contenu RRA ; On teste si le bit 0 = 1 JP nc,Balayage ; Si le bit 0 = 0 on boucle jusqu'a la fin du balayage ; On est en haut de l'ecran, on peut continuer le programme ;HALT ; Attendre interruption 1 ;HALT ; Attendre interruption 2 DS 10 ; Debut de ligne LD B,&7F ; On selection le Gate Array LD HL,Raster ; HL pointe sur la table de couleurs .BoucleRaster LD a,(hl) ; On charge la couleur dans A CP &00 ; Si A=0 alors JP z,Touche ; Saute au test clavier LD C,14 OUT (C),C ; Selection encre 14 OUT (C),A ; Ecrire la couleur INC HL ; Couleur suivante dans le tableau DS 42 ; Attendre fin de ligne JP BoucleRaster ; Test touche .Touche LD BC,&F40E OUT (C),C LD BC,&F6C0 OUT (C),C XOR A OUT (C),A LD BC,&F792 OUT (C),C LD BC,&F645 ;ligne 5 OUT (C),C LD B,&F4 IN A,(C) LD BC,&F782 OUT (C),C LD BC,&F600 OUT (C),C RLA ;Charge dans A la valeur du bit 7 (touche ESPACE) JR NC,Sortir LD BC,&F40E OUT (C),C LD BC,&F6C0 OUT (C),C XOR A OUT (C),A LD BC,&F792 OUT (C),C LD BC,&F649 ;ligne 9 OUT (C),C LD B,&F4 IN A,(C) LD BC,&F782 OUT (C),C LD BC,&F600 OUT (C),C RLA ;Charge dans A la valeur du bit 7 (touche DEL) RLA ;Charge dans A la valeur du bit 6 (touche JOY_FIRE0) RLA ;Charge dans A la valeur du bit 5 (touche JOY_FIRE1 Z) RLA ;Charge dans A la valeur du bit 4 (touche JOY_FIRE2 X) JP C,Programme ;Si TIR du joystick n'a pas etait enfonce on boucle .Sortir ;retour au BASIC DI ; Desactiver les interruptions LD HL,(Sauver) ; Restauration des anciennes interruptions LD (&38),hl ; Ecrire EI ; Interruption autorisees RET .Sauver DW #0000 .Raster ;00 = &54 noir ;01 = &44 bleu ;02 = &55 bleu vif ;03 = &5C rouge fonce ;04 = &58 magenta ;05 = &5D mauve ;06 = &4C rouge vif ;07 = &45 pourpre ;08 = &4D magenta vif ;09 = &56 vert ;10 = &46 turquoise ;11 = &57 bleu ciel ;12 = &5E jaune ;13 = &40 gris ;14 = &5F bleu pastel ;15 = &4E orange ;16 = &47 rose ;17 = &4F magenta pastel ;18 = &52 vert vif ;19 = &42 vert marin ;20 = &53 turquoise vif ;21 = &5A vert citron ;22 = &59 vert pastel ;23 = &5B turquoise pastel ;24 = &4A jaune vif ;25 = &43 jaune pastel ;26 = &4B blanc DB &43 ; jaune pastel (mon encre 14) .Raster1 ;raster 8x25=200 DB &5E,&5E,&4C,&5E,&5E,&4C,&5E,&4C DB &4C,&4C,&4C,&45,&4C,&4C,&45,&4C DB &45,&45,&4C,&45,&45,&45,&45,&4D DB &45,&45,&4D,&45,&4D,&4D,&45,&4D DB &4D,&4F,&4D,&4D,&4F,&4D,&4F,&4F DB &4D,&4F,&4F,&4F,&47,&4F,&4F,&47 DB &4F,&47,&47,&4F,&47,&47,&47,&47 DB &47,&47,&47,&4E,&47,&47,&4E,&47 DB &4E,&4E,&47,&4E,&4E,&5E,&4E,&4E DB &5E,&4E,&5E,&5E,&4E,&5E,&5E,&5E DB &5E,&5E,&56,&5E,&5E,&56,&5E,&56 DB &56,&5E,&56,&56,&56,&5E,&56,&56 DB &56,&56,&4E,&56,&56,&56,&56,&4E DB &56,&56,&56,&4E,&56,&56,&4E,&56 DB &4E,&4E,&4E,&52,&4E,&4E,&52,&4E DB &52,&52,&4E,&52,&52,&52,&52,&59 DB &52,&52,&59,&52,&59,&59,&52,&59 DB &59,&5B,&59,&59,&5B,&59,&5B,&5B DB &59,&5B,&5B,&5B,&5B,&5B,&4B,&5B DB &5B,&4B,&5B,&4B,&4B,&5B,&4B,&4B DB &4B,&4B,&4B,&53,&4B,&4B,&53,&4B DB &53,&53,&4B,&53,&53,&5F,&53,&53 DB &5F,&53,&5F,&5F,&53,&5F,&5F,&5F DB &5F,&5F,&46,&5F,&5F,&46,&5F,&46 DB &46,&5F,&46,&46,&46,&5F,&46,&46 DB &43 ; jaune pastel (mon encre 14) DB 0 ;fin ; ----------------------------------------------------------------------------- ; Tirage langue ; ----------------------------------------------------------------------------- TIR_LANGUE LD A,25:CALL DELAY:LD HL,FRAME1:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME2:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME3:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME4:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME5:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME6:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME7:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME8:CALL AFF_SPRITE LD A,25:CALL DELAY:LD HL,FRAME8:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME7:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME6:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME5:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME4:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME3:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME2:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME1:CALL AFF_SPRITE RET ; ----------------------------------------------------------------------------- ; Palette ; ----------------------------------------------------------------------------- AFF_COULEURS ;charger les couleurs LD HL,couleurs XOR A loopcouleurs PUSH AF PUSH HL LD B,(HL) LD C,B CALL &BC32 POP HL INC HL POP AF INC A CP 16 JR NZ,loopcouleurs RET .couleurs DEFB 0,1,2,3,4,5,6,9,13,14,15,16,18,23,25,26 ; ----------------------------------------------------------------------------- ; OUT OVERSCAN AVEC R6=0 ; ----------------------------------------------------------------------------- OUT_OVERSCAN LD HL,OUT_OVERSCAN_R6_A_ZERO LD BC,&BC00 LOOPR6 LD A,(HL) AND A RET Z OUT (C),A INC B INC HL LD A,(HL) OUT(C),A INC HL DEC B JR LOOPR6 OUT_OVERSCAN_R6_A_ZERO DB &01,&30 ;largeur DB &02,&32 DB &06,&00 DB &07,&23 DB &0C,&0D ;page 32 Ko DB &0D,&00 ;offset a zero DB &00,&00 ;fin de la routine ; ----------------------------------------------------------------------------- ; RIDEAU DESCENDANT OVERSCAN AVEC R6=&00 a &22 inclus ; ----------------------------------------------------------------------------- EFFET_RIDEAU_R6_VERS_LE_BAS XOR A looprideau LD (R6rideau+1),A CALL FRAME:CALL FRAME LD BC,&BC06 OUT(C),C R6rideau LD BC,&BD00 ;01 XX BC OUT(C),C INC A CP &23 ;Ira de &00 a &22 JR NZ,looprideau RET ; ----------------------------------------------------------------------------- ; RIDEAU DESCENDANT OVERSCAN AVEC R6=&00 a &22 inclus ; ----------------------------------------------------------------------------- EFFET_RIDEAU_R6_VERS_LE_HAUT LD A,&22 looprideauH LD (R6rideauH+1),A CALL FRAME:CALL FRAME LD BC,&BC06 OUT(C),C R6rideauH LD BC,&BD00 ;01 XX BC OUT(C),C DEC A CP &FF ;Ira de &22 a &00 JR NZ,looprideauH RET ;------------------------------------------------------------------------------ ; OUT NORMAL ;------------------------------------------------------------------------------ OUT_NORMAL ;OUT R1=40 largeur LD BC,&BC01 OUT (C),C LD BC,&BD28 OUT (C),C ;hauteur ;LD BC,&BC06 ;OUT (C),C ;LD BC,&BD19 ;OUT (C),C ;decalage horizontal LD BC,&BC02 OUT (C),C LD BC,&BD2E OUT (C),C ;decalage vertical LD BC,&BC07 OUT (C),C LD BC,&BD1E OUT (C),C ;ecran 17 ko (&C000 a &FFFF) LD BC,&BC0C OUT (C),C LD BC,&BD3C OUT (C),C ;debut offset (en &C000) LD BC,&BC0D OUT (C),C LD BC,&BD00 OUT (C),C XOR A CALL &BC0E ;mode 0 LD BC,&0101 CALL &BC38 ;border 1 ;charger les couleurs LD HL,couleursloading XOR A loopcouleursloading PUSH AF PUSH HL LD B,(HL) LD C,B CALL &BC32 POP HL INC HL POP AF INC A CP 16 JR NZ,loopcouleursloading LD HL,waitloading LD A,40 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,22 ;hauteur a afficher LD DE,&C000 CALL AFF_TABLEAU ;EFFET_RIDEAU_R6_VERS_LE_BAS(ecran normal) XOR A looprideauN LD (R6rideauN+1),A CALL FRAME:CALL FRAME LD BC,&BC06 OUT(C),C R6rideauN LD BC,&BD00 ;01 XX BC OUT(C),C INC A CP &1A ;Ira de &00 a &19 (25 lignes) JR NZ,looprideauN RET .couleursloading DEFB 1,23,1,10,11,20,9,12,6,3,24,15,26,13,0,16 .waitloading DEFB " AFFF " DEFB " AFFFAF FAF " DEFB " AF ACC AF F " DEFB " AF FACC AC CACC FFAF " DEFB " AF FAC AG GAG C C " DEFB " AFFFAC CAGGG AG GAF " DEFB " AF AC G GACAF " DEFB " AF ACC G DDDD AGAFF F " DEFB " AF AC DDDDDDDDDD AGAC FF " DEFB " AC AGGG DDDDDDDDDDDD AG C " DEFB "AFFFAC DDDDDEEEEDDDDDD AG CAFF " DEFB "AF AGGG DDDDDEEBEEEDDDDDDD GAF F" DEFB "AC DDDDDEBEEEBEBDDDBDDD AC F" DEFB "AC DDDDDEEEEEEEEBCDBDDDDD AG C" DEFB "ACGGG DDDDDDDDDDBBBBBBBBBBBDDDDDDDD AGG " DEFB " DDDDDEEEEEEEEBCDBDDDDD " DEFB " DDDDDEBEEEBEBDDDBDDD " DEFB " DDDDDEEBEEEDDDDDDD " DEFB " DDDDDEEEEDDDDDD " DEFB " DDDDDDDDDDDD " DEFB " DDDDDDDDDD " DEFB " DDDD " ;------------------------------------------------------------------------------ ;TABLEAU DE TILES 2x8 octets avec exclusion des tiles vident ;------------------------------------------------------------------------------ .AFF_TABLEAU PUSH AF PUSH DE .aff_tableau_largeur LD A,0 ;longueur a afficher .aff_tableau2 PUSH AF LD A,(IX+&00) ;lecture caractere INC IX CP 32 ;ne pas afficher les tiles vident JP Z,aff_tableau1 PUSH DE CALL aff_TILES8_0 ;affichage caractere POP DE .aff_tableau1 INC DE ;decalage 2 octets (largeur d'une tuile) INC DE POP AF DEC A JR NZ,aff_tableau2 POP HL LD BC,&0050 ADD HL,BC ;ligne suivante EX DE,HL POP AF DEC A JR NZ,AFF_TABLEAU RET .aff_TILES8_0 LD C,64 SUB C ;A = A-64 PUSH DE ;sauver DE LD L,A ;L = A LD H,0 ;H = 0 ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 LD DE,gfx_fonte ADD HL,DE ;HL contient l'adresse du tiles POP DE ;recuperer l'adresse d'affichage a l'ecran LD A,8 ;Hauteur_du_tile .aff_TILES8_1 LDI LDI ;8 pixels = 2 octets EX DE,HL LD BC,&07FE ;&800 - 2 octets (largeur ecran - largeur tiles) ADD HL,BC JR NC,aff_TILES8_2 LD BC,&C050 ;R1=40 alors &C050 (normal) ADD HL,BC .aff_TILES8_2 EX DE,HL DEC A JR NZ,aff_TILES8_1 RET ;;------------------------------------------------------------------------------ ; DELAY SUBROUTINE ; A = Time ;------------------------------------------------------------------------------ DELAY EI DELAY_1 LD B,15 ; 15 x 1/300th ms (HALT) = 50ms DELAY_2 HALT ; Waits 1/300th s DJNZ DELAY_2 ; Loop for 50ms DEC A JR NZ,DELAY_1 ; Loop for A x 50ms DI RET ;------------------------------------------------------------------------------ ; AFFICHAGE FRAME ;------------------------------------------------------------------------------ AFF_SPRITE ; LD HL,&7EC0+2460 LD DE,SPRITE_ADR_ECRAN LD A,SPRITE_HAUTEUR ;hauteur spr_loop2 PUSH AF PUSH DE LD BC,SPRITE_LARGEUR ;largeur LDIR POP DE EX DE,HL CALL conv_ligne_suivante ;CALL FRAME EX DE,HL POP AF DEC A JR NZ, spr_loop2 RET conv_ligne_suivante ;HL (adresse ecran) LD A,H ADD A,8 LD H,A AND &38 RET NZ LD A,H SUB &40 LD H,A LD A,L ADD A,&60 ;si R1=40 alors &50 si R1=41 alors &52 si R1=48 alors &60 LD L,A RET NC INC H LD A,H AND 7 RET NZ LD A,H SUB 8 LD H,A RET ; ----------------------------------------------------------------------------- ; SYNCHRONISATION VBL ; ----------------------------------------------------------------------------- FRAME PUSH AF PUSH BC WAIT_FOR_VBL LD B,&F5 IN A,(C) RRA JR C,WAIT_FOR_VBL+2 ;Boucle tant que la VBL est active WAIT_FOR_VBL2 IN A,(C) RRA JR NC,WAIT_FOR_VBL2 ;Boucle tant que la VBL est inactive POP BC POP AF RET

Manual n° 2


Manual n° 3

- - - - - - - - - - - - - - - - - [ assemble_fichier_final.asm ] - - - - - - - - - - - - - - - - - ;LOAD"-BASIC.BAS ;ASSEMBLE ;CALL &A000 ORG &1F0 ;transfert de la fin vers le debut pour eviter l'ecrasement des donnees ; LD HL,&200 LD HL,&447F ; LD DE,&4000 LD DE,&827F LD BC,&4280 ; LDIR LDDR JP &76C0 RET ;&200 FIN.PRG ORG &A000 ;ECRAN.DAT en &0200 LD B,&0C LD HL,fichier1 LD DE,&C000 CALL &BC77 ;lecture entete LD HL,&0200 CALL &BC83 ;lecture fichier CALL &BC7A ;ferme le fichier ;sauvegarde LD B,&0C LD HL,fichier_final LD DE,&C000 CALL &BC8C LD HL,&0170 ;adresse debut LD DE,&4320 ;longueur (on arrondi) LD BC,&FADA ;execution (n'importe quoi, mais on s'amuse) LD A,0 ;fichier basic CALL &BC98 CALL &BC8F CALL &BC89 CALL &BC92 fichier1 DEFM "FIN .PRG" fichier_final DEFM "END .BAS" - - - - - - - - - - - - - - - - - [ fin.asm ] - - - - - - - - - - - - - - - - - SPRITE_HAUTEUR EQU 38 SPRITE_LARGEUR EQU 9 SPRITE_ADR_ECRAN EQU &CCBF ;SPRITES.SPR lg &1560 FRAME1 EQU &4000 FRAME2 EQU &4000+342 FRAME3 EQU &4000+684 FRAME4 EQU &4000+1026 FRAME5 EQU &4000+1368 FRAME6 EQU &4000+1710 FRAME7 EQU &4000+2052 FRAME8 EQU &4000+2394 FRAME9 EQU &4000+2736 FRAME10 EQU &4000+3078 FRAME11 EQU &4000+3420 FRAME12 EQU &4000+3762 FRAME13 EQU &4000+4104 FRAME14 EQU &4000+4446 FRAME15 EQU &4000+4788 FRAME16 EQU &4000+5130 ;fin &555F ;FIN2.MUS ZIC_RAYXAMBER EQU &5600 ;lg &1C2 ;fin &57C1 ;ENDFIN.SPR ETOILE_FIN EQU &5800 ;lg &474 ;fin &5C73 ;FIN.PAK ECRAN_FIN_PAK EQU &5C80 ;lg &1A34 ;fin &76B4 TEMPO EQU 2 TEMPO2 EQU 1 ORG &76C0 WRITE DIRECT "FIN.BIN" CALL TEST CALL DECOMPACK CALL ETOILES LD A,0 LD B,0 LD C,0 LD D,0 LD E,0 LD H,0 LD L,0 CALL PLAYER_ARKOS CALL AFF_COULEURS .loop_anim LD A,25:CALL DELAYN:LD HL,FRAME1:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME2:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME3:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME4:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME5:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME6:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME7:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME8:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME9:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME10:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME11:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME12:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME13:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME14:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME15:CALL AFF_SPRITE LD A,TEMPO:CALL DELAY:LD HL,FRAME16:CALL AFF_SPRITE LD A,25:CALL DELAYN:LD HL,FRAME15:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME14:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME13:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME12:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME11:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME10:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME9:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME8:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME7:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME6:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME5:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME4:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME3:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME2:CALL AFF_SPRITE LD A,TEMPO2:CALL DELAY:LD HL,FRAME1:CALL AFF_SPRITE LD A,50:CALL DELAY JP loop_anim RET ;------------------------------------------------------------------------------ ; Couleurs ;------------------------------------------------------------------------------ .AFF_COULEURS LD HL,couleurs XOR A loopcouleurs PUSH AF PUSH HL LD B,(HL) LD C,B CALL &BC32 CALL &BD19:CALL &BD19:CALL &BD19:CALL &BD19 POP HL INC HL POP AF INC A CP 16 JR NZ,loopcouleurs ;encre 2 clignotante LD A,2 LD B,11 LD C,23 CALL &BC32 RET .couleurs DEFB 0,1,11,3,4,5,6,9,11,12,14,16,21,23,24,26 ;------------------------------------------------------------------------------ ; Test ;------------------------------------------------------------------------------ .TEST LD A,(&BE81) CP "O" ;&4F JP Z,suite CALL 0 .suite LD A,(&BE82) CP "K" ;&4B JP Z,suite2 CALL 0 .suite2 RET ;------------------------------------------------------------------------------ ; Etoiles FIN (0=SP, 1=FR) ou END (2=UK) ;------------------------------------------------------------------------------ .ETOILES LD A,(&BE80) CP 0:CALL Z,ETOILES_SP_FR CP 1:CALL Z,ETOILES_SP_FR CP 2:CALL Z,ETOILES_UK .AFF_SPRITEB LD DE,&C121 LD A,19 AFF_SPRITEB1 PUSH DE LD BC,30 LDIR POP DE PUSH HL LD HL,&800 ADD HL,DE JR NC,AFF_SPRITEB2 LD BC,&C050 ADD HL,BC AFF_SPRITEB2 EX HL,DE POP HL DEC A JR NZ,AFF_SPRITEB1 RET .ETOILES_SP_FR LD HL,ETOILE_FIN+&23A RET .ETOILES_UK LD HL,ETOILE_FIN RET ;------------------------------------------------------------------------------ ; Sprite opaque ; Entrees ; ; - LIGNES = nombre de lignes ; - LARGEUR = largeur du sprite en octets ; - HL = adresse du sprite ; - DE = adresse ecran. ;------------------------------------------------------------------------------ .AFF_SPRITE LD DE,SPRITE_ADR_ECRAN LD A,SPRITE_HAUTEUR AFF_SPRITE1 PUSH DE LD BC,SPRITE_LARGEUR LDIR POP DE PUSH HL LD HL,&800 ADD HL,DE JR NC,AFF_SPRITE2 LD BC,&C050 ADD HL,BC AFF_SPRITE2 EX HL,DE POP HL DEC A JR NZ,AFF_SPRITE1 RET ;------------------------------------------------------------------------------ ; DELAY SUBROUTINE ; A = Time ;------------------------------------------------------------------------------ DELAY EI DELAY_1 LD B,5 ; 15 x 1/300th ms (HALT) = 50ms DELAY_2 HALT ; Waits 1/300th s DJNZ DELAY_2 ; Loop for 50ms DEC A JR NZ,DELAY_1 ; Loop for A x 50ms DI RET ;------------------------------------------------------------------------------ ; DELAY SUBROUTINE (0.05s to 12.75s) ; A = Timeout / 50ms ;------------------------------------------------------------------------------ DELAYN EI DELAYN_1 LD B,15 ; 15 x 1/300th ms (HALT) = 50ms DELAYN_2 HALT ; Waits 1/300th s DJNZ DELAYN_2 ; Loop for 50ms DEC A JR NZ,DELAYN_1 ; Loop for A x 50ms DI RET ;------------------------------------------------------------------------------ ; Player Arkos tracker ;------------------------------------------------------------------------------ PLAYER_ARKOS list ;*** Start of Arkos Tracker Player nolist ; music selector JP start_music ; front-end minable mais bon PLAYER_ARKOS_OFF JP PLY_InterruptionOff ; routine Arkos tracker JP PLY_InterruptionContinue ; routine Arkos tracker JP PLY_SetFadeValue jp PLY_SFX_Init ;Call Player + 9 to initialise the sound effect music. jp PLY_BasicSoundEffectInterface_PlaySound ;Call Player + 12 to add sound effect in BASIC. jp PLY_SFX_Stop start_music LD A,E ADD A,A ; x2 LD C,A LD B,&0 LD HL,musiques ADD HL,BC ; on pointe sur la table contenant l'adresse de depart d'une musique LD E,(HL) INC HL LD D,(HL) JP PLY_InterruptionOn musiques defw ZIC_RAYXAMBER defw &0000 ; rien defw &0000 ; rien ;end &5D03 ; Arkos Tracker Player V1.01 - CPC & MSX version. ; 21/09/09 ; Code By Targhan/Arkos. ; PSG registers sendings based on Madram/Overlander's optimisation trick. ; Restoring interruption status snippet by Grim/Arkos. ; V1.01 additions ; --------------- ; - Small (but not useless !) optimisations by Grim/Arkos at the PLY_Track1_WaitCounter / PLY_Track2_WaitCounter / PLY_Track3_WaitCounter labels. ; - Optimisation of the R13 management by Grim/Arkos. ; This player can adapt to the following machines = ; Amstrad CPC and MSX. ; Output codes are specific, as well as the frequency tables. ; This player modifies all these registers = HL, DE, BC, AF, HL', DE', BC', AF', IX, IY. ; The Stack is used in conventionnal manners (Call, Ret, Push, Pop) so integration with any of your code should be seamless. ; The player does NOT modifies the Interruption state, unless you use the PLY_SystemFriendly flag, which will cut the ; interruptions at the beginning, and will restore them ONLY IF NEEDED. ; Basically, there are three kind of players. ; ASM ; --- ; Used in your Asm productions. You call the Player by yourself, you don't care if all the registers are modified. ; Set PLY_SystemFriendly and PLY_UseFirmwareInterruptions to 0. ; In Assembler = ; ld de,MusicAddress ; call Player / PLY_Init to initialise the player with your song. ; then ; call Player + 3 / PLY_Play whenever you want to play/continue the song. ; call Player + 6 / PLY_Stop to stop the song. ; BASIC ; ----- ; Used in Basic (on CPC), or under the helm of any OS. Interruptions will be cut by the player, but restored ONLY IF NECESSARY. ; Also, some registers are saved (AF', BC', IX and IY), as they are used by the CPC Firmware. ; If you need to add/remove more registers, take care to do it at PLY_Play, but also at PLY_Stop. ; Registers are restored at PLY_PSGREG13_RecoverSystemRegisters. ; Set PLY_SystemFriendly to 1 and PLY_UseFirmwareInterruptions to 0. ; The Calls in Assembler are the same as above. ; In Basic = ; call Player, MusicAddress to initialise the player with your song. ; then ; call Player + 3 whenever you want to play/continue the song. ; call Player + 6 to stop the song. ; INTERRUPTIONS ; ------------- ; CPC Only ! Uses the Firmware Interruptions to put the Player on interruption. Very useful in Basic. ; Set PLY_SystemFriendly and PLY_UseFirmwareInterruptions to 1. ; In Assembler = ; ld de,MusicAddress ; call Player / PLY_InterruptionOn to play the song from start. ; call Player + 3 / PLY_InterruptionOff to stop the song. ; call Player + 6 / PLY_InterruptionContinue to continue the song once it's been stopped. ; In Basic= ; call Player, MusicAddress to play the song from start. ; call Player + 3 to stop the song. ; call Player + 6 to continue the song once it's been stopped. ; FADES IN/OUT ; ------------ ; The player allows the volume to be modified. It provides the interface, but you'll have to set the volume by yourself. ; Set PLY_UseFades to 1. ; In Assembler = ; ld e,Volume (0=full volume, 16 or more=no volume) ; call PLY_SetFadeValue ; In Basic = ; call Player + 9 (or + 18, see just below), Volume (0=full volume, 16 or more=no volume) ; WARNING ! You must call Player + 18 if PLY_UseBasicSoundEffectInterface is set to 1. ; SOUND EFFECTS ; ------------- ; The player manages Sound Effects. They must be defined in another song, generated as a "SFX Music" in the Arkos Tracker. ; Set the PLY_UseSoundEffects to 1. If you want to use sound effects in Basic, set PLY_UseBasicSoundEffectInterface to 1. ; In Assembler = ; ld de,SFXMusicAddress ; call PLY_SFX_Init to initialise the SFX Song. ; Then initialise and play the "music" song normally. ; To play a sound effect = ; A = No Channel (0,1,2) ; L = SFX Number (>0) ; H = Volume (0...F) ; E = Note (0...143) ; D = Speed (0 = As original, 1...255 = new Speed (1 is the fastest)) ; BC = Inverted Pitch (-#FFFF -> FFFF). 0 is no pitch. The higher the pitch, the lower the sound. ; call PLY_SFX_Play ; To stop a sound effect = ; ld e,No Channel (0,1,2) ; call PLY_SFX_Stop ; To stop the sound effects on all the channels = ; call PLY_SFX_StopAll ; In Basic = ; call Player + 9, SFXMusicAddress to initialise the SFX Song. ; To play a sound effect = ; call Player + 12, No Channel, SFX Number, Volume, Note, Speed, Inverted Pitch. No parameter should be ommited ! ; To stop a sound effect = ; call Player + 15, No Channel (0,1,2) ; For more information, check the manual. ; Any question, complaint, a need to reward ? Write to contact@julien-nevo.com PLY_UseCPCMachine equ 1 ;Indicates what frequency table and output code to use. 1 to use it. PLY_UseMSXMachine equ 0 PLY_UseSoundEffects equ 1 ;Set to 1 if you want to use Sound Effects in your player. Both CPU and memory consuming. PLY_UseFades equ 1 ;Set to 1 to allow fades in/out. A little CPU and memory consuming. ;PLY_SetFadeValue becomes available. PLY_SystemFriendly equ 1 ;Set to 1 if you want to save the Registers used by AMSDOS (AF', BC', IX, IY) ;(which allows you to call this player in BASIC) ;As this option is system-friendly, it cuts the interruption, and restore them ONLY IF NECESSARY. PLY_UseFirmwareInterruptions equ 1 ;Set to 1 to use a Player under interruption. Only works on CPC, as it uses the CPC Firmware. ;WARNING, PLY_SystemFriendly must be set to 1 if you use the Player under interruption ! ;SECOND WARNING, make sure the player is above #3fff, else it won't be played (system limitation). PLY_UseBasicSoundEffectInterface equ 1 ;Set to 1 if you want a little interface to be added if you are a BASIC programmer who wants ;to use sound effects. Of course, you must also set PLY_UseSoundEffects to 1. PLY_RetrigValue equ #fe ;Value used to trigger the Retrig of Register 13. #FE corresponds to CP xx. Do not change it ! Player if PLY_UseFirmwareInterruptions ;******* Interruption Player ******** ;You can remove these JPs if using the sub-routines directly. jp PLY_InterruptionOn ;Call Player = Start Music. jp PLY_InterruptionOff ;Call Player + 3 = Stop Music. jp PLY_InterruptionContinue ;Call Player + 6 = Continue (after stopping). if PLY_UseBasicSoundEffectInterface jp PLY_SFX_Init ;Call Player + 9 to initialise the sound effect music. jp PLY_BasicSoundEffectInterface_PlaySound ;Call Player + 12 to add sound effect in BASIC. jp PLY_SFX_Stop ;Call Player + 15 to stop a sound effect. endif if PLY_UseFades jp PLY_SetFadeValue ;Call Player + 9 or + 18 to set Fades values. endif PLY_InterruptionOn call PLY_Init ld hl,PLY_Interruption_Convert PLY_ReplayFrequency ld de,0 ld a,d ld (PLY_Interruption_Cpt + 1),a add hl,de ld a,(hl) ;Chope nbinter wait ld (PLY_Interruption_Value + 1),a PLY_InterruptionContinue ld hl,PLY_Interruption_ControlBloc ld bc,%10000001*256+0 ld de,PLY_Interruption_Play jp #bce0 PLY_InterruptionOff ld hl,PLY_Interruption_ControlBloc call #bce6 jp PLY_Stop PLY_Interruption_ControlBloc defs 10,0 ;Buffer used by the OS. ;Code run by the OS on each interruption. PLY_Interruption_Play di PLY_Interruption_Cpt ld a,0 ;Run the player only if it has to, according to the music frequency. PLY_Interruption_Value cp 5 jr z,PLY_Interruption_NoWait inc a ld (PLY_Interruption_Cpt + 1),a ret PLY_Interruption_NoWait xor a ld (PLY_Interruption_Cpt + 1),a jp PLY_Play ;Table to convert PLY_ReplayFrequency into a Frequency value for the AMSDOS. PLY_Interruption_Convert defb 17, 11, 5, 2, 1, 0 else ;***** Normal Player ***** ;To be called when you want. ;You can remove these following JPs if using the sub-routines directly. jp PLY_Init ;Call Player = Initialise song (DE = Song address). jp PLY_Play ;Call Player + 3 = Play song. jp PLY_Stop ;Call Player + 6 = Stop song. endif if PLY_UseBasicSoundEffectInterface jp PLY_SFX_Init ;Call Player + 9 to initialise the sound effect music. jp PLY_BasicSoundEffectInterface_PlaySound ;Call Player + 12 to add sound effect in BASIC. jp PLY_SFX_Stop ;Call Player + 15 to stop a sound effect. endif if PLY_UseFades jp PLY_SetFadeValue ;Call Player + 9 or + 18 to set Fades values. endif PLY_Digidrum db 0 ;Read here to know if a Digidrum has been played (0=no). PLY_Play if PLY_SystemFriendly call PLY_DisableInterruptions ex af,af' exx push af push bc push ix push iy endif xor a ld (PLY_Digidrum),a ;Reset the Digidrum flag. ;Manage Speed. If Speed counter is over, we have to read the Pattern further. PLY_SpeedCpt ld a,1 dec a jp nz,PLY_SpeedEnd ;Moving forward in the Pattern. Test if it is not over. PLY_HeightCpt ld a,1 dec a jr nz,PLY_HeightEnd ;Pattern Over. We have to read the Linker. ;Get the Transpositions, if they have changed, or detect the Song Ending ! PLY_Linker_PT ld hl,0 ld a,(hl) inc hl rra jr nc,PLY_SongNotOver ;Song over ! We read the address of the Loop point. ld a,(hl) inc hl ld h,(hl) ld l,a ld a,(hl) ;We know the Song won't restart now, so we can skip the first bit. inc hl rra PLY_SongNotOver rra jr nc,PLY_NoNewTransposition1 ld de,PLY_Transposition1 + 1 ldi PLY_NoNewTransposition1 rra jr nc,PLY_NoNewTransposition2 ld de,PLY_Transposition2 + 1 ldi PLY_NoNewTransposition2 rra jr nc,PLY_NoNewTransposition3 ld de,PLY_Transposition3 + 1 ldi PLY_NoNewTransposition3 ;Get the Tracks addresses. ld de,PLY_Track1_PT + 1 ldi ldi ld de,PLY_Track2_PT + 1 ldi ldi ld de,PLY_Track3_PT + 1 ldi ldi ;Get the Special Track address, if it has changed. rra jr nc,PLY_NoNewHeight ld de,PLY_Height + 1 ldi PLY_NoNewHeight rra jr nc,PLY_NoNewSpecialTrack PLY_NewSpecialTrack ld e,(hl) inc hl ld d,(hl) inc hl ld (PLY_SaveSpecialTrack + 1),de PLY_NoNewSpecialTrack ld (PLY_Linker_PT + 1),hl PLY_SaveSpecialTrack ld hl,0 ld (PLY_SpecialTrack_PT + 1),hl ;Reset the SpecialTrack/Tracks line counter. ;We can't rely on the song data, because the Pattern Height is not related to the Tracks Height. ld a,1 ld (PLY_SpecialTrack_WaitCounter + 1),a ld (PLY_Track1_WaitCounter + 1),a ld (PLY_Track2_WaitCounter + 1),a ld (PLY_Track3_WaitCounter + 1),a PLY_Height ld a,1 PLY_HeightEnd ld (PLY_HeightCpt + 1),a ;Read the Special Track/Tracks. ;------------------------------ ;Read the Special Track. PLY_SpecialTrack_WaitCounter ld a,1 dec a jr nz,PLY_SpecialTrack_Wait PLY_SpecialTrack_PT ld hl,0 ld a,(hl) inc hl srl a ;Data (1) or Wait (0) ? jr nc,PLY_SpecialTrack_NewWait ;If Wait, A contains the Wait value. ;Data. Effect Type ? srl a ;Speed (0) or Digidrum (1) ? ;First, we don't test the Effect Type, but only the Escape Code (=0) jr nz,PLY_SpecialTrack_NoEscapeCode ld a,(hl) inc hl PLY_SpecialTrack_NoEscapeCode ;Now, we test the Effect type, since the Carry didn't change. jr nc,PLY_SpecialTrack_Speed ld (PLY_Digidrum),a jr PLY_PT_SpecialTrack_EndData PLY_SpecialTrack_Speed ld (PLY_Speed + 1),a PLY_PT_SpecialTrack_EndData ld a,1 PLY_SpecialTrack_NewWait ld (PLY_SpecialTrack_PT + 1),hl PLY_SpecialTrack_Wait ld (PLY_SpecialTrack_WaitCounter + 1),a ;Read the Track 1. ;----------------- ;Store the parameters, because the player below is called every frame, but the Read Track isn't. PLY_Track1_WaitCounter ld a,1 dec a jr nz,PLY_Track1_NewInstrument_SetWait PLY_Track1_PT ld hl,0 call PLY_ReadTrack ld (PLY_Track1_PT + 1),hl jr c,PLY_Track1_NewInstrument_SetWait ;No Wait command. Can be a Note and/or Effects. ld a,d ;Make a copy of the flags+Volume in A, not to temper with the original. rra ;Volume ? If bit 4 was 1, then volume exists on b3-b0 jr nc,PLY_Track1_SameVolume and %1111 ld (PLY_Track1_Volume),a PLY_Track1_SameVolume rl d ;New Pitch ? jr nc,PLY_Track1_NoNewPitch ld (PLY_Track1_PitchAdd + 1),ix PLY_Track1_NoNewPitch rl d ;Note ? If no Note, we don't have to test if a new Instrument is here. jr nc,PLY_Track1_NoNoteGiven ld a,e PLY_Transposition1 add a,0 ;Transpose Note according to the Transposition in the Linker. ld (PLY_Track1_Note),a ld hl,0 ;Reset the TrackPitch. ld (PLY_Track1_Pitch + 1),hl rl d ;New Instrument ? jr c,PLY_Track1_NewInstrument PLY_Track1_SavePTInstrument ld hl,0 ;Same Instrument. We recover its address to restart it. ld a,(PLY_Track1_InstrumentSpeed + 1) ;Reset the Instrument Speed Counter. Never seemed useful... ld (PLY_Track1_InstrumentSpeedCpt + 1),a jr PLY_Track1_InstrumentResetPT PLY_Track1_NewInstrument ;New Instrument. We have to get its new address, and Speed. ld l,b ;H is already set to 0 before. add hl,hl PLY_Track1_InstrumentsTablePT ld bc,0 add hl,bc ld a,(hl) ;Get Instrument address. inc hl ld h,(hl) ld l,a ld a,(hl) ;Get Instrument speed. inc hl ld (PLY_Track1_InstrumentSpeed + 1),a ld (PLY_Track1_InstrumentSpeedCpt + 1),a ld a,(hl) or a ;Get IsRetrig?. Code it only if different to 0, else next Instruments are going to overwrite it. jr z,$+5 ld (PLY_PSGReg13_Retrig + 1),a inc hl ld (PLY_Track1_SavePTInstrument + 1),hl ;When using the Instrument again, no need to give the Speed, it is skipped. PLY_Track1_InstrumentResetPT ld (PLY_Track1_Instrument + 1),hl PLY_Track1_NoNoteGiven ld a,1 PLY_Track1_NewInstrument_SetWait ld (PLY_Track1_WaitCounter + 1),a ;Read the Track 2. ;----------------- ;Store the parameters, because the player below is called every frame, but the Read Track isn't. PLY_Track2_WaitCounter ld a,1 dec a jr nz,PLY_Track2_NewInstrument_SetWait PLY_Track2_PT ld hl,0 call PLY_ReadTrack ld (PLY_Track2_PT + 1),hl jr c,PLY_Track2_NewInstrument_SetWait ;No Wait command. Can be a Note and/or Effects. ld a,d ;Make a copy of the flags+Volume in A, not to temper with the original. rra ;Volume ? If bit 4 was 1, then volume exists on b3-b0 jr nc,PLY_Track2_SameVolume and %1111 ld (PLY_Track2_Volume),a PLY_Track2_SameVolume rl d ;New Pitch ? jr nc,PLY_Track2_NoNewPitch ld (PLY_Track2_PitchAdd + 1),ix PLY_Track2_NoNewPitch rl d ;Note ? If no Note, we don't have to test if a new Instrument is here. jr nc,PLY_Track2_NoNoteGiven ld a,e PLY_Transposition2 add a,0 ;Transpose Note according to the Transposition in the Linker. ld (PLY_Track2_Note),a ld hl,0 ;Reset the TrackPitch. ld (PLY_Track2_Pitch + 1),hl rl d ;New Instrument ? jr c,PLY_Track2_NewInstrument PLY_Track2_SavePTInstrument ld hl,0 ;Same Instrument. We recover its address to restart it. ld a,(PLY_Track2_InstrumentSpeed + 1) ;Reset the Instrument Speed Counter. Never seemed useful... ld (PLY_Track2_InstrumentSpeedCpt + 1),a jr PLY_Track2_InstrumentResetPT PLY_Track2_NewInstrument ;New Instrument. We have to get its new address, and Speed. ld l,b ;H is already set to 0 before. add hl,hl PLY_Track2_InstrumentsTablePT ld bc,0 add hl,bc ld a,(hl) ;Get Instrument address. inc hl ld h,(hl) ld l,a ld a,(hl) ;Get Instrument speed. inc hl ld (PLY_Track2_InstrumentSpeed + 1),a ld (PLY_Track2_InstrumentSpeedCpt + 1),a ld a,(hl) or a ;Get IsRetrig?. Code it only if different to 0, else next Instruments are going to overwrite it. jr z,$+5 ld (PLY_PSGReg13_Retrig + 1),a inc hl ld (PLY_Track2_SavePTInstrument + 1),hl ;When using the Instrument again, no need to give the Speed, it is skipped. PLY_Track2_InstrumentResetPT ld (PLY_Track2_Instrument + 1),hl PLY_Track2_NoNoteGiven ld a,1 PLY_Track2_NewInstrument_SetWait ld (PLY_Track2_WaitCounter + 1),a ;Read the Track 3. ;----------------- ;Store the parameters, because the player below is called every frame, but the Read Track isn't. PLY_Track3_WaitCounter ld a,1 dec a jr nz,PLY_Track3_NewInstrument_SetWait PLY_Track3_PT ld hl,0 call PLY_ReadTrack ld (PLY_Track3_PT + 1),hl jr c,PLY_Track3_NewInstrument_SetWait ;No Wait command. Can be a Note and/or Effects. ld a,d ;Make a copy of the flags+Volume in A, not to temper with the original. rra ;Volume ? If bit 4 was 1, then volume exists on b3-b0 jr nc,PLY_Track3_SameVolume and %1111 ld (PLY_Track3_Volume),a PLY_Track3_SameVolume rl d ;New Pitch ? jr nc,PLY_Track3_NoNewPitch ld (PLY_Track3_PitchAdd + 1),ix PLY_Track3_NoNewPitch rl d ;Note ? If no Note, we don't have to test if a new Instrument is here. jr nc,PLY_Track3_NoNoteGiven ld a,e PLY_Transposition3 add a,0 ;Transpose Note according to the Transposition in the Linker. ld (PLY_Track3_Note),a ld hl,0 ;Reset the TrackPitch. ld (PLY_Track3_Pitch + 1),hl rl d ;New Instrument ? jr c,PLY_Track3_NewInstrument PLY_Track3_SavePTInstrument ld hl,0 ;Same Instrument. We recover its address to restart it. ld a,(PLY_Track3_InstrumentSpeed + 1) ;Reset the Instrument Speed Counter. Never seemed useful... ld (PLY_Track3_InstrumentSpeedCpt + 1),a jr PLY_Track3_InstrumentResetPT PLY_Track3_NewInstrument ;New Instrument. We have to get its new address, and Speed. ld l,b ;H is already set to 0 before. add hl,hl PLY_Track3_InstrumentsTablePT ld bc,0 add hl,bc ld a,(hl) ;Get Instrument address. inc hl ld h,(hl) ld l,a ld a,(hl) ;Get Instrument speed. inc hl ld (PLY_Track3_InstrumentSpeed + 1),a ld (PLY_Track3_InstrumentSpeedCpt + 1),a ld a,(hl) or a ;Get IsRetrig?. Code it only if different to 0, else next Instruments are going to overwrite it. jr z,$+5 ld (PLY_PSGReg13_Retrig + 1),a inc hl ld (PLY_Track3_SavePTInstrument + 1),hl ;When using the Instrument again, no need to give the Speed, it is skipped. PLY_Track3_InstrumentResetPT ld (PLY_Track3_Instrument + 1),hl PLY_Track3_NoNoteGiven ld a,1 PLY_Track3_NewInstrument_SetWait ld (PLY_Track3_WaitCounter + 1),a PLY_Speed ld a,1 PLY_SpeedEnd ld (PLY_SpeedCpt + 1),a ;Play the Sound on Track 3 ;------------------------- ;Plays the sound on each frame, but only save the forwarded Instrument pointer when Instrument Speed is reached. ;This is needed because TrackPitch is involved in the Software Frequency/Hardware Frequency calculation, and is calculated every frame. ld iy,PLY_PSGRegistersArray + 4 PLY_Track3_Pitch ld hl,0 PLY_Track3_PitchAdd ld de,0 add hl,de ld (PLY_Track3_Pitch + 1),hl sra h ;Shift the Pitch to slow its speed. rr l sra h rr l ex de,hl exx PLY_Track3_Volume equ $+2 PLY_Track3_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_Track3_Instrument ld hl,0 call PLY_PlaySound PLY_Track3_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_Track3_PlayNoForward ld (PLY_Track3_Instrument + 1),hl PLY_Track3_InstrumentSpeed ld a,6 PLY_Track3_PlayNoForward ld (PLY_Track3_InstrumentSpeedCpt + 1),a ;*************************************** ;Play Sound Effects on Track 3 (only assembled used if PLY_UseSoundEffects is set to one) ;*************************************** if PLY_UseSoundEffects PLY_SFX_Track3_Pitch ld de,0 exx PLY_SFX_Track3_Volume equ $+2 PLY_SFX_Track3_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_SFX_Track3_Instrument ld hl,0 ;If 0, no sound effect. ld a,l or h jr z,PLY_SFX_Track3_End ld a,1 ld (PLY_PS_EndSound_SFX + 1),a call PLY_PlaySound xor a ld (PLY_PS_EndSound_SFX + 1),a ld a,l ;If the new address is 0, the instrument is over. Speed is set in the process, we don't care. or h jr z,PLY_SFX_Track3_Instrument_SetAddress PLY_SFX_Track3_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_SFX_Track3_PlayNoForward PLY_SFX_Track3_Instrument_SetAddress ld (PLY_SFX_Track3_Instrument + 1),hl PLY_SFX_Track3_InstrumentSpeed ld a,6 PLY_SFX_Track3_PlayNoForward ld (PLY_SFX_Track3_InstrumentSpeedCpt + 1),a PLY_SFX_Track3_End endif ;****************************************** ld a,ixl ;Save the Register 7 of the Track 3. ex af,af' ;Play the Sound on Track 2 ;------------------------- ld iy,PLY_PSGRegistersArray + 2 PLY_Track2_Pitch ld hl,0 PLY_Track2_PitchAdd ld de,0 add hl,de ld (PLY_Track2_Pitch + 1),hl sra h ;Shift the Pitch to slow its speed. rr l sra h rr l ex de,hl exx PLY_Track2_Volume equ $+2 PLY_Track2_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_Track2_Instrument ld hl,0 call PLY_PlaySound PLY_Track2_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_Track2_PlayNoForward ld (PLY_Track2_Instrument + 1),hl PLY_Track2_InstrumentSpeed ld a,6 PLY_Track2_PlayNoForward ld (PLY_Track2_InstrumentSpeedCpt + 1),a ;*************************************** ;Play Sound Effects on Track 2 (only assembled used if PLY_UseSoundEffects is set to one) ;*************************************** if PLY_UseSoundEffects PLY_SFX_Track2_Pitch ld de,0 exx PLY_SFX_Track2_Volume equ $+2 PLY_SFX_Track2_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_SFX_Track2_Instrument ld hl,0 ;If 0, no sound effect. ld a,l or h jr z,PLY_SFX_Track2_End ld a,1 ld (PLY_PS_EndSound_SFX + 1),a call PLY_PlaySound xor a ld (PLY_PS_EndSound_SFX + 1),a ld a,l ;If the new address is 0, the instrument is over. Speed is set in the process, we don't care. or h jr z,PLY_SFX_Track2_Instrument_SetAddress PLY_SFX_Track2_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_SFX_Track2_PlayNoForward PLY_SFX_Track2_Instrument_SetAddress ld (PLY_SFX_Track2_Instrument + 1),hl PLY_SFX_Track2_InstrumentSpeed ld a,6 PLY_SFX_Track2_PlayNoForward ld (PLY_SFX_Track2_InstrumentSpeedCpt + 1),a PLY_SFX_Track2_End endif ;****************************************** ex af,af' add a,a ;Mix Reg7 from Track2 with Track3, making room first. or ixl rla ex af,af' ;Play the Sound on Track 1 ;------------------------- ld iy,PLY_PSGRegistersArray PLY_Track1_Pitch ld hl,0 PLY_Track1_PitchAdd ld de,0 add hl,de ld (PLY_Track1_Pitch + 1),hl sra h ;Shift the Pitch to slow its speed. rr l sra h rr l ex de,hl exx PLY_Track1_Volume equ $+2 PLY_Track1_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_Track1_Instrument ld hl,0 call PLY_PlaySound PLY_Track1_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_Track1_PlayNoForward ld (PLY_Track1_Instrument + 1),hl PLY_Track1_InstrumentSpeed ld a,6 PLY_Track1_PlayNoForward ld (PLY_Track1_InstrumentSpeedCpt + 1),a ;*************************************** ;Play Sound Effects on Track 1 (only assembled used if PLY_UseSoundEffects is set to one) ;*************************************** if PLY_UseSoundEffects PLY_SFX_Track1_Pitch ld de,0 exx PLY_SFX_Track1_Volume equ $+2 PLY_SFX_Track1_Note equ $+1 ld de,0 ;D=Inverted Volume E=Note PLY_SFX_Track1_Instrument ld hl,0 ;If 0, no sound effect. ld a,l or h jr z,PLY_SFX_Track1_End ld a,1 ld (PLY_PS_EndSound_SFX + 1),a call PLY_PlaySound xor a ld (PLY_PS_EndSound_SFX + 1),a ld a,l ;If the new address is 0, the instrument is over. Speed is set in the process, we don't care. or h jr z,PLY_SFX_Track1_Instrument_SetAddress PLY_SFX_Track1_InstrumentSpeedCpt ld a,1 dec a jr nz,PLY_SFX_Track1_PlayNoForward PLY_SFX_Track1_Instrument_SetAddress ld (PLY_SFX_Track1_Instrument + 1),hl PLY_SFX_Track1_InstrumentSpeed ld a,6 PLY_SFX_Track1_PlayNoForward ld (PLY_SFX_Track1_InstrumentSpeedCpt + 1),a PLY_SFX_Track1_End endif ;*********************************** ex af,af' or ixl ;Mix Reg7 from Track3 with Track2+1. ;Send the registers to PSG. Various codes according to the machine used. PLY_SendRegisters ;A=Register 7 if PLY_UseMSXMachine ld b,a ld hl,PLY_PSGRegistersArray ;Register 0 xor a out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 1 ld a,1 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 2 ld a,2 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 3 ld a,3 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 4 ld a,4 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 5 ld a,5 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 6 ld a,6 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 7 ld a,7 out (#a0),a ld a,b ;Use the stored Register 7. out (#a1),a ;Register 8 ld a,8 out (#a0),a ld a,(hl) if PLY_UseFades PLY_Channel1_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+3 xor a endif out (#a1),a inc hl inc hl ;Skip unused byte. ;Register 9 ld a,9 out (#a0),a ld a,(hl) if PLY_UseFades PLY_Channel2_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+3 xor a endif out (#a1),a inc hl inc hl ;Skip unused byte. ;Register 10 ld a,10 out (#a0),a ld a,(hl) if PLY_UseFades PLY_Channel3_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+3 xor a endif out (#a1),a inc hl ;Register 11 ld a,11 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 12 ld a,12 out (#a0),a ld a,(hl) out (#a1),a inc hl ;Register 13 if PLY_SystemFriendly call PLY_PSGReg13_Code PLY_PSGREG13_RecoverSystemRegisters pop iy pop ix pop bc pop af exx ex af,af' ;Restore Interrupt status PLY_RestoreInterruption nop ;Will be automodified to an DI/EI. ret endif PLY_PSGReg13_Code ld a,13 out (#a0),a ld a,(hl) PLY_PSGReg13_Retrig cp 255 ;If IsRetrig?, force the R13 to be triggered. ret z out (#a1),a ld (PLY_PSGReg13_Retrig + 1),a ret endif if PLY_UseCPCMachine ld de,#c080 ld b,#f6 out (c),d ;#f6c0 exx ld hl,PLY_PSGRegistersArray ld e,#f6 ld bc,#f401 ;Register 0 defb #ed,#71 ;#f400+Register ld b,e defb #ed,#71 ;#f600 dec b outi ;#f400+value exx out (c),e ;#f680 out (c),d ;#f6c0 exx ;Register 1 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 2 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 3 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 4 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 5 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 6 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 7 out (c),c ld b,e defb #ed,#71 dec b dec b out (c),a ;Read A register instead of the list. exx out (c),e out (c),d exx inc c ;Register 8 out (c),c ld b,e defb #ed,#71 dec b if PLY_UseFades dec b ld a,(hl) PLY_Channel1_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+6 defb #ed,#71 jr $+4 out (c),a inc hl else outi endif exx out (c),e out (c),d exx inc c inc hl ;Skip unused byte. ;Register 9 out (c),c ld b,e defb #ed,#71 dec b if PLY_UseFades ;If PLY_UseFades is set to 1, we manage the volume fade. dec b ld a,(hl) PLY_Channel2_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+6 defb #ed,#71 jr $+4 out (c),a inc hl else outi endif exx out (c),e out (c),d exx inc c inc hl ;Skip unused byte. ;Register 10 out (c),c ld b,e defb #ed,#71 dec b if PLY_UseFades dec b ld a,(hl) PLY_Channel3_FadeValue sub 0 ;Set a value from 0 (full volume) to 16 or more (volume to 0). jr nc,$+6 defb #ed,#71 jr $+4 out (c),a inc hl else outi endif exx out (c),e out (c),d exx inc c ;Register 11 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 12 out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d exx inc c ;Register 13 if PLY_SystemFriendly call PLY_PSGReg13_Code PLY_PSGREG13_RecoverSystemRegisters pop iy pop ix pop bc pop af exx ex af,af' ;Restore Interrupt status PLY_RestoreInterruption nop ;Will be automodified to an DI/EI. ret endif PLY_PSGReg13_Code ld a,(hl) PLY_PSGReg13_Retrig cp 255 ;If IsRetrig?, force the R13 to be triggered. ret z ld (PLY_PSGReg13_Retrig + 1),a out (c),c ld b,e defb #ed,#71 dec b outi exx out (c),e out (c),d ret endif ;There are two holes in the list, because the Volume registers are set relatively to the Frequency of the same Channel (+7, always). ;Also, the Reg7 is passed as a register, so is not kept in the memory. PLY_PSGRegistersArray PLY_PSGReg0 db 0 PLY_PSGReg1 db 0 PLY_PSGReg2 db 0 PLY_PSGReg3 db 0 PLY_PSGReg4 db 0 PLY_PSGReg5 db 0 PLY_PSGReg6 db 0 PLY_PSGReg8 db 0 ;+7 db 0 PLY_PSGReg9 db 0 ;+9 db 0 PLY_PSGReg10 db 0 ;+11 PLY_PSGReg11 db 0 PLY_PSGReg12 db 0 PLY_PSGReg13 db 0 PLY_PSGRegistersArray_End ;Plays a sound stream. ;HL=Pointer on Instrument Data ;IY=Pointer on Register code (volume, frequency). ;E=Note ;D=Inverted Volume ;DE'=TrackPitch ;RET= ;HL=New Instrument pointer. ;IXL=Reg7 mask (x00x) ;Also used inside = ;B,C=read byte/second byte. ;IXH=Save original Note (only used for Independant mode). PLY_PlaySound ld b,(hl) inc hl rr b jp c,PLY_PS_Hard ;************** ;Software Sound ;************** ;Second Byte needed ? rr b jr c,PLY_PS_S_SecondByteNeeded ;No second byte needed. We need to check if Volume is null or not. ld a,b and %1111 jr nz,PLY_PS_S_SoundOn ;Null Volume. It means no Sound. We stop the Sound, the Noise, and it's over. ld (iy + 7),a ;We have to make the volume to 0, because if a bass Hard was activated before, we have to stop it. ld ixl,%1001 ret PLY_PS_S_SoundOn ;Volume is here, no Second Byte needed. It means we have a simple Software sound (Sound = On, Noise = Off) ;We have to test Arpeggio and Pitch, however. ld ixl,%1000 sub d ;Code Volume. jr nc,$+3 xor a ld (iy + 7),a rr b ;Needed for the subroutine to get the good flags. call PLY_PS_CalculateFrequency ld (iy + 0),l ;Code Frequency. ld (iy + 1),h exx ret PLY_PS_S_SecondByteNeeded ld ixl,%1000 ;By defaut, No Noise, Sound. ;Second Byte needed. ld c,(hl) inc hl ;Noise ? ld a,c and %11111 jr z,PLY_PS_S_SBN_NoNoise ld (PLY_PSGReg6),a ld ixl,%0000 ;Open Noise Channel. PLY_PS_S_SBN_NoNoise ;Here we have either Volume and/or Sound. So first we need to read the Volume. ld a,b and %1111 sub d ;Code Volume. jr nc,$+3 xor a ld (iy + 7),a ;Sound ? bit 5,c jr nz,PLY_PS_S_SBN_Sound ;No Sound. Stop here. inc ixl ;Set Sound bit to stop the Sound. ret PLY_PS_S_SBN_Sound ;Manual Frequency ? rr b ;Needed for the subroutine to get the good flags. bit 6,c call PLY_PS_CalculateFrequency_TestManualFrequency ld (iy + 0),l ;Code Frequency. ld (iy + 1),h exx ret ;********** ;Hard Sound ;********** PLY_PS_Hard ;We don't set the Volume to 16 now because we may have reached the end of the sound ! rr b ;Test Retrig here, it is common to every Hard sounds. jr nc,PLY_PS_Hard_NoRetrig ld a,(PLY_Track1_InstrumentSpeedCpt + 1) ;Retrig only if it is the first step in this line of Instrument ! ld c,a ld a,(PLY_Track1_InstrumentSpeed + 1) cp c jr nz,PLY_PS_Hard_NoRetrig ld a,PLY_RetrigValue ld (PLY_PSGReg13_Retrig + 1),a PLY_PS_Hard_NoRetrig ;Independant/Loop or Software/Hardware Dependent ? bit 1,b ;We don't shift the bits, so that we can use the same code (Frequency calculation) several times. jp nz,PLY_PS_Hard_LoopOrIndependent ;Hardware Sound. ld (iy + 7),16 ;Set Volume ld ixl,%1000 ;Sound is always On here (only Independence mode can switch it off). ;This code is common to both Software and Hardware Dependent. ld c,(hl) ;Get Second Byte. inc hl ld a,c ;Get the Hardware Envelope waveform. and %1111 ;We don't care about the bit 7-4, but we have to clear them, else the waveform might be reset. ld (PLY_PSGReg13),a bit 0,b jr z,PLY_PS_HardwareDependent ;****************** ;Software Dependent ;****************** ;Calculate the Software frequency bit 4-2,b ;Manual Frequency ? -2 Because the byte has been shifted previously. call PLY_PS_CalculateFrequency_TestManualFrequency ld (iy + 0),l ;Code Software Frequency. ld (iy + 1),h exx ;Shift the Frequency. ld a,c rra rra ;Shift=Shift*4. The shift is inverted in memory (7 - Editor Shift). and %11100 ld (PLY_PS_SD_Shift + 1),a ld a,b ;Used to get the HardwarePitch flag within the second registers set. exx PLY_PS_SD_Shift jr $+2 srl h rr l srl h rr l srl h rr l srl h rr l srl h rr l srl h rr l srl h rr l jr nc,$+3 inc hl ;Hardware Pitch ? bit 7-2,a jr z,PLY_PS_SD_NoHardwarePitch exx ;Get Pitch and add it to the just calculated Hardware Frequency. ld a,(hl) inc hl exx add a,l ;Slow. Can be optimised ? Probably never used anyway..... ld l,a exx ld a,(hl) inc hl exx adc a,h ld h,a PLY_PS_SD_NoHardwarePitch ld (PLY_PSGReg11),hl exx ;This code is also used by Hardware Dependent. PLY_PS_SD_Noise ;Noise ? bit 7,c ret z ld a,(hl) inc hl ld (PLY_PSGReg6),a ld ixl,%0000 ret ;****************** ;Hardware Dependent ;****************** PLY_PS_HardwareDependent ;Calculate the Hardware frequency bit 4-2,b ;Manual Hardware Frequency ? -2 Because the byte has been shifted previously. call PLY_PS_CalculateFrequency_TestManualFrequency ld (PLY_PSGReg11),hl ;Code Hardware Frequency. exx ;Shift the Hardware Frequency. ld a,c rra rra ;Shift=Shift*4. The shift is inverted in memory (7 - Editor Shift). and %11100 ld (PLY_PS_HD_Shift + 1),a ld a,b ;Used to get the Software flag within the second registers set. exx PLY_PS_HD_Shift jr $+2 sla l rl h sla l rl h sla l rl h sla l rl h sla l rl h sla l rl h sla l rl h ;Software Pitch ? bit 7-2,a jr z,PLY_PS_HD_NoSoftwarePitch exx ;Get Pitch and add it to the just calculated Software Frequency. ld a,(hl) inc hl exx add a,l ld l,a ;Slow. Can be optimised ? Probably never used anyway..... exx ld a,(hl) inc hl exx adc a,h ld h,a PLY_PS_HD_NoSoftwarePitch ld (iy + 0),l ;Code Frequency. ld (iy + 1),h exx ;Go to manage Noise, common to Software Dependent. jr PLY_PS_SD_Noise PLY_PS_Hard_LoopOrIndependent bit 0,b ;We mustn't shift it to get the result in the Carry, as it would be mess the structure jr z,PLY_PS_Independent ;of the flags, making it uncompatible with the common code. ;The sound has ended. ;If Sound Effects activated, we mark the "end of sound" by returning a 0 as an address. if PLY_UseSoundEffects PLY_PS_EndSound_SFX ld a,0 ;Is the sound played is a SFX (1) or a normal sound (0) ? or a jr z,PLY_PS_EndSound_NotASFX ld hl,0 ret PLY_PS_EndSound_NotASFX endif ;The sound has ended. Read the new pointer and restart instrument. ld a,(hl) inc hl ld h,(hl) ld l,a jp PLY_PlaySound ;*********** ;Independent ;*********** PLY_PS_Independent ld (iy + 7),16 ;Set Volume ;Sound ? bit 7-2,b ;-2 Because the byte has been shifted previously. jr nz,PLY_PS_I_SoundOn ;No Sound ! It means we don't care about the software frequency (manual frequency, arpeggio, pitch). ld ixl,%1001 jr PLY_PS_I_SkipSoftwareFrequencyCalculation PLY_PS_I_SoundOn ld ixl,%1000 ;Sound is on. ld ixh,e ;Save the original note for the Hardware frequency, because a Software Arpeggio will modify it. ;Calculate the Software frequency bit 4-2,b ;Manual Frequency ? -2 Because the byte has been shifted previously. call PLY_PS_CalculateFrequency_TestManualFrequency ld (iy + 0),l ;Code Software Frequency. ld (iy + 1),h exx ld e,ixh PLY_PS_I_SkipSoftwareFrequencyCalculation ld b,(hl) ;Get Second Byte. inc hl ld a,b ;Get the Hardware Envelope waveform. and %1111 ;We don't care about the bit 7-4, but we have to clear them, else the waveform might be reset. ld (PLY_PSGReg13),a ;Calculate the Hardware frequency rr b ;Must shift it to match the expected data of the subroutine. rr b bit 4-2,b ;Manual Hardware Frequency ? -2 Because the byte has been shifted previously. call PLY_PS_CalculateFrequency_TestManualFrequency ld (PLY_PSGReg11),hl ;Code Hardware Frequency. exx ;Noise ? We can't use the previous common code, because the setting of the Noise is different, since Independent can have no Sound. bit 7-2,b ret z ld a,(hl) inc hl ld (PLY_PSGReg6),a ld a,ixl ;Set the Noise bit. res 3,a ld ixl,a ret ;Subroutine that = ;If Manual Frequency? (Flag Z off), read frequency (Word) and adds the TrackPitch (DE'). ;Else, Auto Frequency. ; if Arpeggio? = 1 (bit 3 from B), read it (Byte). ; if Pitch? = 1 (bit 4 from B), read it (Word). ; Calculate the frequency according to the Note (E) + Arpeggio + TrackPitch (DE'). ;HL = Pointer on Instrument data. ;DE'= TrackPitch. ;RET= ;HL = Pointer on Instrument moved forward. ;HL'= Frequency ; RETURN IN AUXILIARY REGISTERS PLY_PS_CalculateFrequency_TestManualFrequency jr z,PLY_PS_CalculateFrequency ;Manual Frequency. We read it, no need to read Pitch and Arpeggio. ;However, we add TrackPitch to the read Frequency, and that's all. ld a,(hl) inc hl exx add a,e ;Add TrackPitch LSB. ld l,a exx ld a,(hl) inc hl exx adc a,d ;Add TrackPitch HSB. ld h,a ret PLY_PS_CalculateFrequency ;Pitch ? bit 5-1,b jr z,PLY_PS_S_SoundOn_NoPitch ld a,(hl) inc hl exx add a,e ;If Pitch found, add it directly to the TrackPitch. ld e,a exx ld a,(hl) inc hl exx adc a,d ld d,a exx PLY_PS_S_SoundOn_NoPitch ;Arpeggio ? ld a,e bit 4-1,b jr z,PLY_PS_S_SoundOn_ArpeggioEnd add a,(hl) ;Add Arpeggio to Note. inc hl cp 144 jr c,$+4 ld a,143 PLY_PS_S_SoundOn_ArpeggioEnd ;Frequency calculation. exx ld l,a ld h,0 add hl,hl ld bc,PLY_FrequencyTable add hl,bc ld a,(hl) inc hl ld h,(hl) ld l,a add hl,de ;Add TrackPitch + InstrumentPitch (if any). ret ;Read one Track. ;HL=Track Pointer. ;Ret = ;HL=New Track Pointer. ;Carry = 1 = Wait A lines. Carry=0=Line not empty. ;A=Wait (0(=256)-127), if Carry. ;D=Parameters + Volume. ;E=Note ;B=Instrument. 0=RST ;IX=PitchAdd. Only used if Pitch? = 1. PLY_ReadTrack ld a,(hl) inc hl srl a ;Full Optimisation ? If yes = Note only, no Pitch, no Volume, Same Instrument. jr c,PLY_ReadTrack_FullOptimisation sub 32 ;0-31 = Wait. jr c,PLY_ReadTrack_Wait jr z,PLY_ReadTrack_NoOptimisation_EscapeCode dec a ;0 (32-32) = Escape Code for more Notes (parameters will be read) ;Note. Parameters are present. But the note is only present if Note? flag is 1. ld e,a ;Save Note. ;Read Parameters PLY_ReadTrack_ReadParameters ld a,(hl) ld d,a ;Save Parameters. inc hl rla ;Pitch ? jr nc,PLY_ReadTrack_Pitch_End ld b,(hl) ;Get PitchAdd ld ixl,b inc hl ld b,(hl) ld ixh,b inc hl PLY_ReadTrack_Pitch_End rla ;Skip IsNote? flag. rla ;New Instrument ? ret nc ld b,(hl) inc hl or a ;Remove Carry, as the player interpret it as a Wait command. ret ;Escape code, read the Note and returns to read the Parameters. PLY_ReadTrack_NoOptimisation_EscapeCode ld e,(hl) inc hl jr PLY_ReadTrack_ReadParameters PLY_ReadTrack_FullOptimisation ;Note only, no Pitch, no Volume, Same Instrument. ld d,%01000000 ;Note only. sub 1 ld e,a ret nc ld e,(hl) ;Escape Code found (0). Read Note. inc hl or a ret PLY_ReadTrack_Wait add a,32 ret PLY_FrequencyTable if PLY_UseCPCMachine dw 3822,3608,3405,3214,3034,2863,2703,2551,2408,2273,2145,2025 dw 1911,1804,1703,1607,1517,1432,1351,1276,1204,1136,1073,1012 dw 956,902,851,804,758,716,676,638,602,568,536,506 dw 478,451,426,402,379,358,338,319,301,284,268,253 dw 239,225,213,201,190,179,169,159,150,142,134,127 dw 119,113,106,100,95,89,84,80,75,71,67,63 dw 60,56,53,50,47,45,42,40,38,36,34,32 dw 30,28,27,25,24,22,21,20,19,18,17,16 dw 15,14,13,13,12,11,11,10,9,9,8,8 dw 7,7,7,6,6,6,5,5,5,4,4,4 dw 4,4,3,3,3,3,3,2,2,2,2,2 dw 2,2,2,2,1,1,1,1,1,1,1,1 endif if PLY_UseMSXMachine dw 4095,4095,4095,4095,4095,4095,4095,4095,4095,4030,3804,3591 dw 3389,3199,3019,2850,2690,2539,2397,2262,2135,2015,1902,1795 dw 1695,1599,1510,1425,1345,1270,1198,1131,1068,1008,951,898 dw 847,800,755,712,673,635,599,566,534,504,476,449 dw 424,400,377,356,336,317,300,283,267,252,238,224 dw 212,200,189,178,168,159,150,141,133,126,119,112 dw 106,100,94,89,84,79,75,71,67,63,59,56 dw 53,50,47,45,42,40,37,35,33,31,30,28 dw 26,25,24,22,21,20,19,18,17,16,15,14 dw 13,12,12,11,11,10,9,9,8,8,7,7 dw 7,6,6,6,5,5,5,4,4,4,4,4 dw 3,3,3,3,3,2,2,2,2,2,2,2 endif ;DE = Music PLY_Init if PLY_UseFirmwareInterruptions ld hl,8 ;Skip Header, SampleChannel, YM Clock (DB*3). The Replay Frequency is used in Interruption mode. add hl,de ld de,PLY_ReplayFrequency + 1 ldi else ld hl,9 ;Skip Header, SampleChannel, YM Clock (DB*3), and Replay Frequency. add hl,de endif ld de,PLY_Speed + 1 ldi ;Copy Speed. ld c,(hl) ;Get Instruments chunk size. inc hl ld b,(hl) inc hl ld (PLY_Track1_InstrumentsTablePT + 1),hl ld (PLY_Track2_InstrumentsTablePT + 1),hl ld (PLY_Track3_InstrumentsTablePT + 1),hl add hl,bc ;Skip Instruments to go to the Linker address. ;Get the pre-Linker information of the first pattern. ld de,PLY_Height + 1 ldi ld de,PLY_Transposition1 + 1 ldi ld de,PLY_Transposition2 + 1 ldi ld de,PLY_Transposition3 + 1 ldi ld de,PLY_SaveSpecialTrack + 1 ldi ldi ld (PLY_Linker_PT + 1),hl ;Get the Linker address. ld a,1 ld (PLY_SpeedCpt + 1),a ld (PLY_HeightCpt + 1),a ld a,#ff ld (PLY_PSGReg13),a ;Set the Instruments pointers to Instrument 0 data (Header has to be skipped). ld hl,(PLY_Track1_InstrumentsTablePT + 1) ld e,(hl) inc hl ld d,(hl) ex de,hl inc hl ;Skip Instrument 0 Header. inc hl ld (PLY_Track1_Instrument + 1),hl ld (PLY_Track2_Instrument + 1),hl ld (PLY_Track3_Instrument + 1),hl ret ;Stop the music, cut the channels. PLY_Stop if PLY_SystemFriendly call PLY_DisableInterruptions ex af,af' exx push af push bc push ix push iy endif ld hl,PLY_PSGReg8 ld bc,#0300 ld (hl),c inc hl djnz $-2 ld a,%00111111 jp PLY_SendRegisters if PLY_UseSoundEffects ;Initialize the Sound Effects. ;DE = SFX Music. PLY_SFX_Init ;Find the Instrument Table. ld hl,12 add hl,de ld (PLY_SFX_Play_InstrumentTable + 1),hl ;Clear the three channels of any sound effect. PLY_SFX_StopAll ld hl,0 ld (PLY_SFX_Track1_Instrument + 1),hl ld (PLY_SFX_Track2_Instrument + 1),hl ld (PLY_SFX_Track3_Instrument + 1),hl ret PLY_SFX_OffsetPitch equ 0 PLY_SFX_OffsetVolume equ PLY_SFX_Track1_Volume - PLY_SFX_Track1_Pitch PLY_SFX_OffsetNote equ PLY_SFX_Track1_Note - PLY_SFX_Track1_Pitch PLY_SFX_OffsetInstrument equ PLY_SFX_Track1_Instrument - PLY_SFX_Track1_Pitch PLY_SFX_OffsetSpeed equ PLY_SFX_Track1_InstrumentSpeed - PLY_SFX_Track1_Pitch PLY_SFX_OffsetSpeedCpt equ PLY_SFX_Track1_InstrumentSpeedCpt - PLY_SFX_Track1_Pitch ;Plays a Sound Effects along with the music. ;A = No Channel (0,1,2) ;L = SFX Number (>0) ;H = Volume (0...F) ;E = Note (0...143) ;D = Speed (0 = As original, 1...255 = new Speed (1 is fastest)) ;BC = Inverted Pitch (-#FFFF -> FFFF). 0 is no pitch. The higher the pitch, the lower the sound. PLY_SFX_Play ld ix,PLY_SFX_Track1_Pitch or a jr z,PLY_SFX_Play_Selected ld ix,PLY_SFX_Track2_Pitch dec a jr z,PLY_SFX_Play_Selected ld ix,PLY_SFX_Track3_Pitch PLY_SFX_Play_Selected ld (ix + PLY_SFX_OffsetPitch + 1),c ;Set Pitch ld (ix + PLY_SFX_OffsetPitch + 2),b ld a,e ;Set Note ld (ix + PLY_SFX_OffsetNote),a ld a,15 ;Set Volume sub h ld (ix + PLY_SFX_OffsetVolume),a ld h,0 ;Set Instrument Address add hl,hl PLY_SFX_Play_InstrumentTable ld bc,0 add hl,bc ld a,(hl) inc hl ld h,(hl) ld l,a ld a,d ;Read Speed or use the user's one ? or a jr nz,PLY_SFX_Play_UserSpeed ld a,(hl) ;Get Speed PLY_SFX_Play_UserSpeed ld (ix + PLY_SFX_OffsetSpeed + 1),a ld (ix + PLY_SFX_OffsetSpeedCpt + 1),a inc hl ;Skip Retrig inc hl ld (ix + PLY_SFX_OffsetInstrument + 1),l ld (ix + PLY_SFX_OffsetInstrument + 2),h ret ;Stops a sound effect on the selected channel ;E = No Channel (0,1,2) ;I used the E register instead of A so that Basic users can call this code in a straightforward way (call player+15, value). PLY_SFX_Stop ld a,e ld hl,PLY_SFX_Track1_Instrument + 1 or a jr z,PLY_SFX_Stop_ChannelFound ld hl,PLY_SFX_Track2_Instrument + 1 dec a jr z,PLY_SFX_Stop_ChannelFound ld hl,PLY_SFX_Track3_Instrument + 1 dec a PLY_SFX_Stop_ChannelFound ld (hl),a inc hl ld (hl),a ret endif if PLY_UseFades ;Sets the Fade value. ;E = Fade value (0 = full volume, 16 or more = no volume). ;I used the E register instead of A so that Basic users can call this code in a straightforward way (call player+9/+18, value). PLY_SetFadeValue ld a,e ld (PLY_Channel1_FadeValue + 1),a ld (PLY_Channel2_FadeValue + 1),a ld (PLY_Channel3_FadeValue + 1),a ret endif if PLY_SystemFriendly ;Save Interrupt status and Disable Interruptions PLY_DisableInterruptions ld a,i di ;IFF in P/V flag. ;Prepare opcode for DI. ld a,#f3 jp po,PLY_DisableInterruptions_Set_Opcode ;Opcode for EI. ld a,#fb PLY_DisableInterruptions_Set_Opcode ld (PLY_RestoreInterruption),a ret endif ;A little convient interface for BASIC user, to allow them to use Sound Effects in Basic. if PLY_UseBasicSoundEffectInterface PLY_BasicSoundEffectInterface_PlaySound ld c,(ix+0) ;Get Pitch ld b,(ix+1) ld d,(ix+2) ;Get Speed ld e,(ix+4) ;Get Note ld h,(ix+6) ;Get Volume ld l,(ix+8) ;Get SFX number ld a,(ix+10) ;Get Channel jp PLY_SFX_Play endif list ;*** End of Arkos Tracker Player nolist ;------------------------------------------------------------------------------ list ; Aplib decrunching routine nolist ; (c) CNGSOFT ; En entree, on a : ; HL = implantation du code compacte ; DE = implantation du code decompacte ;------------------------------------------------------------------------------ DECOMPACK ;DI LD HL,ECRAN_FIN_PAK LD DE,&C000 CALL boot JP &000F ; Maxam source by T&J/GPA - 01/18/2008 ; Nothing changed, except thy damned hidden opcodes ; and a new variable for Maxam ( 13+8*0 = 0 for Maxam ) ; Attention, cette routine contient un assemblage conditionnel. ; Si Aplib8flag = 0, le code decompacte est ecrite du bas de la ; memoire vers le haut de la memoire. C est ce que font par defaut ; les programmes modifies par Dadman/CEZ - Team (APPACK.EXE et ; aPPackWin.exe. ; Si Aplib8flag = 1, le code decompacte est ecrit du haut de la ; memoire vers le bas de la memoire. Le code compacte doit bien ; evidemment etre organise en consequence. aplib8flag equ &0 ; = DEC &00 pour INC flagdecde equ aplib8flag*8 ; for Maxam compatibility Boot PUSH HL ; used for EX HL,(SP) PUSH HL POP IX DB &FD,&26,&80 ; LD IYh,&80 aplib8literal LD A,(IX+ &00) DB &DD,&23 + flagdecde ; INC IX/DEC IX LD (DE),A DB &13 + flagdecde ; INC DE/DEC DE DB &FD,&2E,&02 ; LD IYl,&2 aplib8nexttag CALL aplib8getbit JR NC, aplib8literal LD BC,&0000 CALL aplib8getbit JR NC, aplib8codepair LD H,B CALL aplib8getbit JR NC, aplib8shortmatch DB &FD,&2E,&02 ; LD IYl,2 INC C ; bc LD L,&10 aplib8getmorebits CALL aplib8getbit RL L JR NC, aplib8getmorebits JR NZ, aplib8domatch LD A,L LD (DE),A DB &13+ flagdecde ; INC DE/DEC DE JR aplib8nexttag aplib8codepair CALL aplib8getgamma DB &FD,&4D ; LD C,IYl SBC HL,BC JR NZ, aplib8normalcodepair CALL aplib8getgamma LD B,H JR aplib8domatch_lastpos aplib8normalcodepair DEC L LD H,L LD L,(IX + &00) DB &DD,&23+ flagdecde ; INC IX/DEC IX PUSH HL CALL aplib8getgamma LD B,H POP HL LD A,H CP 125 ; cmp eax,32000 JR NC, aplib8domatch_with_2inc CP &05 JR NC, aplib8domatch_with_inc AND A JR NZ, aplib8domatch_new_lastpos LD A,L ADD A JR C, aplib8domatch_new_lastpos aplib8domatch_with_2inc INC BC aplib8domatch_with_inc INC BC aplib8domatch_new_lastpos EX (SP),HL aplib8domatch_lastpos POP HL PUSH HL DB &FD,&2E,&01 ; LD IYl,1 aplib8domatch if aplib8flag ; LDIR/LDDR ADD HL,DE LDDR else AND A EX DE,HL SBC HL,DE EX DE,HL ADD HL,DE EX DE,HL LDIR endif JR aplib8nexttag aplib8shortmatch LD L,(IX+&00) DB &DD,&23+ flagdecde ; INC IX/DEC IX SRL L JR Z, aplib8donedepacking RL C JR aplib8domatch_with_2inc aplib8getbit DB &FD,&7C ; LD A,IYh ADD A JR NZ,aplib8getbit_ LD A,(IX + &00) DB &DD,&23+ flagdecde ; INC IX/DEC IX ADC A aplib8getbit_ DB &FD,&67 ; LD IYh,A RET aplib8getgamma LD HL,&0001 aplib8getgamma_ CALL aplib8getbit ADC HL,HL CALL aplib8getbit JR C, aplib8getgamma_ LD C,L RET aplib8donedepacking POP HL ; used for EX HL,(SP) PUSH IX POP HL RET ; Warning, A might not be 0!


Goto Top
CPC-POWER/CPCSOFTS, programming by Kukulcan © 2007-2021 all rights reserved.
Reproduction forbidden without any express authorization. All the game titles used belong to their respective owners.
Hébergement Web, Mail et serveurs de jeux haute performance