;**************************************** ;* CrASHEmu * ;*Emulateur du shell CrASH 1.6 pour SNG * ;* 18/07/2004 * ;* par Marc Plouhinec * ;* site: http://www.thebestof.tk * ;* Email: mailto://m_plouhinec@yahoo.fr * ;* * ;**************************************** ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License ; as published by the Free Software Foundation; either version 2 ; of the License, or (at your option) any later version. ;Ce programme émule l'environnement de CrASH 1.6 et adapte les appels vers la rom ;pour les routines ayant changées d'adresses depuis la rom 19.0 (comme GET_KEY) ;Principe du programme: ;On remplace SNG par un CrASh modifié. ;Ce CrASH modifié copie (depuis CRASHEMU) dans APD_BUF le code chargé de déplacer le programme #include "sng10.inc" DEBUT_PROG = $9104-5 DEBUT_PROG_1 = $90 DEBUT_PROG_2 = $FF CP_HL_BC_CRASH2 = $8D8E .ORG START_ADDR Commentaire .DB "CrASHEmu par Marc Plouhinec",0 ;-------------------------------------- ;1-On créer une liste de programmes ; compatibles avec CrASH ;-------------------------------------- CALL ChercheProgTEXT_MEM ;Place dans TEXT_MEM les adresses dans la VAT des programmes compatibles LD A,(NombreDeProgrammes) OR A RET Z CALL AfficheListe XOR A LD (ProgrammeSelectionne),A CALL AfficheUnrectangleSurLeAemeProg CALL GRB_COPY Touches: ROM_CALL(GET_KEY) cp G_CLEAR RET Z cp G_UP CALL Z,Haut cp G_DOWN CALL Z,Bas cp G_ENTER JR Z,Entree halt jr Touches Haut: LD A,(ProgrammeSelectionne) OR A RET Z CALL AfficheUnrectangleSurLeAemeProg LD A,(ProgrammeSelectionne) DEC A LD (ProgrammeSelectionne),A CALL AfficheUnrectangleSurLeAemeProg CALL GRB_COPY RET Bas: LD A,(NombreDeProgrammes) LD B,A LD A,(ProgrammeSelectionne) DEC B CP B RET Z CALL AfficheUnrectangleSurLeAemeProg LD A,(ProgrammeSelectionne) INC A LD (ProgrammeSelectionne),A CALL AfficheUnrectangleSurLeAemeProg CALL GRB_COPY RET Entree: LD A,(ProgrammeSelectionne) LD H,0 LD L,A ADD HL,HL LD BC,TEXT_MEM ADD HL,BC CALL LD_HL_MHL INC HL LD (AdresseProgALancer),HL ;HL->06 JP LanceProg ChercheProgTEXT_MEM: LD HL,TEXT_MEM LD DE,TEXT_MEM+1 LD (HL),0 LD BC,127 LDIR XOR A LD (NombreDeProgrammes),A LD HL,TEXT_MEM LD (ListeIndex),HL LD HL,VAT_START PUSH HL ChercheProg: POP HL LD A,6 LD BC,$ffff CPDR LD DE,(VAT_END) CALL CP_HL_DE RET C OnAPasFini: DEC HL PUSH HL LD (AdresseProgVAT),HL LD D,(HL) INC HL LD E,(HL) EX DE,HL INC HL INC HL LD A,(HL) CP $D5 JR NZ,ChercheProgASH INC HL LD A,(HL) CP $00 JR NZ,ChercheProg INC HL LD A,(HL) CP $11 JR NZ,ChercheProg ProgTrouve: POP HL PUSH HL LD HL,(ListeIndex) LD (HL),E INC HL LD (HL),D INC HL LD (ListeIndex),HL LD A,(NombreDeProgrammes) INC A CP 11 JR Z,TropDeProgrammes LD (NombreDeProgrammes),A JR ChercheProg TropDeProgrammes: POP HL RET ChercheProgASH: CP $D9 JR NZ,ChercheProg INC HL LD A,(HL) CP $00 JR NZ,ChercheProg INC HL LD A,(HL) CP $30 JR NZ,ChercheProg JR ProgTrouve AfficheListe: SET 7,(IY+$14) ;Ecrit du texte de menu seulement dans la mémoire graphique (GRAPH_MEM) et pas sur l'écran LCD LD HL,0 LD (GRAF_CURS),HL LD HL,TEXT_MEM LD (ListeIndex),HL AfficheNom: LD HL,(ListeIndex) CALL LD_HL_MHL LD E,(HL) DEC HL LD D,(HL) EX DE,HL LD BC,5 ADD HL,BC ROM_CALL(D_ZM_STR) LD HL,(GRAF_CURS) LD L,0 LD A,H ADD A,6 LD H,A LD (GRAF_CURS),HL LD HL,(ListeIndex) INC HL INC HL LD (ListeIndex),HL XOR A CP (HL) RET Z INC HL CP (HL) RET Z JR AfficheNom AfficheUnrectangleSurLeAemeProg: LD HL,6*12 LD C,A LD B,0 CALL MUL_HL_BC LD BC,GRAPH_MEM ADD HL,BC LD B,6*12 AfficheRectangle: LD A,(HL) XOR $FF LD (HL),A INC HL DJNZ AfficheRectangle RET ListeIndex .DW 0 NombreDeProgrammes .DB 0 ProgrammeSelectionne .DB 0 ;-------------------------------------- ;2-On remplace SNG par CRASHMODIFIE ;-------------------------------------- LanceProg: LD HL,PetitCode LD DE,TEXT_MEM LD BC,TaillePetitCode JP EXT_INSTR PetitCode: ;On cherche dans la ram le programme CRASHEMU LD HL,(VAT_END) ChercheCRASHEMU: LD BC,$ffff LD A,6 CPIR PUSH HL LD BC,5 SBC HL,BC LD DE,CrASHEmuChaine-PetitCode+TEXT_MEM LD C,1 CALL CP_STRING POP HL OR A JR Z,ChercheCRASHEMU DEC HL DEC HL LD E,(HL) DEC HL LD D,(HL) EX DE,HL ;HL->CRASHEMU LD D,H ; LD E,L ; LD BC,AdresseCRASHEMUDansRam-Commentaire+39+2 ;LD (AdresseCRASHEMUDansRam),HL ADD HL,BC ; LD (HL),E ; INC HL ; LD (HL),D ; EX DE,HL ; LD DE,CRASHMODIFIE-Commentaire+39+2 ADD HL,DE ;HL->CRASHMODIFIE LD DE,$8D26 LD BC,TailleCRASHMODIFIE EchangeDonnees: PUSH BC LD A,(DE) LD C,(HL) EX DE,HL LD (DE),A LD (HL),C EX DE,HL INC DE INC HL POP BC DEC BC XOR A CP B JR NZ,EchangeDonnees CP C JR NZ,EchangeDonnees JP $8D26 CrASHEmuChaine .DB "CRASHEMU",0 PetitCodeFin: TaillePetitCode = PetitCodeFin-PetitCode CRASHMODIFIE: ;adresse $8d26 ;-------------------------------------- ;3-On adapte les ROM_CALL ;-------------------------------------- CALL AdapteROMCALL-CRASHMODIFIE+$8D26 ;-------------------------------------- ;4-On lance le programme ;-------------------------------------- ROM_CALL(DEL_TMP) LD HL,(AdresseProgALancer-CRASHMODIFIE+$8D26) DEC HL LD E,(HL) DEC HL LD D,(HL) LD (AdresseProgVAT-CRASHMODIFIE+$8D26),HL EX DE,HL CALL PlaceLeProg-CRASHMODIFIE+$8D26 CALL PrepareEtLanceCode-CRASHMODIFIE+$8D26 ;-------------------------------------- ;5-On replace le programme ;-------------------------------------- CALL RePlaceLeProg-CRASHMODIFIE+$8D26 ;On remet SNG comme avant grace à PetitCode2 LD HL,PetitCode2-CRASHMODIFIE+$8D26 LD DE,TEXT_MEM LD BC,PetitCode2Taille LDIR JP TEXT_MEM RAND: ;Routine originale de Crash 1.6 LD A,$A6 RAND0 = $-1 PUSH HL LD HL,$8243 RAND1 = $-2 INC L DEC H ADD A,(HL) LD (RAND1-CRASHMODIFIE+$8D26),HL RLCA RLCA SUB H ADD A,L POP HL LD (RAND0-CRASHMODIFIE+$8D26),A SRL A RET AdresseProgVAT .DW 0 AdresseProgALancer .DW 0 BLOC1: .DS $8d70-$8d26-BLOC1+CRASHMODIFIE ;adresse $8d70 ; APD_FREE .DW 0 INT_STATE .DB 0 CRASH_VER .DB $16 ;adresse $8D74 JP $0000 ROM_CALLS = $-2 ;adresse $8D77 BLOC2_0: EXIT_2_TIOS: ;Non émulé RET CP_HL_BC_CRASH: ;Routine originale de Crash 1.6 PUSH HL OR A SBC HL,BC POP HL RET CR_KHAND_CRASH: ROM_CALL(KEY_HAND) RET BLOC2: .DS $8D88-$8D77-BLOC2+BLOC2_0 ;adresse $8D88 JP EXIT_2_TIOS-CRASHMODIFIE+$8D26 JP RAND-CRASHMODIFIE+$8D26 JP CP_HL_BC_CRASH-CRASHMODIFIE+$8D26 JP CR_KHAND_CRASH-CRASHMODIFIE+$8D26 JP CR_GRBCopy_CRASH-CRASHMODIFIE+$8D26 ;adresse $8D97 BLOC3_0: CR_GRBCopy_CRASH: ;Routine originale de Crash 1.6 PUSH HL LD HL,GRAPH_MEM PUSH AF LD A,$80 OUT ($10),A PUSH BC PUSH DE RLCA DEC HL LD C,$20 OR A OUT ($10),A INC (HL) DEC (HL) LD A,(HL) LD DE,$C LD A,C CR_GRBCopy_CRASH0: OUT ($10),A INC HL LD B,$40 INC C CR_GRBCopy_CRASH1: INC DE DEC DE LD A,(HL) ADD HL,DE OUT ($11),A DJNZ CR_GRBCopy_CRASH1 DEC H DEC H DEC H LD A,C CP $2C JR NZ,CR_GRBCopy_CRASH0 POP DE POP BC POP AF POP HL RET AdapteROMCALL: LD A,($29D0) ;pour rom |16.0:36| |17.0:37| |18.0:38| |19.0:6D| |19.006:18| CP $18 JR Z,nouv_rom CP $6D JR Z,rom_190 LD HL,0 LD (aSetRomOffset_2+1-CRASHMODIFIE+$8D26),HL LD HL,ROM_CALL_anciennes_rom-CRASHMODIFIE+$8D26 JR adapte_rom_cont rom_190: LD HL,$1A LD (aSetRomOffset_2+1-CRASHMODIFIE+$8D26),HL LD HL,ROM_CALL_anciennes_rom-CRASHMODIFIE+$8D26 JR adapte_rom_cont nouv_rom: CALL AdapteNOUVROMCALL-CRASHMODIFIE+$8D26 LD HL,ROM_CALL_nouvelles_rom-CRASHMODIFIE+$8D26 adapte_rom_cont: LD (ROM_CALLS-CRASHMODIFIE+$8D26),HL RET ROM_CALL_nouvelles_rom: ;ROM_CALL(adresse) = CALL $8D74 \ .DW adresse LD (ROM_CALLan1-CRASHMODIFIE+$8D26),A ;On sauve A LD (ROM_CALLan3-CRASHMODIFIE+$8D26),DE ;On sauve DE LD (ROM_CALLan4-CRASHMODIFIE+$8D26),BC ;On sauve BC LD (ROM_CALLan5-CRASHMODIFIE+$8D26),HL ;On sauve HL EX (SP),HL ; LD E,(HL) ; INC HL ; Met dans DE l'adresse à appeller LD D,(HL) ; INC HL ; EX (SP),HL ; LD A,$FF LD HL,rom_call_zones-1-CRASHMODIFIE+$8D26 JR modif_appel modif_appel0: EX DE,HL modif_appel: INC A INC HL LD C,(HL) INC HL LD B,(HL) EX DE,HL CALL CP_HL_BC_CRASH2 JR NC,modif_appel0 EX DE,HL SLA A LD H,0 LD L,A LD BC,rom_call_diff-CRASHMODIFIE+$8D26 ADD HL,BC LD A,(HL) INC HL LD H,(HL) LD L,A ADD HL,DE PUSH HL LD BC,0 ROM_CALLan4 = $-2 LD DE,0 ROM_CALLan3 = $-2 LD A,0 ROM_CALLan1 = $-1 LD HL,0 ROM_CALLan5 = $-2 RET ROM_CALL_anciennes_rom: ld (aSaveHLRom_2+1-CRASHMODIFIE+$8D26),hl ; Save HL pop hl ; Correct return address push hl inc hl inc hl ex (sp),hl ; Address of ROM offset in HL push de ; Save DE ld e,(hl) ; Get offset in DE inc hl ld d,(hl) aSetRomOffset_2: ld hl,$001A ; Offset for ROM version 19.0 add hl,de ; Correct address for ROM version 19.0 pop de ; restore DE push hl ; Fake return address aSaveHLRom_2: ld hl,0 ; Restore HL ret ; Jump to ROM routine ;indispensable pour adapter les appels à la rom 19.006 rom_call_diff: .DW 0 .DW 0 .DW $1F .DW $51 .DW $52 .DW $53 .DW $9B .DW $46 .DW $57 .DW $221 .DW $53 .DW $FFCE ;-32 .DW $43 .DW $47 .DW $12B .DW $12C .DW $12E .DW $12F .DW $13F .DW $142 .DW $145 .DW $143 .DW $144 .DW $160 .DW $166 .DW $13C .DW $15D .DW $157 .DW $14B .DW $145 .DW $13F .DW $139 .DW $1E7 .DW $133 .DW $13F .DW $127 .DW $133 .DW $157 .DW $163 .DW $163 rom_call_zones: .DW $0008 .DW $0103 .DW $021d .DW $0272 .DW $027E .DW $059D .DW $05AD .DW $05F2 .DW $061E .DW $0625 .DW $066A .DW $067A .DW $0684 .DW $07F8 .DW $0A0D .DW $0FCE .DW $0FD0 .DW $0FD5 .DW $0FF9 .DW $1005 .DW $29D6 .DW $2E1C .DW $2E22 .DW $2E37 .DW $2E3C .DW $2E46 .DW $31E1 .DW $3249 .DW $32DF .DW $37B3 .DW $37C5 .DW $3876 .DW $387C .DW $38BB .DW $38C7 .DW $38D0 .DW $390F .DW $3924 .DW $4000 PrepareEtLanceCode: LD HL,DEBUT_PROG+5 LD BC,100 XOR A CPIR ;HL->Adresse de la première instruction du programme LD (ApelProg-CRASHMODIFIE+$8D26),HL LD HL,GRAPH_MEM LD DE,GRAPH_MEM+1 LD (HL),0 LD BC,767 LDIR LD HL,TEXT_MEM LD DE,TEXT_MEM+1 LD (HL),0 LD BC,127 LDIR RES 7,(IY+$14) RES 1,(IY+$0D) CALL $0000 ;On lance le programme ApelProg = $-2 RET PlaceLeProg: ;Pour déplacer le programme, on créer une zone libre juste après SNG et on détruit le programme original après l'avoir copié. ;Pour ne pas gaspiller de la mémoire, on augmente la taille de la zone libre en même temps qu'on réduit la taille du programme. ;initialisation LD (AdresseInitProg),HL LD C,(HL) INC HL LD B,(HL) INC BC INC BC LD (TailleDonnesADeplacer),BC LD (TailleProg),BC DEC HL LD (AdresseProgDetruit),HL LD HL,DEBUT_PROG LD (AdresseProgDeplace),HL CreationDeZoneLibre: ;On créer une zone de mémoire à l'adresse AdresseProgDeplace de HL octets ;HL est { = 768 si TailleDonnesADeplacer>768 ; = TailleDonnesADeplacer sinon LD HL,(TailleDonnesADeplacer) LD BC,768 SBC HL,BC JP P,TaillePositive-CRASHMODIFIE+$8D26 LD HL,(TailleDonnesADeplacer) JR TailleCalculee TaillePositive: LD HL,768 TailleCalculee: PUSH HL LD DE,(TailleDonnesADeplacer) EX DE,HL SBC HL,DE LD (TailleDonnesADeplacer),HL POP HL ;On a calculé la taille de la mémoire à allouer PUSH HL LD DE,(AdresseProgDeplace) ROM_CALL(INSERT_MEM) ;Allocates a region of memory: HL = size DE = address ;Cette routine modifie l'adresse du programme à copier, on modifie donc l'adresse AdresseProgDetruit POP HL PUSH HL EX DE,HL LD HL,(AdresseProgDetruit) Add HL,DE LD (AdresseProgDetruit),HL ;On copie maintenant les données vers la nouvelle adresse POP HL PUSH HL LD B,H LD C,L LD HL,(AdresseProgDetruit) LD DE,(AdresseProgDeplace) LDIR POP HL ;On detruit la zone copiée du programme EX DE,HL PUSH DE LD HL,(AdresseProgDetruit) ROM_CALL(DEL_MEM) ;Deletes a region of allocated memory: HL = address DE = size POP DE ;On met à jour AdresseProgDeplace ;ici DE = taille des données copiées LD HL,(AdresseProgDeplace) ADD HL,DE LD (AdresseProgDeplace),HL ;On regarde s'il reste des données à copier LD HL,(TailleDonnesADeplacer) LD A,H CP $FF JR NZ,CreationDeZoneLibre LD A,L CP $FF JR NZ,CreationDeZoneLibre ;On modifie l'adresse du programme dans la VAT LD HL,(AdresseProgVAT-CRASHMODIFIE+$8D26) LD (HL),DEBUT_PROG_1 INC HL LD (HL),DEBUT_PROG_2 ROM_CALL(CREATE_TMP) RET AdresseInitProg2 .DW 0 TailleDonnesADeplacer2 .DW 0 TailleProg2 .DW 0 AdresseProgDetruit2 .DW 0 AdresseProgDeplace2 .DW 0 AdresseInitProg = AdresseInitProg2 -CRASHMODIFIE+$8D26 TailleDonnesADeplacer = TailleDonnesADeplacer2-CRASHMODIFIE+$8D26 TailleProg = TailleProg2 -CRASHMODIFIE+$8D26 AdresseProgDetruit = AdresseProgDetruit2 -CRASHMODIFIE+$8D26 AdresseProgDeplace = AdresseProgDeplace2 -CRASHMODIFIE+$8D26 RePlaceLeProg: ;initialisation SET 1,(IY+$0D) RES 3,(IY+$05) ROM_CALL(DEL_TMP) LD HL,(TailleProg) LD (TailleDonnesADeplacer),HL LD HL,DEBUT_PROG LD (AdresseProgDetruit),HL LD HL,(AdresseInitProg) LD BC,(TailleProg) ADD HL,BC LD (AdresseProgDeplace),HL CreationDeZoneLibre_2: ;On créer une zone de mémoire à l'adresse AdresseProgDeplace de HL octets ;HL est { = 768 si TailleDonnesADeplacer>768 ; = TailleDonnesADeplacer sinon LD HL,(TailleDonnesADeplacer) LD BC,768 SBC HL,BC JP P,TaillePositive_2-CRASHMODIFIE+$8D26 LD HL,(TailleDonnesADeplacer) JR TailleCalculee_2 TaillePositive_2: LD HL,768 TailleCalculee_2: PUSH HL LD DE,(TailleDonnesADeplacer) EX DE,HL SBC HL,DE LD (TailleDonnesADeplacer),HL POP HL ;On a calculé la taille de la mémoire à allouer PUSH HL LD DE,(AdresseProgDeplace) ROM_CALL(INSERT_MEM) ;Allocates a region of memory: HL = size DE = address ;On copie maintenant les données vers la nouvelle adresse POP HL PUSH HL LD B,H LD C,L LD HL,(AdresseProgDetruit) LD DE,(AdresseProgDeplace) LDIR POP HL ;On detruit la zone copiée du programme EX DE,HL PUSH DE LD HL,(AdresseProgDetruit) ROM_CALL(DEL_MEM) ;Deletes a region of allocated memory: HL = address DE = size POP DE ;On regarde s'il reste des données à copier LD HL,(TailleDonnesADeplacer) LD A,H CP $FF JR NZ,CreationDeZoneLibre_2 LD A,L CP $FF JR NZ,CreationDeZoneLibre_2 ;On modifie l'adresse du programme dans la VAT LD HL,(AdresseProgVAT-CRASHMODIFIE+$8D26) LD A,(AdresseInitProg+1) LD (HL),A INC HL LD A,(AdresseInitProg) LD (HL),A ROM_CALL(CREATE_TMP) RET AdapteNOUVROMCALL: ;On récupère l'adresse où se lance le programme LD HL,(AdresseProgALancer-CRASHMODIFIE+$8D26) DEC HL LD E,(HL) DEC HL LD D,(HL) EX DE,HL ;On charge dans BC la taille du programme LD C,(HL) INC HL LD B,(HL) ChercheCALL: LD A,(HL) INC HL DEC BC CP $DC JR Z,AppelTrouve CP $FC JR Z,AppelTrouve CP $D4 JR Z,AppelTrouve CP $C4 JR Z,AppelTrouve CP $F4 JR Z,AppelTrouve CP $EC JR Z,AppelTrouve CP $E4 JR Z,AppelTrouve CP $CC JR Z,AppelTrouve CP $CD JR Z,AppelTrouve ;si BC=0 on a fini XOR A CP B JR NZ,ChercheCALL CP C JR NZ,ChercheCALL RET AppelTrouve: ;On essaie de retrouvé une adresse de la rom ;D'abord on regarde si c'est un appel vers la rom INC HL LD A,(HL) DEC HL CP $40 JR NC,ChercheCALL ;maintenant on regarde si on connais cet appel LD DE,AppelsRom160-CRASHMODIFIE+$8D26 LD (SavBC-CRASHMODIFIE+$8D26),BC ChercheAdresse: LD A,(DE) OR A JR Z,AsTonFini OnAPasFini2: INC DE INC DE CP (HL) JR NZ,ChercheAdresse ;ici on a déjà trouvé un bout, on vérifie si l'autre correspond INC HL LD A,(HL) LD B,A DEC HL DEC DE LD A,(DE) INC DE CP B JR NZ,ChercheAdresse ;On a trouvé l'adresse! ;On la modifie DEC DE DEC DE EX DE,HL LD BC,AppelsRom160-CRASHMODIFIE+$8D26 SBC HL,BC LD BC,AppelsRom19006-CRASHMODIFIE+$8D26 ADD HL,BC ;HL->Adresse rom 19.006 ;DE->Adresse rom 16.0 LD A,(HL) LD (DE),A INC HL INC DE LD A,(HL) LD (DE),A EX DE,HL INC HL LD BC,0 SavBC = $-2 JR ChercheCALL AsTonFini: LD BC,(SavBC-CRASHMODIFIE+$8D26) INC DE LD A,(DE) DEC DE OR A JR Z,ChercheCALL JR OnAPasFini2 AppelsRom160: .DW $01B8 .DW $01C7 .DW $01D4 .DW $07F3 .DW 0 AppelsRom19006: .DW $01D7 .DW $01E6 .DW $01F3 .DW $083A PetitCode2: LD HL,(AdresseCRASHEMUDansRam-CRASHMODIFIE+$8D26) LD DE,CRASHMODIFIE-Commentaire+41 ADD HL,DE ;HL->CRASHMODIFIE LD DE,$8D26 LD BC,TailleCRASHMODIFIE EchangeDonnees2: PUSH BC LD A,(DE) LD C,(HL) EX DE,HL LD (DE),A LD (HL),C EX DE,HL INC DE INC HL POP BC DEC BC XOR A CP B JR NZ,EchangeDonnees2 CP C JR NZ,EchangeDonnees2 RET PetitCode2Fin: PetitCode2Taille = PetitCode2Fin-PetitCode2 AdresseCRASHEMUDansRam .DW 0 BLOC3: .DS DEBUT_PROG-$8D97-BLOC3+BLOC3_0 .DB 0 ;adresse DEBUT_PROG CRASHMODIFIEFin: TailleCRASHMODIFIE = CRASHMODIFIEFin-CRASHMODIFIE .echo "Il reste " .echo DEBUT_PROG-$8D97-BLOC3+BLOC3_0 .echo " octets libres dans CrASHmodifie.\n"