15700
JEU -> Réflexion
© cpc-power.com (2019)
19.50 / 20.00
 
 
Clevermind
cpc
 
 

NOTICE / MANUAL

TXT (3)

NOTICE TEXTE n° 1 (12.75 Ko)

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
 

NOTICE TEXTE n° 2 (92.35 Ko)

LANGUE_SP EQU 1 LANGUE_FR EQU 0 LANGUE_UK EQU 0 gfx_des_tiles EQU &6146 ;lg &800 gfx_des_sprites EQU &6646 ;20eme +&500 ZIC_RAYXAMBER1 EQU &6970 ;lg &0237 ZIC_RAYXAMBER2 EQU &6BB0 ;lg &01C2 ZIC_RAYXAMBER3 EQU &6D80 ;lg &0275 ;fin &6FF5 LES_NIVEAUX EQU &C000 ;decompacte LES_NIVEAUX_PAK EQU &7000 ;compacte lg &0E31 ;fin &7E31 gfx_fonte EQU &7F4F ;lg &5B0 ;fin &84FF ;CLEVER.DAT deb=&6146 lg=&23BA load_niveau_courant EQU &8500 memoire_target EQU &85F3 teleporteur1x EQU &85F4 teleporteur1y EQU &85F5 teleporteur2x EQU &85F6 teleporteur2y EQU &85F7 taille_niveau EQU 243 largeur_niveau EQU 20 hauteur_niveau EQU 12 ecran_niveau EQU &C050 ORG &8600 if LANGUE_SP WRITE DIRECT "CLEVER0.RSX" endif if LANGUE_FR WRITE DIRECT "CLEVER1.RSX" endif if LANGUE_UK WRITE DIRECT "CLEVER2.RSX" endif NOLIST ; **************************** ; *** RSX - INITIALISATION *** ; **************************** .RSX_Init : LD HL,RSX_Init LD (HL),&C9 ; Ecrire un RET pour empecher une nouvelle initialisation LD BC,RSX_Commandes ; BC pointe sur la table des Commandes RSX LD HL,RSX_Tampon ; HL pointe sur 4 octets libres. JP &BCD1 .RSX_Tampon : DEFS 4 ; Tampon de quatre octets. .RSX_Commandes : DEFW RSX_Mots_Clefs ; Adresse des mots clefs JP TILES_16x16_opaque JP AFFICHAGE_ELEMENT_TRANSPARENT JP TILE8 JP LEVEL JP LIVES JP TARGET JP DECOR_16x16_SAUVEGARDE JP DECOR_16x16_RESTAURATION JP CLS2 JP AFFOHNO JP AFFDONE JP AFFGAMEOVER JP OPTIONS_MENU_BASIC JP MENU JP CREDITS JP INSTRUCTIONS JP HOWTOPLAY JP PLAYER_ARKOS JP PLAYER_ARKOS_OFF JP AFFICHAGE_LEVEL JP MESSAGES JP BADEND JP DECOMPACK JP WAITING JP FIN .RSX_Mots_Clefs DEFB "T"+&80 ;T,element,adresse_ecran DEFB "SP","R"+&80 ;SPR,element,adresse_ecran DEFB "T","8"+&80 ;T8,caractere,adresse_ecran DEFB "LEVE","L"+&80 ;LEVEL,dizaine,unite DEFB "LIVE","S"+&80 ;LIVES,unite DEFB "TARGE","T"+&80 ;TARGET,centaine,dizaine,unite DEFB "SA","V"+&80 ;DECORSAVE,adresse_ecran DEFB "AF","F"+&80 ;DECORAFF,adresse_ecran DEFB "CLS","2"+&80 ;CLS2 DEFB "OHN","O"+&80 ;OHNO DEFB "DON","E"+&80 ;DONE DEFB "LOS","T"+&80 ;LOST DEFB "MENU","2"+&80 ;MENU2,ligne_active DEFB "MENU","1"+&80 ;MENU1 DEFB "CREDIT","S"+&80 ;CREDITS DEFB "INFO","S"+&80 ;INFOS DEFB "HO","W"+&80 ;HOW DEFB "ZICO","N"+&80 ;ZICON DEFB "ZICOF","F"+&80 ;ZICOFF DEFB "AFFLV","L"+&80 ;AFFLVL,x(0 a 49) DEFB "MS","G"+&80 ;MSG,x DEFB "BA","D"+&80 ;BAD DEFB "UNPAC","K"+&80 ;UNPACK DONNEES NIVEAUX DEFB "WAI","T"+&80 ;WAIT,x DEFB "FI","N"+&80 NOP ;Fin de la table. NOP NOP NOP NOP NOP ;------------------------------------------------------------------------------ ; FIN ;------------------------------------------------------------------------------ .FIN LD HL,&BE81 LD A,"O" LD (HL),A INC HL LD A,"K" LD (HL),A RET ;------------------------------------------------------------------------------ ; TEMPORISATION ; A = nb ;------------------------------------------------------------------------------ WAITING LD A,(IX+&00) LD B,A DELAY_2 CALL &BD19 DJNZ DELAY_2 RET ;------------------------------------------------------------------------------ ; MAUVAISE FIN ;------------------------------------------------------------------------------ .BADEND if LANGUE_SP CALL CLS2 LD HL,BADEND01:LD DE,&C1E0+9:CALL directmini LD HL,BADEND02:LD DE,&C320+19:CALL directmini LD HL,BADEND03:LD DE,&C460+12:CALL directmini LD HL,BADEND04:LD DE,&C5A0+22:CALL directmini RET BADEND01 DEFB "HAS TERMINADO TODOS LOS NIVELES" : DB 0 BADEND02 DEFB "PERO HAS HECHO TRAMPA" : DB 0 BADEND03 DEFB "ASI QUE TE QUEDAS SIN PREMIO" : DB 0 BADEND04 DB 34 : DEFB "NO HAGAS TRAMPAS!" : DB 0 endif if LANGUE_FR CALL CLS2 LD HL,BADEND01:LD DE,&C1E0+9:CALL directmini LD HL,BADEND02:LD DE,&C320+24:CALL directmini LD HL,BADEND03:LD DE,&C460+3:CALL directmini LD HL,BADEND04:LD DE,&C5A0+18:CALL directmini RET BADEND01 DEFB "VOUS AVEZ FINI TOUS LES NIVEAUX" : DB 0 BADEND02 DEFB "MAIS EN TRICHANT" : DB 0 BADEND03 DEFB "DESOLES, PAS D;ECRAN DE FIN POUR VOUS" : DB 0 BADEND04 DEFB "REJOUEZ SANS TRICHER" : DB 0 endif if LANGUE_UK CALL CLS2 LD HL,BADEND01:LD DE,&C1E0+12:CALL directmini LD HL,BADEND02:LD DE,&C320+20:CALL directmini LD HL,BADEND03:LD DE,&C460+10:CALL directmini LD HL,BADEND04:LD DE,&C5A0+19:CALL directmini RET BADEND01 DEFB "YOU HAVE FINISHED ALL LEVELS" : DB 0 BADEND02 DEFB "BUT YOU HAVE CHEATED" : DB 0 BADEND03 DEFB "SORRY, NO FINAL SCREEN FOR YOU" : DB 0 BADEND04 DEFB "PLAY WITHOUT CHEATING" : DB 0 endif ;------------------------------------------------------------------------------ ; LOAD LEVEL ;------------------------------------------------------------------------------ .AFFICHAGE_LEVEL LD A,(IX+00) ;0 a 49 (numero du niveau) LD HL,LES_NIVEAUX-taille_niveau .calculadrniveau LD DE,taille_niveau ADD HL,DE DEC A CP &FF JP NZ,calculadrniveau ;transfert des donnees LD DE,load_niveau_courant LD BC,taille_niveau LDIR ;target=0 XOR A LD (memoire_target),A ;teleporteur 1x 1y 2x 2y =&FF LD A,&FF LD (teleporteur1x),A LD (teleporteur1y),A LD (teleporteur2x),A LD (teleporteur2y),A ;affichage du niveau LD IX,load_niveau_courant LD DE,ecran_niveau LD IY,0 ;compteur LD A,hauteur_niveau .aff_tableaulvl3 PUSH AF PUSH DE ; on sauvegarde l'adresse video de la premiere ligne de sprites a afficher LD A,largeur_niveau .aff_tableaulvl2 PUSH AF LD A,(IX+&00) ;sauver les registres pour faire les sous-totaux target et teleporteur PUSH AF PUSH IX PUSH IY CP 1:CALL Z,TARGET_PLUS CP 2:CALL Z,TARGET_PLUS CP 3:CALL Z,TARGET_PLUS CP 4:CALL Z,TARGET_PLUS CP 5:CALL Z,TARGET_PLUS CP 6:CALL Z,TARGET_PLUS CP 7:CALL Z,TARGET_PLUS CP 8:CALL Z,TARGET_PLUS CP 9:CALL Z,TARGET_PLUS CP 9:CALL Z,TELEPORTEUR CP 17:CALL Z,TELEPORTEUR POP IY POP IX POP AF ;fin sous-totaux INC IY ;pour le teleporteur INC IX LD L,A LD H,0 ADD HL,HL ; x2 ADD HL,HL ; x4 ADD HL,HL ; x8 ADD HL,HL ; x16 ADD HL,HL ; x32 ADD HL,HL ; x64 (16x16 = 4 octets x 16) LD BC,gfx_des_tiles ADD HL,BC PUSH DE CALL TILES_1 POP DE .aff_tableaulvl1 INC DE ;Case suivante 16 pixels = 4 octets INC DE INC DE INC DE POP AF DEC A JR NZ,aff_tableaulvl2 POP HL LD BC,&00A0 ADD HL,BC EX DE,HL ;Ligne suivante POP AF DEC A JR NZ,aff_tableaulvl3 RET .TARGET_PLUS LD HL,memoire_target INC (HL) RET .TELEPORTEUR LD A,(teleporteur1x) CP &FF CALL Z,teleporteur1xvide CP &FE RET Z ;on traite le premier donc fin LD A,(teleporteur2x) CP &FF CALL Z,teleporteur2xvide RET .teleporteur1xvide PUSH IY POP IX LD (teleporteur1x),IX LD A,&FE RET .teleporteur2xvide PUSH IY POP IX LD (teleporteur2x),IX RET ;------------------------------------------------------------------------------ ; HOW TO PLAY ;------------------------------------------------------------------------------ .HOWTOPLAY CALL CLS2 CALL &BB03 ;HOW TO PLAY LD HL,HOW00:LD DE,&C050+22:CALL directmini ;LADYBUG LD DE,&C140 LD HL,gfx_des_tiles+768 ;adresse tile 12 CALL TILES_1 LD DE,&C140+4 LD HL,gfx_des_tiles+640 ;adresse tile 10 CALL TILES_1 LD DE,&C140+4 ;adresse ecran LD HL,gfx_des_sprites ;adresse sprite(0*4*16) LD B,16 LD C,4 CALL TRAN_SPR_PR LD HL,HOW01:LD DE,&C140+10:CALL directmini LD HL,HOW02:LD DE,&C190+10:CALL directmini LD HL,HOW03:LD DE,&C230:CALL directmini LD HL,HOW04:LD DE,&C320:CALL directmini LD HL,HOW05:LD DE,&C410:CALL directmini LD HL,HOW06:LD DE,&C4B0:CALL directmini LD HL,HOW07:LD DE,&C5F0:CALL directmini LD HL,HOW08:LD DE,&C733-3:CALL directmini ;wait CALL &BB03:CALL &BB06 RET if LANGUE_SP HOW00 DEFB "\]] como jugar ]]^": DB 0 HOW01 DEFB "la mariquita ODIA EL AGUA":DB 0 HOW02 DEFB "UN NUEVO MINI HEROE":DB 0 ;-------------0123456789012345678901234567890123456789------------ HOW03 DEFB "TU MISION PUEDE PARECER FACIL, HAY QUE" DEFB "ELIMINAR TODAS LAS HOJAS DE LA PANTALLA." : DB 0 HOW04 DEFB "EL CONTADOR objetivo TE MUESTRA CUANTAS" DEFB "QUEDAN." : DB 0 HOW05 DEFB "AL PASAR POR LAS PIEDRAS NO TE HUNDIRAS." : DB 0 HOW06 DEFB "NO OLVIDES LEER LAS INSTRUCCIONES PARA" DEFB "CONOCER LAS CARACTERISTICAS ESPECIFICAS" DEFB "DE CADA ELEMENTO." : DB 0 HOW07 DEFB "EL JUEGO SE PUEDE USAR CON joystick," DEFB "TECLADO qaop O LOS cursores." : DB 0 HOW08 DEFB "m: MUSICA SI/NO esc: SALIR DEL JUEGO" : DB 0 endif if LANGUE_FR HOW00 DEFB "\]] comment jouer ]]^": DB 0 HOW01 DEFB "la coccinelle DETESTE L;EAU":DB 0 HOW02 DEFB "UN NOUVEAU MINI HEROS":DB 0 ;-------------0123456789012345678901234567890123456789------------ HOW03 DEFB "VOTRE MISSION SEMBLE FACILE, VOUS DEVEZ " DEFB "DETRUIRE TOUTES LES FEUILLES A L;ECRAN." : DB 0 HOW04 DEFB "LE COMPTEUR DE cible VOUS MONTRE COMBIEN" DEFB "IL EN RESTE A DETRUIRE." : DB 0 HOW05 DEFB "LES ROCHES VOUS EVITERONT DE COULER." : DB 0 HOW06 DEFB "N;OUBLIEZ PAS DE LIRE LES INSTRUCTIONS " DEFB "POUR CONNAITRE LES CARACTERISTIQUES " DEFB "SPECIFIQUES DE CHAQUE ELEMENT." : DB 0 HOW07 DEFB "LE JEU PEUT ETRE JOUE AVEC LE joystick, " DEFB "LE CLAVIER qaop OU LES touches curseurs." : DB 0 HOW08 DEFB "m:MUSIQUE OUI/NON esc:QUITTER LA PARTIE" : DB 0 endif if LANGUE_UK HOW00 DEFB "\]] how to play ]]^": DB 0 HOW01 DEFB "ladybug HATE THE WATER":DB 0 HOW02 DEFB "A NEW MINI HERO":DB 0 ;-------------0123456789012345678901234567890123456789------------ HOW03 DEFB "YOUR MISSION SEEMS TO BE EASY, YOU HAVE" DEFB "TO DESTROY ALL THE LEAVES AT SCREEN." : DB 0 HOW04 DEFB "THE target COUNTER SHOW YOU HOW MANY" DEFB "REMAINS." : DB 0 HOW05 DEFB "USING STONES WILL PREVENT YOU TO SINK." : DB 0 HOW06 DEFB "DON;T FORGET TO READ THE INSTRUCTIONS" DEFB "TO KNOW SPECIFIC FEATURES OF EACH" DEFB "ELEMENT." : DB 0 HOW07 DEFB "THE GAME CAN BE PLAYED WITH THE joystick" DEFB "KEYBOARD qaop OR THE arrows keys." : DB 0 HOW08 DEFB "m: MUSIC ON/OFF esc: EXIT THE GAME" : DB 0 endif ;------------------------------------------------------------------------------ ; MESSAGES ;------------------------------------------------------------------------------ .MESSAGES LD A,(IX) CP 0:CALL Z,cheatoff CP 1:CALL Z,cheaton CP 2:CALL Z,illegalH CP 3:CALL Z,illegalV CP 4:CALL Z,illegalM LD DE,&C000:CALL directmini RET .cheatoff LD HL,cheatmode1 RET .cheaton LD HL,cheatmode2 RET .illegalH LD HL,msg_illegalH RET .illegalV LD HL,msg_illegalV RET .illegalM LD HL,msg_illegalM RET if LANGUE_SP .cheatmode1 ;---------------------------------------- DEFB "]]]]]]]]]]]] desactiva cheat ]]]]]]]]]]]":DB 0 .cheatmode2 DEFB "]]]]]]]]]]]] activa cheat ]]]]]]]]]]]]":DB 0 .msg_illegalH DEFB " aqui solo te puedes mover en horizontal":DB 0 .msg_illegalV DEFB " aqui solo te puedes mover en vertical ":DB 0 .msg_illegalM DEFB " no, no puedes ir en esa direccion ":DB 0 endif if LANGUE_FR .cheatmode1 DEFB "]]]]]]]]]]] mode triche non ]]]]]]]]]]]]":DB 0 .cheatmode2 DEFB "]]]]]]]]]]] mode triche oui ]]]]]]]]]]]]":DB 0 .msg_illegalH DEFB " deplacement horizontal uniquement ":DB 0 .msg_illegalV DEFB " deplacement vertical uniquement ":DB 0 .msg_illegalM DEFB " non non, cette direction est interdite ":DB 0 endif if LANGUE_UK .cheatmode1 DEFB "]]]]]]]]]]]] cheat mode no ]]]]]]]]]]]]":DB 0 .cheatmode2 DEFB "]]]]]]]]]]]] cheat mode yes ]]]]]]]]]]]]":DB 0 .msg_illegalH DEFB " illegal move - cross horizontally only ":DB 0 .msg_illegalV DEFB " illegal move - cross verticaly only ":DB 0 .msg_illegalM DEFB " no no, this direction is prohibited ":DB 0 endif ;------------------------------------------------------------------------------ ; INSTRUCTION ;------------------------------------------------------------------------------ .INSTRUCTIONS CALL CLS2 CALL &BB03 ;Instructions - PAGE 1/2 LD HL,INS00:LD DE,&C050+22:CALL directmini ;LEAF LD DE,&C140+4 LD HL,gfx_des_tiles+128 ;adresse tile 2 CALL TILES_1 LD HL,INS01:LD DE,&C140+10:CALL directmini LD HL,INS02:LD DE,&C190+10:CALL directmini ;NENUPHAR LD DE,&C280+4 LD HL,gfx_des_tiles+64 ;adresse tile 1 CALL TILES_1 LD HL,INS03:LD DE,&C280+10:CALL directmini LD HL,INS04:LD DE,&C2D0+10:CALL directmini ;STONE LD DE,&C3C0+4 LD HL,gfx_des_tiles+640 ;adresse tile 10 CALL TILES_1 LD HL,INS05:LD DE,&C3C0+10:CALL directmini LD HL,INS06:LD DE,&C410+10:CALL directmini ;TREE TRUNCK LD DE,&C500+4 LD HL,gfx_des_tiles+1216 ;adresse tile 19 CALL TILES_1 LD HL,INS07:LD DE,&C500+10:CALL directmini LD HL,INS06:LD DE,&C550+10:CALL directmini ;JUMP X2 LD DE,&C640+4 LD HL,gfx_des_tiles+1152 ;adresse tile 18 CALL TILES_1 LD HL,INS08:LD DE,&C640+10:CALL directmini LD HL,INS06:LD DE,&C690+10:CALL directmini ;PAGE 1/2 if LANGUE_SP LD HL,INS09:LD DE,&C780+58:CALL directmini endif if LANGUE_FR LD HL,INS09:LD DE,&C780+62:CALL directmini endif if LANGUE_UK LD HL,INS09:LD DE,&C780+62:CALL directmini endif ;wait CALL &BB03:CALL &BB06 ;CLS CLASSIQUE CALL &BB6C ;Instructions - PAGE 2/2 LD HL,INS00:LD DE,&C050+22:CALL directmini ;CROSS H LD DE,&C140 LD HL,gfx_des_tiles+256 ;adresse tile 4 CALL TILES_1 LD DE,&C140+6 LD HL,gfx_des_tiles+768 ;adresse tile 12 CALL TILES_1 LD HL,INS11:LD DE,&C140+12:CALL directmini LD HL,INS10:LD DE,&C190+12:CALL directmini ;CROSS V LD DE,&C280 LD HL,gfx_des_tiles+192 ;adresse tile 3 CALL TILES_1 LD DE,&C280+6 LD HL,gfx_des_tiles+704 ;adresse tile 11 CALL TILES_1 LD HL,INS12:LD DE,&C280+12:CALL directmini LD HL,INS10:LD DE,&C2D0+12:CALL directmini ;TELEPORTEUR LD DE,&C3C0 LD HL,gfx_des_tiles+576 ;adresse tile 9 CALL TILES_1 LD DE,&C3C0+6 LD HL,gfx_des_tiles+1088 ;adresse tile 17 CALL TILES_1 LD HL,INS13:LD DE,&C3C0+12:CALL directmini LD HL,INS10:LD DE,&C410+12:CALL directmini ;FOLLOW DIRECTION LD HL,INS14:LD DE,&C500:CALL directmini LD DE,&C550 LD HL,gfx_des_tiles+320 ;adresse tile 5 CALL TILES_1 LD DE,&C550+6 LD HL,gfx_des_tiles+832 ;adresse tile 13 CALL TILES_1 LD HL,INS16:LD DE,&C550+12:CALL directmini LD HL,INS15:LD DE,&C5A0+12:CALL directmini LD DE,&C550+40 LD HL,gfx_des_tiles+512 ;adresse tile 8 CALL TILES_1 LD DE,&C550+46 LD HL,gfx_des_tiles+1024 ;adresse tile 16 CALL TILES_1 LD HL,INS17:LD DE,&C550+52:CALL directmini LD HL,INS15:LD DE,&C5A0+52:CALL directmini LD DE,&C640 LD HL,gfx_des_tiles+448 ;adresse tile 7 CALL TILES_1 LD DE,&C640+6 LD HL,gfx_des_tiles+960 ;adresse tile 15 CALL TILES_1 LD HL,INS18:LD DE,&C640+12:CALL directmini LD HL,INS15:LD DE,&C690+12:CALL directmini LD DE,&C640+40 LD HL,gfx_des_tiles+384 ;adresse tile 6 CALL TILES_1 LD DE,&C640+46 LD HL,gfx_des_tiles+896 ;adresse tile 14 CALL TILES_1 LD HL,INS19:LD DE,&C640+52:CALL directmini LD HL,INS15:LD DE,&C690+52:CALL directmini ;PAGE 2/2 if LANGUE_SP LD HL,INS20:LD DE,&C780+58:CALL directmini endif if LANGUE_FR LD HL,INS20:LD DE,&C780+62:CALL directmini endif if LANGUE_UK LD HL,INS20:LD DE,&C780+62:CALL directmini endif ;wait CALL &BB03:CALL &BB06 RET if LANGUE_SP INS00 DEFB "\]] instrucciones ]]^": DB 0 INS01 DEFB "hoja":DB 0 INS02 DEFB "DESAPARECE AL PASAR POR ENCIMA":DB 0 INS03 DEFB "nenufar":DB 0 INS04 DEFB "DESAPARECE AL PISARLA DOS VECES":DB 0 INS05 DEFB "piedra":DB 0 INS06 DB 34 : DEFB "NO DESAPARECE, NO SE HUNDE!":DB 0 INS07 DEFB "tronco - transporta a la mariquita":DB 0 INS08 DEFB "@pega un salto[":DB 0 INS09 DEFB "PAGINA 1/2":DB 0 INS10 DEFB "PUEDE SER HOJA O PIEDRA":DB 0 INS11 DEFB "aqui solo te mueves en horizontal":DB 0 INS12 DEFB "aqui solo te mueves en vertical":DB 0 INS13 DEFB "teletransportador":DB 0 INS14 DEFB "SIGUE LA DIRECCION DE LA FLECHA":DB 0 INS15 DEFB "HOJA/PIEDRA":DB 0 INS16 DEFB "hacia arriba":DB 0 INS17 DEFB "a la izquierda":DB 0 INS18 DEFB "hacia abajo":DB 0 INS19 DEFB "a la derecha":DB 0 INS20 DEFB "PAGINA 2/2":DB 0 endif if LANGUE_FR INS00 DEFB "\]] instructions ]]^": DB 0 INS01 DEFB "feuille":DB 0 INS02 DEFB "CASE DESTRUCTIBLE APRES 1 PASSAGE":DB 0 INS03 DEFB "nenuphar":DB 0 INS04 DEFB "CASE DESTRUCTIBLE APRES 2 PASSAGES":DB 0 INS05 DEFB "rocher":DB 0 INS06 DEFB "CASE INDESTRUCTIBLE":DB 0 INS07 DEFB "tronc - transporte la coccinelle":DB 0 INS08 DEFB "sauter a la deuxieme case":DB 0 INS09 DEFB "PAGE 1/2":DB 0 INS10 DEFB "FEUILLE OU ROCHER":DB 0 INS11 DEFB "deplacement horizontal uniquement":DB 0 INS12 DEFB "deplacement vertical uniquement":DB 0 INS13 DEFB "teleporteur vers teleporteur":DB 0 INS14 DEFB "SUIVRE LA DIRECTION AUTOMATIQUEMENT":DB 0 INS15 DEFB "FEUILLE/ROCHER":DB 0 INS16 DEFB "vers le haut":DB 0 INS17 DEFB "vers la gauche":DB 0 INS18 DEFB "vers le bas":DB 0 INS19 DEFB "vers la droite":DB 0 INS20 DEFB "PAGE 2/2":DB 0 endif if LANGUE_UK INS00 DEFB "\]] instructions ]]^": DB 0 INS01 DEFB "leaf":DB 0 INS02 DEFB "CASE DESTRUCTIBLE AFTER ONE PASS":DB 0 INS03 DEFB "nenuphar":DB 0 INS04 DEFB "CASE DESTRUCTIBLE AFTER TWO PASS":DB 0 INS05 DEFB "stone":DB 0 INS06 DEFB "CASE INDESTRUCTIBLE":DB 0 INS07 DEFB "tree trunck - transports ladybug":DB 0 INS08 DEFB "jump to the second case":DB 0 INS09 DEFB "PAGE 1/2":DB 0 INS10 DEFB "LEAF OR STONE":DB 0 INS11 DEFB "cross horizontally only":DB 0 INS12 DEFB "cross vertically only":DB 0 INS13 DEFB "teleporter to teleporter":DB 0 INS14 DEFB "LADYBUG FOLLOW DIRECTION AUTOMATICALLY":DB 0 INS15 DEFB "LEAF/STONE":DB 0 INS16 DEFB "go up":DB 0 INS17 DEFB "go left":DB 0 INS18 DEFB "go down":DB 0 INS19 DEFB "go right":DB 0 INS20 DEFB "PAGE 2/2":DB 0 endif ;------------------------------------------------------------------------------ ; CREDITS ;------------------------------------------------------------------------------ .CREDITS CALL CLS2 CALL &BB03 if LANGUE_SP .AFFCREDITS LD HL,txtcredits01:LD DE,&C06E:CALL directmini LD HL,txtcredits02:LD DE,&C0BE:CALL directmini LD HL,txtcredits03:LD DE,&C1A2-16:CALL directmini LD HL,txtcredits04:LD DE,&C244-10:CALL directmini LD HL,txtcredits05:LD DE,&C2A0:CALL directmini LD HL,txtcredits06:LD DE,&C330-2:CALL directmini LD HL,txtcredits07:LD DE,&C3D0-16:CALL directmini LD HL,txtcredits08:LD DE,&C470-2:CALL directmini LD HL,txtcredits09:LD DE,&C50C-6:CALL directmini LD HL,txtcredits10:LD DE,&C570:CALL directmini LD HL,txtcredits11:LD DE,&C5C0:CALL directmini LD HL,txtcredits12:LD DE,&C610:CALL directmini LD HL,txtcredits13:LD DE,&C660:CALL directmini LD HL,txtcredits14:LD DE,&C6B0:CALL directmini LD HL,txtcredits15:LD DE,&C700:CALL directmini LD HL,txtcredits16:LD DE,&C750:CALL directmini LD DE,&C730 ;adresse ecran LD HL,gfx_des_tiles+128 ;adresse tiles(2*4*16) CALL TILES_1 LD DE,&C730 ;adresse ecran LD HL,gfx_des_sprites ;adresse sprite(0*4*16) LD B,16 LD C,4 CALL TRAN_SPR_PR LD DE,&C734 LD HL,gfx_des_tiles+64 ;adresse tiles(1*4*16) CALL TILES_1 LD DE,&C694 ;adresse ecran LD HL,gfx_des_tiles+640 ;adresse tiles(10*4*16) CALL TILES_1 CALL &BB03 CALL &BB06 RET .txtcredits01 DEFB "creditos" : DB 0 .txtcredits02 DEFB "\]]]]]]^" : DB 0 .txtcredits03 DEFB "PROGRAMACION : kukulcan" : DB 0 .txtcredits04 DEFB "GRAFICOS : ced" : DB 0 .txtcredits05 DEFB "christophe petit" : DB 0 .txtcredits06 DEFB "MUSICA : rayxamber" : DB 0 .txtcredits07 DEFB "ILUSTRACIONES : toto" : DB 0 .txtcredits08 DEFB "TEXTOS : johnny farragut" : DB 0 .txtcredits09 DEFB "PROBADORES : arnaud bouche" : DB 0 .txtcredits10 DEFB "cpcmaniaco" : DB 0 .txtcredits11 DEFB "fredbezies" : DB 0 .txtcredits12 DEFB "fredouille" : DB 0 .txtcredits13 DEFB "johnny farragut" : DB 0 .txtcredits14 DEFB "johnny olsen" : DB 0 .txtcredits15 DEFB "maxit" : DB 0 .txtcredits16 DEFB "zisquier" : DB 0 endif if LANGUE_FR .AFFCREDITS LD HL,txtcredits01:LD DE,&C06E:CALL directmini LD HL,txtcredits02:LD DE,&C0BE:CALL directmini LD HL,txtcredits03:LD DE,&C1A2-18:CALL directmini LD HL,txtcredits04:LD DE,&C244-12:CALL directmini LD HL,txtcredits05:LD DE,&C2A0:CALL directmini LD HL,txtcredits06:LD DE,&C330-4:CALL directmini LD HL,txtcredits07:LD DE,&C3D0-16:CALL directmini LD HL,txtcredits08:LD DE,&C470-2:CALL directmini LD HL,txtcredits09:LD DE,&C50C-2:CALL directmini LD HL,txtcredits10:LD DE,&C570:CALL directmini LD HL,txtcredits11:LD DE,&C5C0:CALL directmini LD HL,txtcredits12:LD DE,&C610:CALL directmini LD HL,txtcredits13:LD DE,&C660:CALL directmini LD HL,txtcredits14:LD DE,&C6B0:CALL directmini LD HL,txtcredits15:LD DE,&C700:CALL directmini LD HL,txtcredits16:LD DE,&C750:CALL directmini LD DE,&C730 ;adresse ecran LD HL,gfx_des_tiles+128 ;adresse tiles(2*4*16) CALL TILES_1 LD DE,&C730 ;adresse ecran LD HL,gfx_des_sprites ;adresse sprite(0*4*16) LD B,16 LD C,4 CALL TRAN_SPR_PR LD DE,&C734 LD HL,gfx_des_tiles+64 ;adresse tiles(1*4*16) CALL TILES_1 LD DE,&C694 ;adresse ecran LD HL,gfx_des_tiles+640 ;adresse tiles(10*4*16) CALL TILES_1 CALL &BB03 CALL &BB06 RET .txtcredits01 DEFB "credits" : DB 0 .txtcredits02 DEFB "\]]]]]^" : DB 0 .txtcredits03 DEFB "PROGRAMMATION : kukulcan" : DB 0 .txtcredits04 DEFB "GRAPHISTE : ced" : DB 0 .txtcredits05 DEFB "christophe petit" : DB 0 .txtcredits06 DEFB "MUSIQUE : rayxamber" : DB 0 .txtcredits07 DEFB "ILLUSTRATIONS : toto" : DB 0 .txtcredits08 DEFB "TEXTES : galamoth" : DB 0 .txtcredits09 DEFB "TESTEURS : arnaud bouche" : DB 0 .txtcredits10 DEFB "cpcmaniaco" : DB 0 .txtcredits11 DEFB "fredbezies" : DB 0 .txtcredits12 DEFB "fredouille" : DB 0 .txtcredits13 DEFB "johnny farragut" : DB 0 .txtcredits14 DEFB "johnny olsen" : DB 0 .txtcredits15 DEFB "maxit" : DB 0 .txtcredits16 DEFB "zisquier" : DB 0 endif if LANGUE_UK .AFFCREDITS LD HL,txtcredits01:LD DE,&C06E:CALL directmini LD HL,txtcredits02:LD DE,&C0BE:CALL directmini LD HL,txtcredits03:LD DE,&C1A2:CALL directmini LD HL,txtcredits04:LD DE,&C244:CALL directmini LD HL,txtcredits05:LD DE,&C2A0:CALL directmini LD HL,txtcredits06:LD DE,&C330:CALL directmini LD HL,txtcredits07:LD DE,&C3D0-16:CALL directmini LD HL,txtcredits08:LD DE,&C470:CALL directmini LD HL,txtcredits09:LD DE,&C50C:CALL directmini LD HL,txtcredits10:LD DE,&C570:CALL directmini LD HL,txtcredits11:LD DE,&C5C0:CALL directmini LD HL,txtcredits12:LD DE,&C610:CALL directmini LD HL,txtcredits13:LD DE,&C660:CALL directmini LD HL,txtcredits14:LD DE,&C6B0:CALL directmini LD HL,txtcredits15:LD DE,&C700:CALL directmini LD HL,txtcredits16:LD DE,&C750:CALL directmini LD DE,&C730 ;adresse ecran LD HL,gfx_des_tiles+128 ;adresse tiles(2*4*16) CALL TILES_1 LD DE,&C730 ;adresse ecran LD HL,gfx_des_sprites ;adresse sprite(0*4*16) LD B,16 LD C,4 CALL TRAN_SPR_PR LD DE,&C734 LD HL,gfx_des_tiles+64 ;adresse tiles(1*4*16) CALL TILES_1 LD DE,&C694 ;adresse ecran LD HL,gfx_des_tiles+640 ;adresse tiles(10*4*16) CALL TILES_1 CALL &BB03 CALL &BB06 RET .txtcredits01 DEFB "credits" : DB 0 .txtcredits02 DEFB "\]]]]]^" : DB 0 .txtcredits03 DEFB "CODE : kukulcan" : DB 0 .txtcredits04 DEFB "GFX : ced" : DB 0 .txtcredits05 DEFB "christophe petit" : DB 0 .txtcredits06 DEFB "MUSIC : rayxamber" : DB 0 .txtcredits07 DEFB "ILLUSTRATIONS : toto" : DB 0 .txtcredits08 DEFB "TEXTS : galamoth" : DB 0 .txtcredits09 DEFB "TESTERS : arnaud bouche" : DB 0 .txtcredits10 DEFB "cpcmaniaco" : DB 0 .txtcredits11 DEFB "fredbezies" : DB 0 .txtcredits12 DEFB "fredouille" : DB 0 .txtcredits13 DEFB "johnny farragut" : DB 0 .txtcredits14 DEFB "johnny olsen" : DB 0 .txtcredits15 DEFB "maxit" : DB 0 .txtcredits16 DEFB "zisquier" : DB 0 endif ;------------------------------------------------------------------------------ ; MENU PRINCIPAL ;------------------------------------------------------------------------------ OPTIONS_MENU_BASIC LD A,(IX) CALL OPTIONS_MENU RET OPTIONS_MENU LD HL,MENU02b:LD (SUB2A+1),HL:CP 0:JR Z,NEXTSUB3:LD HL,MENU02a:LD (SUB2A+1),HL NEXTSUB3 LD HL,MENU03b:LD (SUB3A+1),HL:CP 1:JR Z,NEXTSUB4:LD HL,MENU03a:LD (SUB3A+1),HL NEXTSUB4 LD HL,MENU04b:LD (SUB4A+1),HL:CP 2:JR Z,NEXTSUB5:LD HL,MENU04a:LD (SUB4A+1),HL NEXTSUB5 LD HL,MENU05b:LD (SUB5A+1),HL:CP 3:JR Z,NEXTSUB6:LD HL,MENU05a:LD (SUB5A+1),HL NEXTSUB6 LD HL,MENU06b:LD (SUB6A+1),HL:CP 4:JR Z,NEXTSUB7:LD HL,MENU06a:LD (SUB6A+1),HL NEXTSUB7 LD HL,MENU07b:LD (SUB7A+1),HL:CP 5:JR Z,NEXTSUB8:LD HL,MENU07a:LD (SUB7A+1),HL NEXTSUB8 SUB2A LD HL,MENU02a:LD DE,&E190+34-4:CALL directmini SUB3A LD HL,MENU03a:LD DE,&E280+34-2:CALL directmini SUB4A LD HL,MENU04a:LD DE,&E370+34:CALL directmini SUB5A LD HL,MENU05a:LD DE,&E460+34-2:CALL directmini SUB6A LD HL,MENU06a:LD DE,&E550+34-4:CALL directmini SUB7A LD HL,MENU07a:LD DE,&E640+34-6:CALL directmini RET .MENU CALL CLS2 CALL AFFLADYBUG LD HL,MENU01:LD DE,&C050+24:CALL directmini XOR A CALL OPTIONS_MENU LD HL,MENU08:LD DE,&C780+18-4:CALL directmini RET MENU01 DEFB "\]] clevermind ]]": DB 94 : DB 0 if LANGUE_SP MENU02a DEFB " EMPEZAR PARTIDA" : DB 0 MENU02b DEFB "* empezar partida" : DB 0 MENU03a DEFB " INSTRUCCIONES" : DB 0 MENU03b DEFB "* instrucciones" : DB 0 MENU04a DEFB " COMO JUGAR" : DB 0 MENU04b DEFB "* como jugar" : DB 0 MENU05a DEFB " MUSICA" : DB 0 MENU05b DEFB "* musica" : DB 0 MENU06a DEFB " CREDITOS" : DB 0 MENU06b DEFB "* creditos" : DB 0 MENU07a DEFB " INT CODIGO " : DB 0 MENU07b DEFB "* int codigo .... " : DB 0 endif if LANGUE_FR MENU02a DEFB " DEMARRER DEFI" : DB 0 MENU02b DEFB "* demarrer defi" : DB 0 MENU03a DEFB " INSTRUCTIONS" : DB 0 MENU03b DEFB "* instructions" : DB 0 MENU04a DEFB " COMMENT JOUER" : DB 0 MENU04b DEFB "* comment jouer" : DB 0 MENU05a DEFB " MUSIQUE" : DB 0 MENU05b DEFB "* musique" : DB 0 MENU06a DEFB " CREDITS" : DB 0 MENU06b DEFB "* credits" : DB 0 MENU07a DEFB " SAISIR CODE " : DB 0 MENU07b DEFB "* saisir code .... " : DB 0 endif if LANGUE_UK MENU02a DEFB " START MISSION" : DB 0 MENU02b DEFB "* start mission" : DB 0 MENU03a DEFB " INSTRUCTIONS" : DB 0 MENU03b DEFB "* instructions" : DB 0 MENU04a DEFB " HOW TO PLAY" : DB 0 MENU04b DEFB "* how to play" : DB 0 MENU05a DEFB " MUSIC" : DB 0 MENU05b DEFB "* music" : DB 0 MENU06a DEFB " CREDITS" : DB 0 MENU06b DEFB "* credits" : DB 0 MENU07a DEFB " ENTER CODE " : DB 0 MENU07b DEFB "* enter code .... " : DB 0 endif MENU08 DEFB "< 2019 #$ WWW.CPC-POWER.COM": DB 0 ;------------------------------------------------------------------------------ ; INFORMATIONS INGAME ;------------------------------------------------------------------------------ .LEVEL ;lecture valeur adresse_ecran LD A,(IX+00) ADD A,&30 LD (INFOS1+8),A ;dizaine LD A,(IX+02) ADD A,&30 LD (INFOS1+7),A ;unite LD HL,INFOS1 LD DE,&C000 CALL directmini RET if LANGUE_SP INFOS1 DEFB " nivel*XX cdgo????" : DB 0 endif if LANGUE_FR INFOS1 DEFB "niveau*XX code????" : DB 0 endif if LANGUE_UK INFOS1 DEFB " level*XX code????" : DB 0 endif .LIVES ;lecture valeur adresse_ecran LD A,(IX+00) ADD A,&30 LD (INFOS2+6),A ;unite LD HL,INFOS2 LD DE,&C042 CALL directmini RET if LANGUE_SP INFOS2 DEFB "vidas*X" : DB 0 endif if LANGUE_FR INFOS2 DEFB " vies*X" : DB 0 endif if LANGUE_UK INFOS2 DEFB "lives*X" : DB 0 endif .TARGET ;lecture valeur adresse_ecran LD A,(IX+00) ADD A,&30 LD (INFOS3+11),A ;centaine LD A,(IX+02) ADD A,&30 LD (INFOS3+10),A ;dizaine LD A,(IX+04) ADD A,&30 LD (INFOS3+9),A ;unite LD HL,INFOS3 LD DE,&C028 CALL directmini RET if LANGUE_SP INFOS3 DEFB "objetivo*XXX" : DB 0 endif if LANGUE_FR INFOS3 DEFB " cible*XXX" : DB 0 endif if LANGUE_UK INFOS3 DEFB " target*XXX" : DB 0 endif ;------------------------------------------------------------------------------ ; SAUVER LE DECOR DE FOND ;------------------------------------------------------------------------------ .tampon_tile_sauvegarde : DEFS 64 ;TILE = 16px*16px = 4*16 = 64 octets .DECOR_16x16_SAUVEGARDE ;lecture adresse_ecran LD E,(IX+00) LD D,(IX+01) LD HL,tampon_tile_sauvegarde LD A,16 ;hauteur EX DE,HL .sauver_fond1 LDI ; 16 pixels = 4 octets LDI LDI LDI LD BC,&7FC ;ligne suivante &800-4(largeur du tile) ADD HL,BC JR NC,sauver_fond2 LD BC,&C050 ADD HL,BC .sauver_fond2 DEC A JR NZ,sauver_fond1 RET ;------------------------------------------------------------------------------ ; RESTAURER LE DECOR DE FOND ;------------------------------------------------------------------------------ .DECOR_16x16_RESTAURATION ;lecture adresse_ecran LD E,(IX+00) LD D,(IX+01) LD HL,tampon_tile_sauvegarde LD A,16 ;hauteur .restore_fond1 LDI ; 16 pixels = 4 octets LDI LDI LDI EX DE,HL LD BC,&7FC ;ligne suivante &800-4(largeur du tile) ADD HL,BC JR NC,restore_fond2 LD BC,&C050 ADD HL,BC .restore_fond2 EX DE,HL DEC A JR NZ,restore_fond1 RET ;------------------------------------------------------------------------------ ; TILES 16x16 opaque ; Entrees ; ; A = element ; DE = adresse ecran ;------------------------------------------------------------------------------ .TILES_16x16_opaque ;lecture valeur adresse_ecran LD E,(IX+00) LD D,(IX+01) PUSH DE ;element opaque LD A,(IX+02) ;0 a 18 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 ADD HL,HL ;*32 ADD HL,HL ;*64 LD DE,gfx_des_tiles ADD HL,DE ;HL contient l'adresse du tiles POP DE ;DE adresse ecran .TILES_1 LD A,16 .TILES_2 LDI ;16 pixels = 4 octets LDI LDI LDI EX DE,HL LD BC,&07FC ADD HL,BC JR NC,TILES_3 LD BC,&C050 ADD HL,BC .TILES_3 EX DE,HL DEC A JR NZ,TILES_2 RET .directmini LD A,(HL) CP 0 RET Z PUSH HL PUSH DE CALL aff_TILES8_0 POP DE INC DE:INC DE ;+2 pixels POP HL INC HL ;position caractere suivant JR directmini ;------------------------------------------------------------------------------ ; ELEMENTS TRANSPARENT ; Entrees ; ; A = element ; DE = adresse ecran ;------------------------------------------------------------------------------ AFFICHAGE_ELEMENT_TRANSPARENT ;lecture valeur adresse_ecran LD E,(IX+00) LD D,(IX+01) PUSH DE ;element transparent LD A,(IX+02) ;0 a 5 .SPRDIRECT 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 ADD HL,HL ;*32 ADD HL,HL ;*64 LD DE,gfx_des_sprites ADD HL,DE ;HL contient l'adresse de la tuile LD B,16 LD C,4 POP DE CALL TRAN_SPR_PR RET ;------------------------------------------------------------------------------ ; Sprite transparent en mode 0 ; Entrees ; ; - B = nombre de lignes ; - C = largeur du sprite en octets ; - HL = adresse du sprite ; - DE = adresse ecran. ;------------------------------------------------------------------------------ TRAN_SPR_PR PUSH BC PUSH DE TRAN_SPR_P0 LD A,(HL) ; A = octet courant LD B,A OR A ; Octet transparent? JR Z,TRAN_SPR_P1 ; Oui => prochain octet (couleurs inchangees) AND %10101010 ; Couleur gauche transparente? JR NZ,TRAN_SPR_P3 ; Non => TRAN_SPR_P3 LD A,(DE) ; Oui => octet = couleur droite du sprite + couleur gauche du fond d'ecran AND %10101010 OR B LD (DE),A ; Octet paint TRAN_SPR_P1 INC HL INC DE DEC C JR NZ,TRAN_SPR_P0 POP DE ; DE = ligne ecran suivante (+&0800 or +&C800) EX HL,DE LD BC,&800 ADD HL,BC JR NC,TRAN_SPR_P2 LD BC,&C050 ADD HL,BC TRAN_SPR_P2 EX HL,DE POP BC DJNZ TRAN_SPR_PR RET TRAN_SPR_P3 LD A,B AND %01010101 ; Is sprite right color black? JR NZ,TRAN_SPR_P5 ; No => TRAN_SPR_P5 LD A,(DE) ; Oui => octet = couleur gauche du sprite + couleur droite du fond d'ecran AND %01010101 OR B LD (DE),A ; Octet paint INC HL INC DE DEC C JR NZ,TRAN_SPR_P0 POP DE ; DE = ligne ecran suivante (+&0800 or +&C800) EX HL,DE LD BC,&800 ADD HL,BC JR NC,TRAN_SPR_P4 LD BC,&C050 ADD HL,BC TRAN_SPR_P4 EX HL,DE POP BC DJNZ TRAN_SPR_PR RET TRAN_SPR_P5 LD A,(DE) LD A,B LD (DE),A ; Octet = octet entier du sprite JR TRAN_SPR_P1 RET ;------------------------------------------------------------------------------ ; TILE8 OPAQUE ;------------------------------------------------------------------------------ .TILE8 ;lecture valeur caractere LD A,(IX+2) ;lecture valeur adresse_ecran LD D,(IX+1) LD E,(IX+0) .aff_TILES8_0 LD C,32 SUB C ;A = A-32 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 ;------------------------------------------------------------------------------ ;syntax |CLS2 ;Vider l'ecran ;------------------------------------------------------------------------------ .CLS2 LD HL,&C000 LD BC,&4000 clsloop2: LD (HL),&0C;remplir avec l'encre 2 (bleu) LD DE,&0059 ADD HL,DE JR NC,clsloop1 ;CALL &BD19 LD DE,&C000 ADD HL,DE clsloop1: DEC BC LD A,B OR C JR NZ,clsloop2 RET ;------------------------------------------------------------------------------ ;FEUILLE AVEC LADYBUG POUR LE MENU PRINCIPAL ;------------------------------------------------------------------------------ .txtladybug DEFB " < " DEFB " <<< " DEFB " <<<<< " DEFB " <<<<<<< " DEFB " <=<<<=< " DEFB " <<<=<=<<< " DEFB " <<<<<=<<<<< " DEFB " <<<<%=%<<<< " DEFB " <<<<=====<<<< " DEFB " <<<>>>=>>><<< " DEFB "<<<>>=>=>=>><<<" DEFB "<<<>>>>=>>>><<<" DEFB "<<<>=>>=>>=><<<" DEFB "<<<>>>>=>>>><<<" DEFB " <<<>=>=>=><<< " DEFB " <<<<>>=>><<<< " DEFB " <<<<>=><<<< " DEFB " <<<<<<<<< " DEFB " <<<<<<< " DEFB " <<<<< " DEFB " <<< " DEFB " < " DEFB " < " DEFB " < " .AFFLADYBUG LD HL,txtladybug LD A,15 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,24 ;hauteur a afficher LD DE,&C000 CALL AFF_TABLEAU RET ;------------------------------------------------------------------------------ ;syntax |OHNO ; ;------------------------------------------------------------------------------ if LANGUE_SP ;SP = !OH NO! ;Debut ligne texte 11, colonne 7/40 ;Largeur = 26 ;Hauteur = 5 .txtohno DEFB "' '' ' ' ' ' '' '" DEFB " ' ' ' ' '' ' ' ' '" DEFB "' ' ' '''' ' '' ' ' '" DEFB "' ' ' ' ' ' ' ' ' " DEFB "' '' ' ' ' ' '' '" .AFFOHNO LD HL,txtohno LD A,26 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,5 ;hauteur a afficher LD DE,&C320+14 CALL AFF_TABLEAU RET endif if LANGUE_FR ;FR = AH NON! ;Debut ligne texte 11, colonne 6/40 ;Largeur = 28 ;Hauteur = 5 .txtohno DEFB " '' ' ' ' ' '' ' ' '" DEFB "' ' ' ' '' ' ' ' '' ' '" DEFB "'''' '''' ' '' ' ' ' '' '" DEFB "' ' ' ' ' ' ' ' ' ' " DEFB "' ' ' ' ' ' '' ' ' '" .AFFOHNO LD HL,txtohno LD A,28 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,5 ;hauteur a afficher LD DE,&C320+12 CALL AFF_TABLEAU RET endif if LANGUE_UK ;UK = OH NO! ;Debut ligne texte 11, colonne 8/40 ;Largeur = 24 ;Hauteur = 5 .txtohno DEFB " '' ' ' ' ' '' '" DEFB "' ' ' ' '' ' ' ' '" DEFB "' ' '''' ' '' ' ' '" DEFB "' ' ' ' ' ' ' ' " DEFB " '' ' ' ' ' '' '" .AFFOHNO LD HL,txtohno LD A,24 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,5 ;hauteur a afficher LD DE,&C320+16 CALL AFF_TABLEAU RET endif ;------------------------------------------------------------------------------ ;syntax |DONE ;------------------------------------------------------------------------------ if LANGUE_SP ;SP = !BRAVO! ;Debut ligne texte 11, colonne 5,5/40 ;Largeur = 29 ;Hauteur = 5 .txtwelldone DEFB "' ''' ''' '' ' ' '' '" DEFB " ' ' ' ' ' ' ' ' ' ' '" DEFB "' '''' ''' '''' ' ' ' ' '" DEFB "' ' ' ' ' ' ' ' ' ' ' " DEFB "' ''' ' ' ' ' ' '' '" .AFFDONE LD HL,txtwelldone LD A,29 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,5 ;hauteur a afficher LD DE,&C320+11 CALL AFF_TABLEAU RET endif if LANGUE_FR ;FR = BRAVO! ;Debut ligne texte 11, colonne 6,5/40 ;Largeur = 27 ;Hauteur = 5 .txtwelldone DEFB "''' ''' '' ' ' '' '" DEFB "' ' ' ' ' ' ' ' ' ' '" DEFB "'''' ''' '''' ' ' ' ' '" DEFB "' ' ' ' ' ' ' ' ' ' " DEFB "''' ' ' ' ' ' '' '" .AFFDONE LD HL,txtwelldone LD A,27 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,5 ;hauteur a afficher LD DE,&C320+13 CALL AFF_TABLEAU RET endif if LANGUE_UK ;UK = WELL DONE! ;Debut ligne texte 7, colonne 9/40 ;Largeur = 22 ;Hauteur = 11 .txtwelldone DEFB " ' ' '''' ' ' " DEFB " ' ' ' ' ' " DEFB " ' ' '' ' ' " DEFB " ' ' ' ' ' ' " DEFB " ' ' '''' '''' '''' " DEFB " " DEFB "''' '' ' ' '''' '" DEFB "' ' ' ' '' ' ' '" DEFB "' ' ' ' ' '' '' '" DEFB "' ' ' ' ' ' ' " DEFB "''' '' ' ' '''' '" .AFFDONE LD HL,txtwelldone LD A,22 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,11 ;hauteur a afficher LD DE,&C1E0+18 CALL AFF_TABLEAU RET endif ;------------------------------------------------------------------------------ ;syntax |LOST ;------------------------------------------------------------------------------ if LANGUE_SP ;SP = FIN DE LA PARTIDA ;Debut ligne texte 8, colonne 1,5/40 ;Largeur = 37 ;Hauteur = 11 .txtgameover DEFB "'''' ''' ' ' ''' '''' ' '' " DEFB "' ' '' ' ' ' ' ' ' '" DEFB "''' ' ' '' ' ' ''' ' ''''" DEFB "' ' ' ' ' ' ' ' ' '" DEFB "' ''' ' ' ''' '''' '''' ' '" DEFB " " DEFB " ''' '' ''' ''' ''' ''' '' " DEFB " ' ' ' ' ' ' ' ' ' ' ' ' " DEFB " ''' '''' ''' ' ' ' ' '''' " DEFB " ' ' ' ' ' ' ' ' ' ' ' " DEFB " ' ' ' ' ' ' ''' ''' ' ' " .AFFGAMEOVER LD HL,txtgameover LD A,37 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,11 ;hauteur a afficher LD DE,&C230+3 CALL AFF_TABLEAU RET endif if LANGUE_FR ;FR = FIN DE PARTIE ;Debut ligne texte 8, colonne 6,5/40 ;Largeur = 27 ;Hauteur = 11 .txtgameover DEFB " '''' ''' ' ' ''' '''' " DEFB " ' ' '' ' ' ' ' " DEFB " ''' ' ' '' ' ' ''' " DEFB " ' ' ' ' ' ' ' " DEFB " ' ''' ' ' ''' '''' " DEFB " " DEFB "''' '' ''' ''' ''' ''''" DEFB "' ' ' ' ' ' ' ' ' " DEFB "''' '''' ''' ' ' ''' " DEFB "' ' ' ' ' ' ' ' " DEFB "' ' ' ' ' ' ''' ''''" .AFFGAMEOVER LD HL,txtgameover LD A,27 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,11 ;hauteur a afficher LD DE,&C230+13 CALL AFF_TABLEAU RET endif if LANGUE_UK ;UK = GAME OVER! ;Debut ligne texte 8, colonne 9/40 ;Largeur = 22 ;Hauteur = 11 .txtgameover DEFB " '''' '' ' ' '''' " DEFB " ' ' ' '' '' ' " DEFB " ' '' '''' ' ' ' '' " DEFB " ' ' ' ' ' ' ' " DEFB " '''' ' ' ' ' '''' " DEFB " " DEFB " '' ' ' '''' ''' '" DEFB "' ' ' ' ' ' ' '" DEFB "' ' ' ' '' ''' '" DEFB "' ' ' ' ' ' ' " DEFB " '' ' '''' ' ' '" .AFFGAMEOVER LD HL,txtgameover LD A,22 LD (aff_tableau_largeur+1),A ;largeur a afficher PUSH HL ;sauver dans HL POP IX ;restaurer dans IX LD A,11 ;hauteur a afficher LD DE,&C230+18 CALL AFF_TABLEAU RET endif ;------------------------------------------------------------------------------ ;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 ;------------------------------------------------------------------------------ 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,LES_NIVEAUX_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! ;------------------------------------------------------------------------------ ; Player Arkos tracker ;------------------------------------------------------------------------------ PLAYER_ARKOS list ;*** Start of Arkos Tracker Player nolist ; music selector LD A,(IX+00) ; numero de la musique 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_RAYXAMBER1 defw ZIC_RAYXAMBER2 defw ZIC_RAYXAMBER3 defw &0000 ; rien ; 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
 

NOTICE TEXTE n° 3 (56.45 Ko)

- - - - - - - - - - - - - - - - - [ 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, programmation par Kukulcan © 2007-2024 tous droits réservés.
Reproduction sans autorisation interdite. Tous les titres utilisés appartiennent à leurs propriétaires respectifs.
Hébergement Web, Mail et serveurs de jeux haute performance