@ *********************************************************************** @ * * @ * L E M M I N G S ! for HP48 * @ * * @ * Written in january 1993 by C. de DINECHIN * @ * using HPDS 3.0 * @ * * @ *********************************************************************** LIBRARY 1213 "LEMMINGS! (C) C.de DINECHIN, V1.06 du 13/03/1993" COMMANDS LEM LevelLEM AboutLEM LOCAL DecompactLEM LEMCode LEMSprites LEMMenus LEMPatterns LEMScreen Display VScroll LEMLoop LEMLaunch InvalidLEMDAT LEMLevels MESSAGES [ "Unexpected screen addr" @ Variables storage is not possible... "Level does not exist" "Invalid LEMDAT" ] CONFIG PROG <1213d> EXTERNAL 07709h @ HomeAttach(s) END CONTENT @ *********************************************************************** @ * * @ * Graphiques divers de Lemmings * @ * * @ *********************************************************************** LEMSprites INCLUDE "Sprites.48S" LEMPatterns INCLUDE "Motifs.48S" LEMScreen INCLUDE "Screen.48S" LEMMenus { INCLUDE "Unchecked.48S" XHERE LEM_MENU0 GROB 131 8 EF0008F3000E30008F100000000000000F 38FFFC7FFF3FFFFFC0FFF3EFFFFFFFFF3F 10FFFD9FFF736FFFD0FFF7FFFFFFFFFF7F D6FFFDBFFF79DFFFD0FFF7FFFFFFFFFF7F BAFFF50EFF719EFFDEFFF7FFFFFFFFFF7F 7DFFFD9FFF71CFFFDEFFF7FFFFFFFFFF7F FEFFFD9FFF736FFFDEFFF7FFFFFFFFFF71 EFFFF8FFFF3EFFFF8FFFF3EFFFFFFFFF31 @ ENDGROB XHERE LEM_MENU1 GROB 131 8 E70008F1000E70008F1000000000000001 3CFFFC9FFF3FFFFFCFFFF3EFFFFFFFFF31 1CFFFD3FFF7FEFFF5CFFF7FFFFFFFFFF71 7FFFFD3EFF7FCFFFDDFFF7FFFFFFFFFF71 7FFFFD5EFF71CFFFD1FFF7FFFFFFFFFF71 7FFFFDEFFF7FCFFFD7FFF7FFFFFFFFFF71 7FFFF5FFFF7FCFFFD7CFF7FFFFFFFFFF71 EFFFFCFFFF3FFFFFCFFFF3EFFFFFFFFF31 @ ENDGROB } @ *********************************************************************** @ * * @ * Code assembleur pour LEMMINGS * @ * * @ *********************************************************************** LEMCode PROG ASM INCLUDE "HARD.48S" INCLUDE "ROM.48S" INCLUDE "RRAM.48S" ************************************************************************* * * * Variables globales * * * ************************************************************************* RSSET $70C00 VARS_Start RS 0 SCRN_LogBase RS 5 ; Adresse logique de l'残ran SCRN_PhyBase RS 5 ; Adresse physique de l'残ran SCRN_PosX RS 3 ; Position de l'残ran SCRN_PosY RS 3 BACK_Base RS 5 ; Adresse de l'残ran de fond BACK_Height RS 3 ; Hauteur de l'残ran de fond BACK_Width RS 3 ; Largeur de l'残ran de fond BACK_LineStart RS 5 ; Adresses du d暫ut de chaque ligne SPRT_Sprites RS 5 ; Adresse des sprites CRSR_PosX RS 3 ; Position du curseur CRSR_PosY RS 3 KEY_Last RS 5 ; Derni俊e touche press仔 KEY_AntiRepeat RS 5 ; Utilise pour l'anti repetition LEM_Data RS 5 ; Adresse de l'objet lemmings (chaine) LEM_PosX RS 3 ; Position initiale des lemmings LEM_PosY RS 3 LEM_ToCreate RS 2 ; Nombre de lemmings a creer LEM_Delay RS 3 ; Temps entre deux lemmings LEM_Count RS 3 ; Decompte avant la creation du prochain LEM_Number RS 2 ; Nombre total de lemmings LEM_ExitX RS 3 ; Position de la sortie LEM_ExitY RS 3 ; LEM_ToExit RS 2 ; Nombre de lemmings a sortir LEM_IToExit RS 2 ; Nombre de lemmings initialement sortir LEM_Exited RS 2 ; Nombre de lemmings effectivement sortis TIME_Allowed RS 5 ; Temps autoris TIME_Last RS 5 ; D暫ut de boucle TIME_Counter RS 5 ; Compteur de d四ai LEMC_Parachute RS 2 LEMC_Stopping RS 2 ; Nombre de lemmings de chaque type restant LEMC_Dig RS 2 LEMC_Climb RS 2 LEMC_Cons RS 2 LEMC_Exploder RS 2 LEMC_Dummy RS 2 MENU_Index RS 1 ; Indique le num屍o de menu OFF_Flag RS 1 ; <> 0 si appel de la pause OFF QUIT_Flag RS 1 ; <> 0 si quitt par F PAUSE_Flag RS 2 ; <> 0 si en mode pause VARS_End RS 0 ; Fin des variables * --------------------------------------------------------------------- * * Type de lemmings autoris市 * * --------------------------------------------------------------------- * RSRESET ; Numero des sprites de lemmings LEMK_None RS 1 ; Pas de lemming cet emplacement LEMK_Parachute RS 1 ; Lemming sautant en parachute LEMK_Right RS 1 ; Lemming marchant vers la droite LEMK_Left RS 1 ; Lemming marchant vers la gauche LEMK_FallingR RS 1 ; Lemming en train de tomber LEMK_FallingL RS 1 ; LEMK_Stopping RS 1 ; Lemming stoppant les autres LEMK_Explode RS 1 ; Lemming creusant verticalement LEMK_DigRight RS 1 ; Lemming creusant horizontalement droite LEMK_DigLeft RS 1 ; Lemming creusant horizontalement gauche LEMK_ClimbRight RS 1 ; Lemming escaladant droite LEMK_ClimbLeft RS 1 ; Lemming escaladant gauche LEMK_ConsRight RS 1 ; Lemming construisant droite LEMK_ConsLeft RS 1 ; Lemming construisant gauche * --------------------------------------------------------------------- * * Structure d'un lemming * * --------------------------------------------------------------------- * LEM_MaxNumber EQU 128 ; Nombre maxi de lemmings RSRESET LEMV_Kind RS 1 ; Sprite de lemming LEMV_PosX RS 3 ; Position LEMV_PosY RS 3 LEMV_BotMask RS 3 ; Masque du bas du lemming LEMV_Data RS 2 ; Hauteur de chute. LEMV_Athletic RS 1 ; Bit 0: Parachute 1: Escalade 2: DigX 3: DigY LEMV_Explode RS 2 ; Delai avant explosion LEMV_Dir RS 1 ; 0=Droite 1=Gauche ************************************************************************* * * * Routine principale * * * ************************************************************************* MAIN: GOSUBL LEM_Init GOSUBL MENU_Display .loop D0=HARD_Ticks ; Memorise le temps de d暫ut A=DAT0 D0=TIME_Last DAT0=A D0=D0+TIME_Counter-TIME_Last ; Incr士ente le compteur de temps A=DAT0 A=A+1 DAT0=A D0=PAUSE_Flag A=DAT0(P) ?A=0(P) GOYES .normal GOSUBL KEY_Get GOSUBL MENU_Commands GOSUBL MENU_Scores GOSUBL CRSR_Move GOTO .paused .normal GOSUBL KEY_Get ; Lit la touche press仔 GOSUBL LEM_Insert ; Insere des lemmings GOSUBL MENU_Commands ; Commandes des lemmings GOSUBL MENU_Scores GOSUBL CRSR_Move ; D姿lace le curseur GOSUBL LEM_Move ; D姿lace les lemmings .paused GOSUBL SCRN_Copy ; Copie de l'残ran de fond GOSUBL CRSR_Display ; Affichage du curseur GOSUBL LEM_Display ; Affichage des lemmings GOSUBL SCRN_SwapScreen ; Permutation d'残ran D0=OFF_Flag A=DAT0(P) ?A=0(P) GOYES .wait GOLONG CallOFF ; Eteint la machine .wait D0=TIME_Last C=DAT0 D0=HARD_Ticks A=DAT0 A=A-C A=-A LC 409 ; Un dixi塾e de seconde ?A0(X) GOYES .loop RTNCC ; Retourne, C=0 indique OK MENU_Commands: * --------------------------------------------------------------------- * * Commandes menu au clavier * * --------------------------------------------------------------------- * D0=KEY_Last A=DAT0 D0=D0+5 ; KEY_AntiRepeat C=DAT0 ?A=C ; Repetition de touche ? RTNYES ; Ne fait rien DAT0=A ; Copie la derniere touche LC $00420 ; Touche jaune ?A<>C GOYES .nopause D0=PAUSE_Flag A=DAT0(P) A=-A-1(P) DAT0(P)=A RTN .nopause LC $00220 ; Touche bleue ?A<>C GOYES .nooff ; Eteint la machine D0= OFF_Flag ; Indique qu'il faut 師eindre LC(1) 1 DAT0=C(P) RTN .nooff LC $01001 ; Touche Backspace ?A<>C GOYES .noexit D0=QUIT_Flag LC(1) 1 DAT0(P)=C GOTO .quitgame .noexit LC $10001 ; Touche F ?A<>C GOYES .noquit .quitgame D0= LEM_ToCreate ; Efface les lemmings a cr仔r A=0 DAT0(B)=A D0= LEM_Number ; Nombre de lemmings C=DAT0(B) B=C(B) D0=LEM_Data ; Balayage de la table des lems C=DAT0 D0=C D0=D0+LEMV_Explode D1=HARD_Ticks ; Base al斬toire C=DAT1 D=C .exploloop B=B-1(B) RTNC C=D C=C+C ; *2 C=C+C ; *4 C=C+D ; *5 C=C+C ; *10 C=C+C ; *20 C=C+C ; *40 C=C+D ; *41 D=C A=C LC(2) 63 A=A&C(B) LC(2) 80 ; Ins俊e une explosion C=C-A(B) DAT0(B)=C D0=D0+16 ; Passe au lemmings suivant GOTO .exploloop .noquit LC $10002 ; Touche E ?A<>C GOYES .nofast D0=LEM_Count ; Ins俊e imm仕iatement un lemming C=0(X) DAT0=C(X) RTN .nofast D0=PAUSE_Flag ; Teste si en mode Pause C=DAT0(P) ?C<>0(P) RTNYES D0=MENU_Index LC $08001 ; Touche NXT ?A<>C GOYES .no_next A=DAT0(P) A=-A-1(P) DAT0(P)=A GOLONG MENU_Display * Recherche une commande et l'ex残ute .no_next C=DAT0(P) ?C=0(P) GOYES .menu0 GOTO .menu1 .menu0 GOSUB .domenu DC $00210 ; Touche A DC LEMC_Parachute DR MENU_Parachute DC $10010 ; Touche B DC LEMC_Stopping DR MENU_Stopping DC $10008 ; Touche C DC LEMC_Exploder DR MENU_Exploder DC $10004 ; Touche D DC LEMC_Climb DR MENU_Climb .menu1 GOSUB .domenu DC $00210 ; Touche A DC LEMC_Dig DR MENU_DigH DC $10010 ; Touche B DC LEMC_Dig DR MENU_DigHV DC $10008 ; Touche C DC LEMC_Dig DR MENU_DigV DC $10004 ; Touche D DC LEMC_Cons DR MENU_Cons * Recherche dans la table s四ectionn仔 la touche voulue. * Pour cette touche, recherche si la variable est ok. * Si oui, appelle la routine de gestion de la commande .domenu C=RSTK D0=C C=DAT0 ; Touche A ?A=C GOYES .ok D0=D0+15 C=DAT0 ?A=C ; Touche B GOYES .ok D0=D0+15 C=DAT0 ?A=C ; Touche C GOYES .ok D0=D0+15 C=DAT0 ?A=C ; Touche D GOYES .ok RTN .ok D0=D0+5 A=DAT0 ; Adresse du compteur D1=A R3=A(A) ; R3 = Adresse du compteur A=DAT1(B) ; Lecture du compteur ?A=0(B) RTNYES ; Si le compteur est 姿uis, retour D0=D0+5 ; Lit l'adresse de la routine A=DAT0 CD0EX C=C+A R2=C(A) ; R2 = adresse de la routine GOSUB 0+LEM_Find ; Recherche des lemmings sous le curseur .loop RTNC ; si il n'y en a plus C=R2(A) ; Adresse de la routine GOSUB .jumpc GONC .found ; Si la routine a trouv GOSUB 0+LEM_Find_loop GOTO .loop * On a trouv un lemmings ok. .found A=R3 ; Adresse du compteur D1=A A=DAT1(B) ; D残r士ente le compteur A=A-1(B) DAT1(B)=A GOSUB MENU_Display RTN * Appel d'une routine point仔 par C .jumpc PC=C ; Appelle la routine * ********************************************************************* * * Routine g屍ant les commandes * * ********************************************************************* * * Entr仔: * D0 pointe sur le lemmings s四ectionn * Sortie: * D0, R1, R2, R3 non modifi市 * Carry NC si le lemmings 師ait OK. MENU_Parachute: * --------------------------------------------------------------------- * * Lemmings parachutiste * * --------------------------------------------------------------------- * A=DAT0(P) LC(1) LEMK_Stopping ; Si un stoppeur, recommence ?A=C(P) GOYES .no D0=D0+LEMV_Athletic ; Indique qu'il devient parachutiste C=DAT0(P) ?CBIT(0)=1 GOYES .already ; Si d史 parachutiste CBIT(0)=1 DAT0(P)=C RTNCC .already D0=D0-LEMV_Athletic .no RTNSC MENU_Stopping: * --------------------------------------------------------------------- * * Lemmings stoppeur * * --------------------------------------------------------------------- * A=DAT0(P) ; Teste les lemmings autoris市 P=15 LC(1) 6 ; Nombre de choix B=C(S) P=0 LC(7) $23789CD ; Lemmings autoris市 .loop ?A=C(P) GOYES .yes CSR(W) B=B-1(S) GONC .loop RTNSC .yes LC(1) LEMK_Stopping DAT0(P)=C RTNCC MENU_DigH: LC(1) 4 GOTO MENU_Dig MENU_DigV: LC(1) 8 GOTO MENU_Dig MENU_DigHV: LC(1) $C MENU_Dig: * --------------------------------------------------------------------- * * Lemmings creuseur * * --------------------------------------------------------------------- * D=C A=DAT0(P) ; Teste les lemmings autoris市 P=15 LC(1) 4 ; Nombre de choix B=C(S) P=0 LC(7) $14567 ; Lemmings interdits .loop ?A=C(P) GOYES .no CSR(W) B=B-1(S) GONC .loop D0=D0+LEMV_Athletic ; Indique que creuseur LC(1) 3 A=DAT0(P) C=C&A(P) C=C|D(P) DAT0(P)=C D0=D0+LEMV_Dir-LEMV_Athletic A=DAT0(P) D0=D0-LEMV_Dir LC(1) LEMK_DigRight A=A+C(P) DAT0(P)=A ; Change le sprite RTNCC .no RTNSC MENU_Climb: * --------------------------------------------------------------------- * * Lemmings escaladeur * * --------------------------------------------------------------------- * A=DAT0(P) LC(1) LEMK_Stopping ; Si un stoppeur, recommence ?A=C(P) GOYES .no LC(1) LEMK_Explode ; Si un exploder, recommence ?A=C(P) GOYES .no D0=D0+LEMV_Athletic ; Indique qu'il devient parachutiste C=DAT0(P) ?CBIT(1)=1 GOYES .already CBIT(1)=1 DAT0(P)=C D0=D0-LEMV_Athletic RTNCC .already D0=D0-LEMV_Athletic .no RTNSC MENU_Cons: * --------------------------------------------------------------------- * * Lemmings constructeur * * --------------------------------------------------------------------- * A=DAT0(P) LC(1) LEMK_Right ?A=C(P) GOYES .yes LC(1) LEMK_Left ?A=C(P) GOYES .yes RTNSC .yes D0=D0+LEMV_Dir A=DAT0(P) D0=D0-LEMV_Dir LC(1) LEMK_ConsRight A=A+C(P) DAT0(P)=A D0=D0+LEMV_Data LC(2) 44 DAT0(B)=C D0=D0-LEMV_Data RTNCC MENU_Exploder: * --------------------------------------------------------------------- * * Lemmings explosant * * --------------------------------------------------------------------- * D0=D0+LEMV_Explode LC(2) 96 DAT0(B)=C RTNCC ************************************************************************* * * * Gestion des lemmings * * * ************************************************************************* LEM_Insert: * --------------------------------------------------------------------- * * Ins俊e un lemming si necessaire * --------------------------------------------------------------------- * D0=LEM_ToCreate ; Teste si plus rien a creer A=DAT0(B) ?A=0(B) RTNYES D0=D0+5 ; LEM_Count, Decompte avant creation A=DAT0(X) A=A-1(X) DAT0(X)=A RTNNC ; Retour si pas necessaire de creer D0=D0-3 ; LEM_Delay A=DAT0(X) D0=D0+3 ; LEM_Count DAT0(X)=A D0=D0-5 ; LEM_ToCreate A=DAT0(B) ; LEM_ToCreate A=A-1(B) DAT0(B)=A D0=LEM_Number ; Nombre de lemmings A=0 A=DAT0(B) A=A+1(B) DAT0(B)=A A=A-1(B) D0=LEM_Data ; Se place a la fin de la table C=DAT0 D0=C ASL C=C+A D0=C ; D0= adresse du lemming a creer LC(1) LEMK_Right ; Type "Droite" DAT0(P)=C D0=D0+1 D1=LEM_PosX ; Position initiale des lemmings A=DAT1(X) DAT0(X)=A D0=D0+3 D1=D1+3 A=DAT1(X) DAT0(X)=A D0=D0+3 P=8 C=0(WP) ; Mise a 0 de tous les autres champs DAT0=C(WP) P=0 RTN LEM_Move: * --------------------------------------------------------------------- * * D姿lacement de tous les lemmings * * --------------------------------------------------------------------- * GOSUB 0+.lem_table * Sprite permettant de connaitre ce que fait le lemming DR LEMR_None DR LEMR_Falling ; Parachutiste DR LEMR_Right ; Marcheur a droite DR LEMR_Left ; Marcheur a gauche DR LEMR_Falling ; Tombe a droite DR LEMR_Falling ; Tombe a gauche DR LEMR_Stopping ; Stoppeur DR LEMR_Exploder ; En train d'exploser DR LEMR_Dig ; Creuseur droite DR LEMR_Dig ; Creuseur gauche DR LEMR_ClimbRight ; Escaladeur droite DR LEMR_ClimbLeft ; Escaladeur gauche DR LEMR_ConsRight ; Constructeur droite DR LEMR_ConsLeft ; Constructeur gauche .lem_table C=RSTK ; R残up俊e l'adresse de la table R2=C D0=LEM_Data ; Balayage de la table des lems C=DAT0 D0=C D1=LEM_Number ; Lit le nombre de lemmings C=DAT1(B) R1=C D0=D0-16 .loop D0=D0+16 C=R1 ; D残ompte C=C-1(B) RTNC R1=C * Decompte le temps avant explosion D0=D0+LEMV_Explode ; Decompte du temps A=DAT0(B) A=A-1(B) ; Si pas de decompte GOC .noex DAT0(B)=A LC(2) 20 ; Si change le sprite ?A>C(B) GOYES .noex LC(1) LEMK_Explode D0=D0-LEMV_Explode DAT0(P)=C GOTO .ex .noex D0=D0-LEMV_Explode ; Stocke le sprite definitif * Teste si le lemming arrive au paradis et si oui le tue .ex C=0 ; Lit le type de lemming C=DAT0(P) RSTK=C ; Sauvegarde le type D1=LEM_ExitX D0=D0+LEMV_PosX A=DAT0(X) ; Teste X D0=D0-LEMV_PosX C=DAT1(X) ?A<>C(X) GOYES .no_paradise D0=D0+LEMV_PosY ; Teste Y D1=D1+3 ; LEM_ExitY A=DAT0(X) C=DAT1(X) D0=D0-LEMV_PosY ?A<>C(X) GOYES .no_paradise D1=LEM_Exited ; Incr士ente le nombre de lemmings sortis A=DAT1(B) A=A+1(B) DAT1(B)=A D1=LEM_ToExit ; Decremente le nombre de lemmings X A=DAT1(B) A=A-1(B) GOC .win DAT1(B)=A .win D0=D0+LEMV_PosY GOTO .killy * Teste si le lemming sort de l'ecran et si oui le tue .no_paradise D1=BACK_Width D0=D0+LEMV_PosX LC(3) 8 B=C(X) A=0 A=DAT0(X) ; Teste X C=DAT1(X) C=C-B(X) ?A>C(X) GOYES .killx D0=D0+3 ; Teste Y D1=D1-3 ; BACK_Height A=DAT0(X) C=DAT1(X) C=C-B(X) ?A<=C(X) GOYES .ok GOTO .killy .killx D0=D0+3 .killy C=RSTK ; Depile ce qu'il faut D0=D0-4 ; Debut de lemming CD0EX RSTK=C ; Sauvegarde D0 D1=C D0=C D1=D1+16 ; Pointe sur le lemming suivant C=R1 ; Lemmings restant .kill_loop C=C-1(B) GOC .kill_exit A=DAT1(W) DAT0=A(W) D0=D0+16 D1=D1+16 GOTO .kill_loop .kill_exit C=RSTK ; Recup俊e D0 D0=C D1=LEM_Number ; Indique "Un lemming de moins" A=DAT1(B) A=A-1(B) DAT1(B)=A C=R1 ; Compteur de lemmings decremente C=C-1(B) RTNC ; Si il n'en reste plus R1=C GOTO .loop * Calcule l'adresse dans le tableau de la position du Lemming (dans D1) .ok LC(3) 8 A=A+C(X) ; Pointe sur les pieds du lemming D1=D1+3 C=0 C=DAT1(X) ; Largeur de l'残ran C=C/2(X) ; Taille en quartets C=C/2(X) RSTK=C ; Stocke la largeur de l'残ran C=A ; Multiplie la pos Y par 5 A=A+A A=A+A A=A+C D1=BACK_LineStart C=DAT1 ; Trouve l'adresse de la donnee C=C+A D1=C A=DAT1 ; Lit l'adresse dans le tableau D0=D0-3 ; Position X : Offset horizontal C=0 C=DAT0(X) C=C/2(X) ; Taille en quartets C=C/2(X) D0=D0-1 ; Restaure D0 A=A+C ; Position du lemming R0=A ; Sauvegarde dans R0 C=RSTK ; R残up俊e la largeur de l'残ran D=C * Appelle la routine d仕i仔 au Lemming C=RSTK ; R残up俊e le type B=C ; Multiplie par 5 (pour table) C=C+C C=C+C B=B+C C=R2 ; Adresse de la table C=C+B D1=C A=DAT1 ; lecture de la valeur A=A+C ; + adresse = routine D0=D0+7 ; Pointe sur le masque C=DAT0(X) ; Lit le masque de pied B=C(X) D0=D0-7 D1=TIME_Counter ; Compteur de temps C=DAT1 RSTK=C C=R0 ; Adresse des pieds du lemming D1=C C=RSTK ; R残up俊e le compteur de temps ACEX GOSUB 0+.jump GOTO .loop .jump PC=C ; Saut la bonne routine ************************************************************************* * * * Routines particuli俊es pour chaque type * * * ************************************************************************* * Entr仔: * D0= donn仔s du lemming * D1= Adresse 残ran des pieds du lemming * A = TIME_Counter * B = Masque de pied * D = Largeur en q d'une ligne d'残ran LEMR_None RTN LEM_MaxHeight equ 3 LEMR_Right: * --------------------------------------------------------------------- * * Lemming marchant droite * * --------------------------------------------------------------------- * LC(1) 3 ; Vitesse de marche divis仔 par 4 A=A&C(P) ?A<>0(P) RTNYES A=DAT1(X) ; Si rien sous les pieds A=A&B(X) ?A<>0(X) GOYES .nofall GOTO .falling .nofall CD1EX ; Ligne pr残仕ente C=C-D CD1EX B=B+B(X) ; L使俊ement droite A=DAT1(X) ; Si rien A=A&B(X) ?A<>0(X) GOYES .nort GOTO .okrt ; d姿lacement droite .nort LC(3) LEM_MaxHeight-1 ; Hauteur maxi d'une marche .mloop CD1EX ; Ligne pr残仕ente C=C-D CD1EX A=DAT1(X) ; Si rien A=A&B(X) ?A=0(X) GOYES .okup ; monte une marche C=C-1(P) GONC .mloop D0=D0+LEMV_Athletic ; Teste si grimpeur C=DAT0(P) D0=D0-LEMV_Athletic ?CBIT(1)=0 GOYES .chdir LC(1) LEMK_ClimbRight DAT0(P)=C RTN .chdir LC(1) LEMK_Left ; change de direction DAT0(P)=C D0=D0+LEMV_Dir LC(1) 1 DAT0(P)=C D0=D0-LEMV_Dir RTN .okup D0=D0+LEMV_PosY ; Monte la marche A=DAT0(X) A=A-LEM_MaxHeight(X) A=A+C(X) DAT0(X)=A D0=D0-LEMV_PosY .okrt D0=D0+LEMV_PosX ; D姿lacement vers la droite A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosX RTN .falling LC(1) LEMK_FallingR ; Indique que le lemming tombe DAT0(P)=C C=0(B) D0=D0+LEMV_Data ; Restaure le compteur de chute DAT0(B)=C D0=D0-LEMV_Data RTN LEMR_Left: * --------------------------------------------------------------------- * * Lemming marchant gauche * * --------------------------------------------------------------------- * LC(1) 3 ; Divise la vitesse de marche par 4 A=A&C(P) ?A<>0(P) RTNYES A=DAT1(X) ; Si rien sous les pieds A=A&B(X) ?A<>0(X) GOYES .nofall GOTO .falling .nofall CD1EX ; Ligne pr残仕ente C=C-D CD1EX B=B/2(X) ; L使俊ement gauche A=DAT1(X) ; Si rien A=A&B(X) ?A<>0(X) GOYES .nolf ; d姿lacement droite GOTO .oklf .nolf LC(3) LEM_MaxHeight-1 ; Hauteur maxi d'une marche .mloop CD1EX ; Ligne pr残仕ente C=C-D CD1EX A=DAT1(X) ; Si rien A=A&B(X) ?A=0(X) GOYES .okup ; monte une marche C=C-1(P) GONC .mloop D0=D0+LEMV_Athletic ; Teste si grimpeur C=DAT0(P) D0=D0-LEMV_Athletic ?CBIT(1)=0 GOYES .chdir LC(1) LEMK_ClimbLeft DAT0(P)=C RTN .chdir LC(1) LEMK_Right ; change de direction DAT0(P)=C D0=D0+LEMV_Dir LC(1) 0 DAT0(P)=C D0=D0-LEMV_Dir RTN .okup D0=D0+LEMV_PosY ; Monte la marche A=DAT0(X) A=A-LEM_MaxHeight(X) A=A+C(X) DAT0(X)=A D0=D0-LEMV_PosY .oklf D0=D0+LEMV_PosX ; D姿lacement vers la gauche A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosX RTN .falling LC(1) LEMK_FallingL ; Indique que le lemming tombe DAT0(P)=C C=0(B) D0=D0+LEMV_Data ; Restaure le compteur de chute DAT0(B)=C D0=D0-LEMV_Data RTN LEMR_Falling: * --------------------------------------------------------------------- * * Lemming tombant droite et gauche * * --------------------------------------------------------------------- * D0=D0+LEMV_Data ; Compteur de chute A=DAT0(B) A=A+1(B) DAT0(B)=A D0=D0-LEMV_Data LC(2) 16 ; Hauteur mini avant ouverture para ?A0(P) RTNYES D0=D0+LEMV_Data ; Emp芯he le parachutiste de s'残raser LC(2) 32 DAT0(B)=C D0=D0-LEMV_Data .no_para A=DAT1(X) ; Si encore chute A=A&B(X) ?A=0(X) GOYES .chute D0=D0+LEMV_Data ; Verifie si s'残rase A=DAT0(B) D0=D0-LEMV_Data LC(2) 50 ?A>C(B) GOYES .ecrase .walk D0=D0+LEMV_Dir ; Remet le lemming en marche. A=DAT0(P) D0=D0-LEMV_Dir LC(1) LEMK_Right C=C+A(P) DAT0(P)=C RTN .ecrase D0=D0+1 ; Sort le lemming de l'残ran -> mort LC(3) -1 DAT0=C(X) D0=D0-1 RTN .chute D0=D0+4 ; Chute du lemming A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-4 RTN LEMR_Stopping: * --------------------------------------------------------------------- * * Lemming qui arrete les autres * * --------------------------------------------------------------------- * LC(1) 1 ; 2 lignes maxi de descente .fall A=DAT1(X) ; Teste si rien sous moi A=A&B(X) ?A<>0(X) GOYES .ok D0=D0+LEMV_PosY ; Essaie de descendre d'une ligne A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosY CD1EX C=C+D CD1EX C=C-1(P) GONC .fall GOTO LEMR_Falling_walk ; Tombe de trop haut .ok D1=LEM_Number ; Nombre de lemmings C=DAT1(B) D=C(B) D=D-1(B) D1=LEM_Data ; Donn仔s des lemmings C=DAT1 D1=C .loop D0=D0+LEMV_PosY D1=D1+LEMV_PosY A=DAT0(X) ; Coordonn仔 Y stoppeur C=DAT1(X) ; Coordonn仔 Y lemming examin D0=D0-LEMV_PosY D1=D1-LEMV_PosY A=A-C(X) LC(3) 4 A=A+C(X) LC(3) ~7 A=A&C(X) ?A=0(X) GOYES .matchy GOTO .nomatch .matchy D0=D0+LEMV_PosX D1=D1+LEMV_PosX A=DAT0(X) ; Coordonn仔 X stoppeur C=DAT1(X) ; Coordonn仔 X lemming examin D0=D0-LEMV_PosX D1=D1-LEMV_PosX A=A-C(X) LC(3) 2 ; Xstop-Xlem > 0 si lem gauche ?A0(P) GOYES .nomatch ; Si d史 vers la gauche LC(1) 1 D1=D1+LEMV_Dir DAT1(P)=C D1=D1-LEMV_Dir DX 3F0132546798BADCEF A=C(W) C=DAT1(P) P=C(0) ; R残up俊e le retournement DAT1(P)=A P=0 .nomatch D1=D1+16 ; Passe au sprite suivant D=D-1(B) RTNC GOTO .loop LEMR_Dig: * --------------------------------------------------------------------- * * Lemming creuseur * * --------------------------------------------------------------------- * * L'effacement se fait toujours a la position actuelle du Lemming. * Le lemming casse la pioche s'il tombe sur une colonne ou un ligne pleine. LC(1) 7 ; Vitesse de creusement / 8 A=A&C(P) ?A<>0(P) RTNYES * Teste la ligne du bas C=DAT1(X) ; Verifie si en bas, 溝 coince C=C&B(X) ?C<>0(X) ; Si ligne vide GOYES .noempty ST(0)=1 ; Indique "Pioche cass仔" .noempty ?C<>B(X) ; Si ligne continue GOYES .nofull ST(0)=1 ; Indique "Pioche cass仔" * Teste les lignes des bords .nofull LC(3) $FF ; Masque d'effacement B=C(X) D0=D0+LEMV_PosX A=DAT0(P) D0=D0-LEMV_PosX LC(1) 3 A=A&C(P) .shift A=A-1(P) ; Decale le masque d'effacement GOC .eshift B=B+B(X) GOTO .shift * Teste les bords .eshift CD1EX ; Recherche la ligne n。7 C=C-D CD1EX C=0(X) ; Masque plein C=C-1(X) P=15 LC(1) 7 ; 8 lignes P=0 .testloop A=DAT1(X) ; Teste si une ligne compl春e C=C&A(X) CD1EX ; Ligne pr残仕ente C=C-D CD1EX C=C-1(S) GONC .testloop C=C&B(X) ?C=0(X) GOYES .nobrk ; Si la pioche n'est pas cass仔 GOTO .end_dig .nobrk C=D ; Pointe sur la 7塾e ligne C=C+C C=C+C C=C+C AD1EX A=A+C AD1EX * Effacement des bords B=-B-1(X) ; Masque d'effacement P=15 LC(1) 7 ; Nombre de lignes P=0 .clrloop A=DAT1(X) ; Effacement A=A&B(X) DAT1(X)=A CD1EX ; Ligne precedente C=C-D CD1EX C=C-1(S) GONC .clrloop * Teste si pioche cass仔 en d姿lacement verticale ?ST(0)=0 GOYES .okmove ST(0)=0 GOTO .end_dig * Calcule les d姿lacements .okmove D0=D0+LEMV_Athletic ; Lit les directions choisies C=DAT0(P) D0=D0-LEMV_Athletic ?CBIT(2)=0 ; Si pas de d姿lacement X GOYES .nox D0=D0+LEMV_Dir A=DAT0(P) D0=D0-LEMV_Dir ?A=0(P) GOYES .right .left D0=D0+LEMV_PosX A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosX GOTO .nox .right D0=D0+LEMV_PosX A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosX .nox ?CBIT(3)=0 RTNYES D0=D0+LEMV_PosY A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosY RTN * Si on a cass la pioche pour une raison ou une autre .end_dig D0=D0+LEMV_Dir ; Chute dans la bonne direction A=DAT0(P) D0=D0-LEMV_Dir LC(1) LEMK_Right C=C+A(P) DAT0(P)=C D0=D0+LEMV_Athletic ; Debarasse de sa pioche. A=DAT0(P) LC(1) 3 A=A&C(P) DAT0(P)=A D0=D0-LEMV_Athletic RTN LEMR_ClimbRight: * --------------------------------------------------------------------- * * Lemming grimpeur * * --------------------------------------------------------------------- * LC(1) 7 ; Vitesse d'escalade / 8 A=A&C(P) ?A<>0(P) RTNYES * Teste le mur LC(1) 5 ; Nombre de lignes tester B=0(X) ; Masque total .mloop CD1EX ; Passe la ligne pr残仕ente C=C-D CD1EX A=DAT1(X) B=B|A(X) C=C-1(P) GONC .mloop D0=D0+LEMV_PosX A=DAT0(X) D0=D0-LEMV_PosX LC(1) 3 A=A&C(P) .sloop ?A=0(P) GOYES .xsloop B=B/2(X) A=A-1(P) GOTO .sloop .xsloop C=B(X) ?CBIT(5)=1 ; Si il y a un retrait GOYES .fall ?CBIT(7)=0 ; Si rien droite GOYES .walk ?CBIT(6)=0 ; Teste un l使er retrait GOYES .ok D0=D0+LEMV_PosX ; Recule l使俊ement A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosX RTN .ok D0=D0+LEMV_PosY A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosY RTN .walk LC(1) LEMK_Right ; Remet le lemming en marche DAT0(P)=C D0=D0+LEMV_PosX ; 1 pixel droite A=DAT0(X) A=A+1 DAT0(X)=A D0=D0-LEMV_PosX RTN .fall LC(1) LEMK_FallingL ; Lemming tombe gauche DAT0(P)=C D0=D0+LEMV_Dir LC(1) 1 DAT0(P)=C D0=D0-LEMV_Dir RTN LEMR_ClimbLeft: * --------------------------------------------------------------------- * * Lemming grimpeur * * --------------------------------------------------------------------- * LC(1) 7 ; Vitesse d'escalade / 8 A=A&C(P) ?A<>0(P) RTNYES * Teste le mur LC(1) 5 ; Nombre de lignes tester B=0(X) ; Masque total .mloop CD1EX ; Passe la ligne pr残仕ente C=C-D CD1EX A=DAT1(X) B=B|A(X) C=C-1(P) GONC .mloop D0=D0+LEMV_PosX A=DAT0(X) D0=D0-LEMV_PosX LC(1) 3 A=A&C(P) .sloop ?A=0(P) GOYES .xsloop B=B/2(X) A=A-1(P) GOTO .sloop .xsloop C=B(X) ?CBIT(2)=1 ; Si il y a un retrait GOYES .fall ?CBIT(0)=0 ; Si rien droite GOYES .walk ?CBIT(1)=0 ; Teste un l使er retrait GOYES .ok D0=D0+LEMV_PosX ; D残ale l使俊ement le lemmings A=DAT0(X) A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosX RTN .ok D0=D0+LEMV_PosY A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosY RTN .walk LC(1) LEMK_Left ; Remet le lemming en marche DAT0(P)=C D0=D0+LEMV_PosX ; 1 pixel droite A=DAT0(X) A=A-1 DAT0(X)=A D0=D0-LEMV_PosX RTN .fall LC(1) LEMK_FallingR ; Lemming tombe droite DAT0(P)=C D0=D0+LEMV_Dir C=0(P) DAT0(P)=C D0=D0-LEMV_Dir RTN LEMR_ConsRight: * --------------------------------------------------------------------- * * Lemming construisant des escaliers * * --------------------------------------------------------------------- * LC(1) 7 ; Divise par 8 la vitesse de construction A=A&C(P) ?A<>0(P) RTNYES D0=D0+LEMV_Data ; D残ompte le d姿lacement A=DAT0(B) A=A-1(B) DAT0(B)=A D0=D0-LEMV_Data A=A-1(B) ; Teste si fini GOC .end CD1EX ; Regarde si on rencontre un obstacle C=C-D CD1EX A=DAT1(X) A=A&B(X) ?A=0(X) GOYES .ok LC(1) LEMK_ConsLeft ; Retourne le bonhomme DAT0(P)=C LC(1) 1 ; Direction gauche D0=D0+LEMV_Dir DAT0(P)=C D0=D0-LEMV_Dir CD1EX ; Sous le lemmings C=C+D CD1EX B=B/2(X) ; Legerement a gauche A=DAT1(X) A=A|B(X) DAT1(X)=A RTN .end LC(1) LEMK_Right ; Retourne un bonhomme normal DAT0(P)=C RTN .ok D0=D0+LEMV_PosX A=DAT0(X) ; D姿lacement vers la droite A=A+1(X) DAT0(X)=A D0=D0-LEMV_PosX A=A-1(X) LC(1) 3 ; Teste si il faut monter A=A&C(P) ?A<>0(P) RTNYES D0=D0+LEMV_PosY ; Monte une marche A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosY LC(1) $F ; Ecrit une marche droite D1=D1+1 DAT1=C(P) RTN LEMR_ConsLeft: * --------------------------------------------------------------------- * * Lemming construisant des escaliers * * --------------------------------------------------------------------- * LC(1) 7 ; Divise par 8 la vitesse de construction A=A&C(P) ?A<>0(P) RTNYES D0=D0+LEMV_Data ; D残ompte le d姿lacement A=DAT0(B) A=A-1(B) DAT0(B)=A D0=D0-LEMV_Data A=A-1(B) ; Teste si fini GOC .end CD1EX ; Regarde si on rencontre un obstacle C=C-D CD1EX A=DAT1(X) A=A&B(X) ?A=0(X) GOYES .ok LC(1) LEMK_ConsRight ; Retourne le bonhomme DAT0(P)=C C=0(P) ; Direction droite D0=D0+LEMV_Dir DAT0(P)=C D0=D0-LEMV_Dir CD1EX ; Sous le lemmings C=C+D CD1EX B=B+B(X) ; Legerement a droite A=DAT1(X) A=A|B(X) DAT1(X)=A RTN .end LC(1) LEMK_Left ; Retourne un bonhomme normal DAT0(P)=C RTN .ok D0=D0+LEMV_PosX A=DAT0(X) ; D姿lacement vers la gauche A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosX A=A+1(X) LC(1) 3 ; Teste si il faut monter A=A&C(P) ?A<>0(P) RTNYES D0=D0+LEMV_PosY ; Monte une marche A=DAT0(X) A=A-1(X) DAT0(X)=A D0=D0-LEMV_PosY LC(1) $F DAT1(P)=C RTN LEMR_Exploder: * --------------------------------------------------------------------- * * Lem explosant * * --------------------------------------------------------------------- * D0=D0+LEMV_PosY ; Verifie si Y est sur A=DAT0(X) B=A(X) ; B = Y D0=D0-LEMV_PosY CD0EX D0=BACK_Height A=DAT0(X) ; A=Height CD0EX B=B-1(X) ; Y-2 B=B-1(X) LC(3) 12 ; Height - 12 A=A-C(X) ?BC GOYES .noup .doup D=D-1(X) D=D-1(X) .noup LC $04002 ; Touche bas ?A=C GOYES .dodown LC $00204 ; Touche 2 ?A<>C GOYES .nodown .dodown D=D+1(X) D=D+1(X) .nodown LC $04004 ; Touche gauche ?A=C GOYES .doleft LC $00408 ; Touche 4 ?A<>C GOYES .noleft .doleft B=B-1(X) B=B-1(X) .noleft LC $04001 ; Touche droite ?A=C GOYES .doright LC $00402 ; Touche 6 ?A<>C GOYES .noright .doright B=B+1(X) B=B+1(X) .noright D1= BACK_Width ; Teste si reste dans l'残ran LC(3) 7 A=DAT1(X) A=A-C(X) ?B>A(X) ; Si hors 残ran GOYES .nowrite D1=D1-3 A=DAT1(X) C=A-C(X) ?D>C(X) GOYES .nowrite C=D(X) ; Ecriture des nouvelles coordonn仔s DAT0(X)=C D0=D0-3 C=B(X) DAT0(X)=C * Calcule la position de l'残ran .nowrite D0=CRSR_PosX ; Lit les coordonn仔s r仔lles C=DAT0(X) B=C(X) D0=D0+3 C=DAT0(X) D=C(X) LC(3) 60 ; Par d伺aut, 60 pixel gche curseur B=B-C(X) GONC .xlok ; Teste si d姿assement gauche B=0 .xlok D0=BACK_Width ; Teste si d姿assement droite A=DAT0(X) LC(3) 131 A=A-C(X) ?B0(B) ; Si une touche press仔 GOYES .key ; donne le r市ultat C=C+C(X) ; Ligne suivante GOTO .loop .key CSL ; Passage de C dans la partie haute CSL C(B)=A .nokey2 D0= KEY_Last DAT0=C RTN .nokey C=0 GOTO .nokey2 ************************************************************************* * * * Gestion de l'残ran * * * ************************************************************************* SCRN_Copy: * --------------------------------------------------------------------- * * Copie l'残ran de fond sur l'残ran logique * * --------------------------------------------------------------------- * * L'残ran est copi en tenant compte des variables SCRN_PosX et SCRN_PosY * Le d残alage se fait 8 pixel par 8 pixel en X et Y, le reste 師ant * g屍 par SCRN_SwapScreen D0=SCRN_PosY ; Lecture de la position Y A=0 A=DAT0(X) ; Position Y LC(3) ~7 ; Ramen仔 un multiple de 8 A=A&C(X) D0=BACK_Width ; Lecture de la largeur de l'残ran C=0 C=DAT0(X) ; Largeur de l'残ran C=C/2(X) ; Taille en quartets C=C/2(X) RSTK=C ; Stocke la largeur de l'残ran GOSBVL ROM_B_is_AxC ; Offset par rapport au d暫ut D0=BACK_Base A=DAT0 A=A+B ; D暫ut de la premi俊e ligne copier D0=SCRN_PosX ; Offset horizontal C=0 C=DAT0(X) C=C/2(X) ; Taille en quartets C=C/2(X) C=C/2(X) ; Multiple d'un octet... C=C+C(X) A=A+C ; Position du d暫ut copier D0=A D1=SCRN_LogBase ; Destination de la copie A=DAT1 D1=A LC(2) 71 ; Nombre de lignes copier D=C(B) C=RSTK ; Largeur d'une ligne B=C LC 32 ; Moins qut transf屍仔 par copie B=B-C .line A=DAT0(W) ; Copie de 34 quartets DAT1(W)=A D0=D0+16 D1=D1+16 A=DAT0(W) DAT1(W)=A D0=D0+16 D1=D1+16 A=DAT0(X) DAT1(X)=A D1=D1+4 CD0EX C=C+B ; Passage la ligne suivante CD0EX D=D-1(B) GONC .line RTN SPRT_Display: * --------------------------------------------------------------------- * * Affichage d'un sprite * * --------------------------------------------------------------------- * * Entree= * A=Coordonnee X * B=Coordonnee Y * D=Numero du sprite * Sortie= * A(X): Masque du bas du sprite C=D ; Sauvegarde num屍o de sprite R0=C LC ~7 ; Charge le masque de d残alages 残rans D=C D0=SCRN_PosX ; Calcule le decalage par rapport a l'ecran C=0 C=DAT0(X) ; Position X de l'ecran C=C&D A=A-C D0=D0+3 C=DAT0(X) ; Position =Y de l'ecran C=C&D B=B-C C=R0 ; R残up俊e num屍o de sprite D=C C=0 LC(1) 8 ; Decalage pour les tests de clipping A=A+C B=B+C LC(2) 131+15 ; Si coordonnees hors ecran ?A>=C GOYES .out ; on ne trace rien LC(2) 64+15 ?B>=C GOYES .out R0=A ; Reserve la position X C=B ; Calcule l'addresse de debut de ligne Y*36+X/4 BSL ; Y * 16 C=C+C B=B+C ; * 18 B=B+B ; * 36 A=A/2 A=A/2 ; / 4 B=B+A D0=SCRN_LogBase A=DAT0 LC 8*36+2 ; Enleve le clipping en haut et a gauche A=A-C A=A+B ; Ajoute l'offset ecran D0=A ; D0=Addresse ecran DSL ; Numero de sprite => Offset de sprite D1=SPRT_Sprites A=DAT1 C=D A=A+C D1=A ; D1=definition du sprite A=R0 LC(1) 3 A=A&C(P) B=A(P) ; B=Compteur de decalages droit LC(1) 7 D=C(P) B=B-1(P) ; Teste le nombre de shifts GONC .nshift0 GOTO .shift0 * Sortie clipping .out LC(1) 3 C=C&A(P) B=C(P) ; B= D残alage coordonn仔 X DSL ; Numero de sprite => Offset de sprite D1=SPRT_Sprites A=DAT1 C=D A=A+C D1=A ; D1=definition du sprite D1=D1+14 ; Derni俊e ligne A=0(X) A=DAT1(B) .shloop ?B=0(P) RTNYES A=A+A(X) B=B-1(P) GOTO .shloop * D残alages et affichage .nshift0 B=B-1(P) GOC .shift1 B=B-1(P) GOC .shift2 * Cas o il y a trois d残alages faire .shift3 A=0(X) ; D残alage 3x A=DAT1(B) ASL(X) A=A/2(X) C=DAT0(X) ; Mise l'残ran C=C|A(X) DAT0(X)=C D0=D0+16 D0=D0+16 D0=D0+4 D1=D1+2 D=D-1(P) GONC .shift3 RTN * Cas o il y a deux d残alages faire .shift2 A=0(X) ; D残alage 2x A=DAT1(B) A=A+A(X) A=A+A(X) C=DAT0(X) ; Mise l'残ran C=C|A(X) DAT0(X)=C D0=D0+16 D0=D0+16 D0=D0+4 D1=D1+2 D=D-1(P) GONC .shift2 RTN * Cas o il y a un seul d残alage faire .shift1 A=0(X) ; D残alage A=DAT1(B) A=A+A(X) C=DAT0(X) ; Mise l'残ran C=C|A(X) DAT0(X)=C D0=D0+16 D0=D0+16 D0=D0+4 D1=D1+2 D=D-1(P) GONC .shift1 RTN * Cas o il n'y a pas de d残alage faire .shift0 A=0(X) ; Utilis pour que A soit bon en sortie A=DAT1(B) C=DAT0(B) ; Mise l'残ran C=C|A(B) DAT0(B)=C D0=D0+16 D0=D0+16 D0=D0+4 D1=D1+2 D=D-1(P) GONC .shift0 RTN SCRN_SwapScreen: * --------------------------------------------------------------------- * * Permutation des ecrans * * --------------------------------------------------------------------- * * La routine echange les variables SCRN_LogBase et SCRN_PhyBase. * Elle tient compte pour ecrire le pointeur ecran et les offsets des * variables de position SCRN_PosX et SCRN_PosY D0=HARD_ScreenHeight LC(2) 63 INTOFF ; Attend la synchro 残ran .waitVBL A=DAT0(B) A=A&C(B) ?A<>0(B) GOYES .waitVBL INTON A=0 D0=SCRN_PosY ; Calcul de l'offset ecran A=DAT0(1) ; Lecture de la partie basse LC(2) 7 A=A&C(B) C=A ASL ; * 16 C=C+C A=A+C ; * 18 A=A+A ; * 36 B=A ; Mis en reserve D0=SCRN_LogBase ; Pointeur ecran logique A=DAT0 D0=D0+5 ; D0=SCRN_PhyBase C=DAT0 DAT0=A ; Permutation des ecrans D0=D0-5 DAT0=C D0=HARD_ScreenBase ; Pointeur physique ecran A=A+B ; Plus decalage vertical DAT0=A ; Stockage du pointeur ecran D0=SCRN_PosX ; Offset horizontal A=DAT0(1) LC(2) 7 A=A&C(B) ?ABIT(2)=0 GOYES .SmallPosX ; Quand le decalage ecran est > 4 LC(1) $C A=A|C ; Grand decalage Hard D0=HARD_ScreenShift ; Decalage hard D1=HARD_ScreenWidth C=0 DAT0=A(1) DAT1=C(3) ; Largeur = 0 RTN ; Quand le decalage ecran est < 4 .SmallPosX: LC(1) 3 A=A&C(B) LC(1) $8 A=A|C D0=HARD_ScreenShift D1=HARD_ScreenWidth LC(3) $002 DAT1=C(3) ; Largeur=2 DAT0=A(1) RTN ************************************************************************* * * * Initialisation et terminaison * * * ************************************************************************* FATAL_ERROR C=RSTK ; Si impossible de jouer... GOSBVL ROM_LoadRegs LC $4BD01 A=C GOVLNG ROM_Error ; Affiche l'erreur LEM_Init: *-----------------------------------------------------------------------* * Initialisation du programme * *-----------------------------------------------------------------------* GOSBVL ROM_SaveRegs D0=RRAM_GROBStack ; Teste si l'残ran peut accueillir A=DAT0 ; les variables du programme LC 20 A=A+C LC VARS_Start ?CA(A) GOYES FATAL_ERROR A=DAT1 ; Lecture du GROB sprites LC 20 A=A+C D0=SPRT_Sprites DAT0=A * Initialisation des 残rans D1=D1+5 ; Lecture du GROB 残ran A=DAT1 LC 36*16+22 ; D暫ut de l'残ran physique A=A+C ABIT(0)=0 ; S'assure que sur adresse paire D0=SCRN_LogBase ; Adresse de l'残ran logique DAT0=A LC 36*80 A=A+C D0=SCRN_PhyBase ; Adresse de l'残ran physique DAT0=A * Initialisation des variables D1=D1+5 ; Lecture du Library Data AD1EX B=A ; Sauvegarde D1 AD1EX A=DAT1 D0=A D0=D0+10 ; Saute le prologue et la taille P= 3+3+2+3-1 ; Taille des donn仔s lues D1= LEM_PosX ; Position de d姿art des lemmings A=DAT0(WP) DAT1(WP)=A D0=D0+3+3+2+3 P= 3+3+2-1 ; Position d'arriv仔 des lemmings D1=LEM_ExitX A=DAT0(WP) DAT1(WP)=A D0=D0+3+3+2 P=6*2-1 ; Nombre de lemmings de chaque type D1=LEMC_Parachute A=DAT0(WP) DAT1(WP)=A D0=D0+6*2 P=0 ; Temps accord C=DAT0 C=C+C ; Passe en secondes D1=HARD_Ticks+3 A=DAT1 A=A-C D1=TIME_Allowed DAT1=A D0=D0+5 A=B AD1EX ; Restaure D1 * Initialisation du fond d'残ran D1=D1+5 ; Lecture du GROB de fond A=DAT1 LC 20 ; Offset au d暫ut du GROB A=A+C D0=BACK_Base DAT0=A D1=A D1=D1-10 C=DAT1 D0=D0+5 ; BACK_Height DAT0(X)=C D1=D1+5 A=DAT1 D0=D0+3 ; BACK_Width DAT0(X)=A * Remplit un tableau avec les offsets des debuts de ligne du fond C=C+1 B=C C=C+C C=C+C C=C+B ; 5 quartets par ligne GOSBVL ROM_ResString CD0EX D0= BACK_LineStart DAT0=C D0=C D1=BACK_Base ; Lit l'adresse de d暫ut de l'objet A=DAT1 ; A = adresse courante D1=D1+5 ; BACK_Height C=0 C=DAT1(X) ; Lit le nombre de lignes B=C(X) D1=D1+3 C=DAT1(X) ; C=largeur C=C/2 C=C/2 ; Largeur en quartets .wloop B=B-1(X) ; Decomptage des lignes GOC .exitloop DAT0=A A=A+C ; Adresse de la ligne suivante D0=D0+5 GOTO .wloop * Efface la derni俊e ligne .exitloop A=A-C D0=A ; Adresse de la derni俊e ligne A=0 .clrloop C=C-1(X) ; Taille en quartets GOC .exitloop2 DAT0(P)=A D0=D0+1 GOTO .clrloop * R市ervation des donn仔s pour les lemmings .exitloop2 LC 16*LEM_MaxNumber GOSBVL ROM_ResString CD0EX D0= LEM_Data DAT0=C D0=C LC(2) LEM_MaxNumber-1 A=0(W) .emptylems DAT0=A(W) D0=D0+16 C=C-1(B) GONC .emptylems * Copie la position initiale des lemmings dans celle du curseur D0= LEM_PosX A=DAT0(X) D0=D0+3 C=DAT0(X) C=C+16 D0=CRSR_PosX DAT0(X)=A D0=D0+3 DAT0(X)=C * Mise 0 de certaines variables C=0 D0= LEM_Exited DAT0(B)=C D0= MENU_Index ; Premier menu DAT0=C ; MENU_Index, OFF_Flag, QUIT_Flag, PAUSE_Flag D0=LEM_Number DAT0(B)=C D0=LEM_Count ; D四ai avant cr斬tion du premier lemmings DAT0(X)=C * Copie le nombre de lemmings a sortir dans le nombre de lemmings initiaux D0=LEM_ToExit A=DAT0(B) D0=D0+2 ; LEM_IToExit DAT0(B)=A * Decr士ente BACK_Height (Derni俊e ligne vide, permet de faire sortir les lemmings par le bas) D0=BACK_Height A=DAT0(X) A=A-1(X) DAT0(X)=A * Coupe les IT clavier ST(15)=0 ; Coupe les interruptions RTN LEM_Quit: * --------------------------------------------------------------------- * * Quitte le programme * * --------------------------------------------------------------------- * D0= RRAM_ScreenBase A=DAT0 D0= HARD_ScreenBase DAT0=A D0= RRAM_ScreenMenuBase A=DAT0 D0= HARD_ScreenMenuBase DAT0=A D0= HARD_ScreenShift LC(1) 8 DAT0=C(1) D0= HARD_ScreenWidth C(X)=0 DAT0=C(X) * Restaure le contenu des registres sauvegard市 GOSBVL ROM_LoadRegs D1=D1+10 ; D姿ile Sprites, Ecran, LibData et Tableau D1=D1+10 D=D+4 ; Indique place suppl士entaire libre GOSBVL ROM_SaveRegs * Restaure les interruptions et retourne GOSBVL ROM_RestoreIT ; Reinitialise les interruptions RTN CallOFF: * --------------------------------------------------------------------- * * Ex残ute l'instruction OFF et relance la boucle * * --------------------------------------------------------------------- * D0=HARD_Ticks+3  C=DAT0 D0=TIME_Allowed ; M士orise le temps restant A=DAT0 A=A-C DAT0=A D0=HARD_ScreenContrast A=DAT0(B) C=0(B) DAT0(B)=C ; Pour que l'allumage soit joli D0=OFF_Flag ; Efface le drapeau OFF DAT0(B)=A ST(15)=1 ; Restaure les IT PROTECT GOVLNG ROM_LoadRegsEnd ; Retour au RPL AddrOFF: * --------------------------------------------------------------------- * * Adresse de l'instruction OFF qui suit * * --------------------------------------------------------------------- * END ; ASM OFF @ Ce OFF est appel si on demande la pause pause ASM RestartOFF: GOSUB .addr DR AddrOFF .addr C=RSTK ; R残up俊e l'adresse D0=C A=DAT0 A=A+C ; Adresse absolue de l'instruction OFF D0=A ; Restaure D0 pour l'appel suivant de la pause GOSBVL ROM_SaveRegs ; Et resauve les registres ST(15)=0 ; Coupe les interruptions D0=HARD_Ticks+3 ; Recalcule le temps final en fn du A=DAT0 ; Timer D0=TIME_Allowed C=DAT0 A=A+C DAT0=A D0=OFF_Flag A=DAT0(B) C=0(B) DAT0(B)=C D0=HARD_ScreenContrast ; Restaure le contraste DAT0(B)=A GOLONG MAIN_LOOP ; Relance la boucle principale END END @ Fin de LEMCode @ *********************************************************************** @ * * @ * D残ompacteur de LEMMINGS * @ * * @ *********************************************************************** DecompactLEM PROG Check1 PROG LEMPatterns SWAP INCLUDE "Decompacteur.48S" END END @ *********************************************************************** @ * * @ * Informations sur L E M M I N G S ! * @ * * @ *********************************************************************** AboutLEM PROG LEMScreen Display EXTERNAL #40F12h @ VeryVerySlow CLLCD TEXT @2345678901234567890123 " After 」BPACMAN 」W After 」BTETRIS 」W DEQUB presentsノ 」W 」I 」i 」I LEMMINGS! 」i 」I 」i 」W」W」W This program has not yet been qualified for all publics. Parental advisory required. Ce programme n'ayant pas encore re講 son visa d'exploitation pour des raisons techniques, les uti- lisateurs sont pri市 de s'assurer qu'il est destin tous les publics This program is 90% SATURN assembler. It was written on 」I HPDS 3.0 Ce programme est 残rit 90% en 」Bassembleur SATURN. Il a 師 compil sur 」I HPDS 3.0 Cette oeuvre est une pure fiction. Toute ressemblance avec des personnages existant, ayant exist, qui existeront, qui existeraient, qui auraient exist ou qui seront 師 exist市 ne seraient que pure co貧cidence. 」I THE END 」i " VScroll EXTERNAL #3922Fh @ 7 FREEZE END @ *********************************************************************** @ * * @ * Gestion du score, de l'affichage, etc * @ * * @ *********************************************************************** Display PROG <64d> <131d> EXTERNAL #1158Fh @ Cree un GROB 131x64 EXTERNAL #12F94h @ PICT STO EXTERNAL #13135h @ Display PICT ASM DoDisplay: GOSBVL ROM_SaveRegs D0=RRAM_GROBCurrent ; Passe sur l'残ran de pile A=DAT0 LC 20 A=A+C R1=A ; Destination A=DAT1 LC 20 ; Donn仔s du GROB A=A+C R0=A ; Source LC(1) 8 ; Nombre de d残alages B=C(P) .sloop A=R0 ; Source (GROB) D0=A A=R1 ; Destination (Ecran) D1=A LC(3) 17*64-1 ; Nombre d'octets D=C(X) .bloop A=DAT0(B) C=B(P) .shift C=C-1(P) GOC .xshift A=A+A(B) A=A+1(B) GOTO .shift .xshift DAT1(B)=A D0=D0+2 D1=D1+2 D=D-1(X) GONC .bloop D0=HARD_ScreenBase A=R1 DAT0=A D0=HARD_ScreenHeight ; Hauteur de l'残ran LC(2) 63 DAT0=C(B) LC(3) 1000 .wait C=C-1(X) GONC .wait B=B-1(P) GONC .sloop LC $3000 .wait2 C=C-1 GONC .wait2 GOLONG PROTECT END DROP END @ ROUTINE DE SCROLLING VERTICAL DE TEXTE VScroll INCLUDE "About.48S" @ *********************************************************************** @ * * @ * Commandes principales de la librairies * @ * * @ *********************************************************************** LEM @ ===================================================================== @ Start game at first level @ ===================================================================== PROG 1 LEMLoop END LevelLEM @ ===================================================================== @ Start game at first level whose name is string @ ===================================================================== PROG Check1 <3h> PROG " " EXTERNAL #05193 @ String + <1> <8> EXTERNAL #05733 @ String SUB Tronque la cha馬e la bonne taille LEMLevels ASM FINDLEVEL GOSBVL ROM_SaveRegs D1=D1+5 ; Lit le niveau 2 (cha馬e) A=DAT1 D0=A D0=D0+10 C=DAT0(W) ; Lit les 8 caract俊es D=C(W) D1=D1-5 ; Lit la liste des tableaux A=DAT1 D0=A B=0 ; Compteur d'四士ent .loop B=B+1 ; Num屍o d'四士ent D0=D0+5 ; Lit le prologue de "fin" A=DAT0 LC $0312B ; Prologue de fin ? ?A<>C GOYES .noerr GOSBVL ROM_LoadRegs LC $4BD02 ; Message d'erreur "Does not exist" A=C GOVLNG ROM_Error .error GOSBVL ROM_LoadRegs LC $4BD03 ; Message d'erreur "Invalid LEMDAT" A=C GOVLNG ROM_Error .noerr D0=D0+5 ; Saute le prologue liste GOSBVL ROM_Next ; Saute le tableau A=DAT0 ; Teste si le Library Data est OK D0=D0+5 LC $02B88 ; Prologue "Library Data" ?A<>C GOYES .error A=DAT0 D0=D0+5 LC $00039 ; Longueur normale du Library Data ?A<>C GOYES .error AD0EX LC 36 ; D暫ut de la cha馬e A=A+C AD0EX C=DAT0(W) D0=D0+16 ?C=D(W) ; Boucle tant que la cha馬e n'est pas bonne GOYES .end GOTO .loop .end C=B RSTK=C GOSBVL ROM_LoadRegs C=RSTK A=C PROTECT2 GOVLNG ROM_PushA ; Met A dans la pile comme Integer END B->R @ Convertit en r仔l EXTERNAL #6112Ah @ DROP(2-3) LEMLoop @ Appelle la boucle des lemmings END END LEMLoop @ ===================================================================== @ Loop all levels from the one in the stack @ ===================================================================== PROG -> L << LEMScreen Display @ Affiche le start screen EXTERNAL #40F02h @ VerySlow XHERE LEM_LOOP_ADDR LEMLevels L GET LIST-> DROP @234567890123456789012 " Niveau: 」B********」b Temps maximum: 」B9:99」b 」B99」b lemmings 」B99」b sauver Bonne chanceノ" NEWOB ASM ; Dans le Library Data ; Offset start : 6 ; Offset exit : 17 ; Offset temps : 31 ; Offset titre : 36 STARTTEXT GOSBVL ROM_SaveRegs D1=D1+5 ; Library Data A=DAT1 LC 10+36 ; Pointe vers le nom du niveau A=A+C D0=A D1=D1-5 ; Cha馬e de caract俊es A=DAT1 LC 14*2+10 ; Nom du niveau A=A+C D1=A ; Pointeur vers la cha馬e C=DAT0(W) ; Copie le nom du tableau DAT1(W)=C AD1EX LC 60 A=A+C AD1EX ; Pointe vers le temps D0=D0-5 ; Pointe vers le temps A=DAT0 LC 60 ; Nombre de secondes B=C P=4 ; Champ A GOSUBL DivideAB P=0 D=C(B) ; Ecrit le nombre de minutes LC(2) "0" C=C+D(B) DAT1=C(B) D1=D1+4 LC 10 ; Secondes et dizaines B=C P=4 GOSUBL DivideAB P=0 D=C(B) ; Ecrit les dizaines de secondes LC(2) "0" C=C+D(B) DAT1=C(B) D1=D1+2 LC(2) "0" ; Ecrit les secondes C=C+A(B) DAT1=C(B) D1=D1+12 D1=D1+10 ; Pointe sur le nombre de lemmings D0=D0-15 ; Pointe sur le nb de lemmings D0=D0-10 A=DAT0(B) LC(2) 10 B=C(B) P=1 GOSUBL DivideAB P=0 D=C(B) LC(2) "0" C=C+D(B) DAT1(B)=C D1=D1+2 LC(2) "0" C=C+A(B) DAT1(B)=C D1=D1+8 D1=D1+16 D1=D1+16 D0=D0+11 ; Nombre de lemmings sortir A=DAT0(B) LC(2) 10 B=C(B) P=1 GOSUBL DivideAB P=0 D=C(B) LC(2) "0" C=C+D(B) DAT1(B)=C D1=D1+2 LC(2) "0" C=C+A(B) DAT1(B)=C GOLONG PROTECT END ; ASM CLLCD TEXT VScroll LEMLaunch EXTERNAL #13135h @ Display PICT EXTERNAL #40F02h @ Wait .4 s EXTERNAL #40F02h @ Wait .4 s EXTERNAL #00D71h @ Vide le buffer clavier ASM LEMLoopOffset GOSBVL ROM_SaveRegs * Calcule la valeur D0=LEM_ToExit LC 1 ; Ajouter 1 si OK A=DAT0(B) ?A=0(B) GOYES .inc C=0 .inc RSTK=C GOSBVL ROM_LoadRegs C=RSTK A=C GOLONG PROTECT2 END ; ASM B->R L + 1 - LEMLevels SIZE MOD 1 + Quote L STO ASM ExitLEMLoop GOSBVL ROM_SaveRegs D0=QUIT_Flag A=DAT0(P) ?A<>0(P) GOYES .exit GOSUB .loop DR LEM_LOOP_ADDR .loop GOSBVL ROM_LoadRegs C=RSTK ; Boucle l'adresse indiqu仔 D0=C A=DAT0 A=A+C D0=A A=DAT0 ; Apr峻 l'appel, relance le programme D0=D0+5 PC=(A) .exit GOLONG PROTECT END CLLCD TEXT >> END LEMLaunch @ ===================================================================== @ Launch a given level of lemmings @ ===================================================================== PROG Check2 @ GROB et Library Data PROG EXTERNAL #05F42 @ Garbage collector SWAP DecompactLEM SWAP <178d> <144d> EXTERNAL #1158Fh @ Cr仔 les 残rans sur la pile LEMSprites @ Stocke les sprites sur la pile EXTERNAL #05F42 @ Garbage collector LEMCode END END LEMLevels @ ===================================================================== @ List of all levels @ ===================================================================== PROG LEMDAT PROG ACheck1 <5> PROG END @ List <6> PROG EXTERNAL #03244 { } END @ Global Name: DoDROP <0> InvalidLEMDAT @ Any other END INCLUDE "Tableaux.48S" EXTERNAL #0521F @ List + END InvalidLEMDAT PROG #4BD03 DOERR END END