SprGes es un grupo de programas que tenía por objeto acabar con el límite de memoria que Qbasic imponía a las matrices de gráficos. A través de un programa residente en memoria (TSR) vinculado a un controlador de interrupción se reservaba memoria para gráficos de modo MCGA (320×200, 256 colores, el mejor modo gráfico para juegos usando gráficos VGA estándar).
El programa estaba creado en una mezcla de CSEMBL] (para la parte del TSR) y basic (para el juego en cuestión). Una versión compilada (funciona solo en sistemas anteriores a XP, que soporten archivos .COM, y podría ser peligroso ejecutarla en Windows) puede descargarse de [[http://jgmoyay.apagada.com.
Antes de ejecutar estos programas es necesario haber cargado SPRGES16.COM o SPRGES2.COM
DECLARE SUB LUCHA (X%, Y%) DECLARE SUB Centrar (Lin%, MSG$) DECLARE FUNCTION ValorM% (X%, Y%) DECLARE SUB SPRITEPSET2 (N%) DECLARE SUB CARGASPRITES () DECLARE SUB PonerM (X%, Y%, Objeto%) DECLARE SUB MostrarP (X%, Y%) DECLARE FUNCTION VALORMAPA% (X%, Y%) DEFINT A-Z PRINT "JUEGOMAP." PRINT "Ejemplo de juego, creado con MAPAGES2, que utiliza SPRGEST." SLEEP 5: I$ = INKEY$: I$ = "" CLS DIM SHARED NULL AS STRING * 1: NULL = CHR$(0) 'Este programa utiliza SPRGEST para poner gr ficos en pantalla. 'Lo que sigue son matrices est ticas '$STATIC DIM SHARED RUTINAMAQUINA%(1 TO 16), MAQDESP%, MAQSEG% 'Inicializar la rutina secundaria de c¢digo m quina. MAQDESP% = VARPTR(RUTINAMAQUINA%(1)) MAQSEG% = VARSEG(RUTINAMAQUINA%(1)) DEF SEG = MAQSEG% RESTORE RutiMaqData FOR F = 0 TO 15 READ DATO$ POKE MAQDESP% + F, VAL("&h" + LTRIM$(DATO$)) NEXT DEF SEG DIM SHARED MAPADESP%, MAPASEG% 'Tomar ubicaci¢n de INT 60h DEF SEG = 0 I60 = 4 * &H60 des = PEEK(I60) + 256 * PEEK(I60 + 1) MAPASEG% = PEEK(I60 + 2) + 256 * PEEK(I60 + 3) DEF SEG = MAPASEG% FOR F = 1 TO 8 IF PEEK(des + F + 1) <> ASC(MID$("SPR_GEST", F, 1)) THEN PRINT "ERROR: SPRGEST (gestor de sprites y memoria) no cargado." SYSTEM END IF NEXT UBI = des + 10 MAPADESP% = PEEK(UBI) + 256 * PEEK(UBI + 1) 'No podr‚ utilizar los 256 sprites, puesto que ocupan mucho m s de '64Kb. '$STATIC DIM SHARED SPRITES%(32766), SPRDESP%, SPRSEG% 'DIM SHARED SPRIT%(FRE(1) / 2) SPRDESP% = VARPTR(SPRITES%(0)) SPRSEG% = VARSEG(SPRITES%(0)) SCREEN 13 CARGASPRITES X = 0: Y = 0 SPRACT% = 0 LSTSPRACT% = -1 Armapa$ = "JUEGO" IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BLOAD Armapa$, MAPADESP% DEF SEG END IF 'Poner el marcador de energ¡a Energia = 200 LINE (256, 0)-(319, 199), 0, BF LINE (280, 0)-(296, 200 - Energia), 7, B LINE (280, 200 - Energia)-(296, 199), 7, BF X0 = 1: Y0 = 1: ' ObjetoSPR = ValorM(X1 + X0 + 1, Y1 + Y0 + 1) DO ObjetoSPR = ValorM(X1 + X0 + 1, Y1 + Y0 + 1) SELECT CASE ObjetoSPR CASE 1 Oro = Oro + 100: ObjetoSPR = 0': PLAY "L63CDEFCDEG" 'SOUND 1000, .5: SOUND 2000, .5 FOR W = 1 TO 5: SOUND 500 * W, .1: NEXT CASE 20, 21 PLAY "L63A#C" SWAP ObjetoSPR, ObjetCogido SELECT CASE ObjetCogido CASE 20: Nobjeto$ = "Hacha" CASE 21: Nobjeto$ = "Espada" END SELECT END SELECT PonerM X1 + X0 + 1, Y1 + Y0 + 1, 50 + DIRE + ESTA LOCATE 25, 1: PRINT USING "ORO: ##### Arma:\ \ Llaves:####"; Oro; Nobjeto$; llaves; ESTA = ESTA + 1: IF ESTA > 1 THEN ESTA = 0 DO GOSUB MueveMalos IN$ = INKEY$ LOOP UNTIL IN$ > "" PonerM X1 + X0 + 1, Y1 + Y0 + 1, ObjetoSPR SELECT CASE IN$ CASE "4", NULL + "K" X0 = X0 - 1 DIRE = 2 IF X0 < 0 THEN X0 = 0: IF X1 > 0 THEN X1 = X1 - 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN X0 = X0 + 1 IF VM1 >= 30 AND VM1 <= 36 THEN X0 = X0 + 1: LUCHA X1 + X0, Y1 + Y0 + 1 CASE "8", NULL + "H" Y0 = Y0 - 1 DIRE = 4 IF Y0 < 0 THEN Y0 = 0: IF Y1 > 0 THEN Y1 = Y1 - 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN Y0 = Y0 + 1 IF VM1 >= 30 AND VM1 <= 36 THEN Y0 = Y0 + 1: LUCHA X1 + X0 + 1, Y1 + Y0 CASE "6", NULL + "M" X0 = X0 + 1 DIRE = 0 IF X0 > 7 THEN X0 = 7: IF X1 < 119 THEN X1 = X1 + 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN X0 = X0 - 1 IF VM1 >= 30 AND VM1 <= 36 THEN X0 = X0 - 1: LUCHA X1 + X0 + 2, Y1 + Y0 + 1 CASE "2", NULL + "P" Y0 = Y0 + 1 DIRE = 6 IF Y0 > 5 THEN Y0 = 5: IF Y1 < 248 THEN Y1 = Y1 + 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN Y0 = Y0 - 1 IF VM1 >= 30 AND VM1 <= 36 THEN Y0 = Y0 - 1: LUCHA X1 + X0 + 1, Y1 + Y0 + 2 CASE CHR$(27): EXIT DO END SELECT LOOP RutiMaqData: 'Rutina en c¢digo m quina DATA b8,00,00,bb,00,00,b9,00,00,ba,00,00,cd,60,cb,90 MueveMalos: ESTADO = ESTADO + 1 IF ESTADO > 20 THEN FOR F = 0 TO 8: FOR G = 0 TO 6 XF = X1 + F: YG = Y1 + G 'Espero que esto acelere el programa. VM = ValorM(XF, YG) SELECT CASE VM CASE 30, 31, 33, 34: PonerM XF, YG, VM + 1 CASE 32, 35: PonerM XF, YG, VM - 2 END SELECT NEXT: NEXT MostrarP X1, Y1 ESTADO = 0 END IF RETURN SUB CARGASPRITES Archiv$ = "Juego" Archiv$ = LTRIM$(RTRIM$(Archiv$)) PRINT "Cargando la paleta.": PRINT "Espere, por favor..." FOR F = 0 TO 7: FOR G = 0 TO 31 LINE (G * 8, 64 + F * 8)-(7 + G * 8, 73 + F * 8), F * 32 + G, BF NEXT: NEXT DIM RGB AS STRING * 3 NFILE = FREEFILE OPEN Archiv$ + "._PA" FOR BINARY AS NFILE FOR F = 0 TO 255 GET NFILE, , RGB PALETTE F, CVL(RGB + NULL) NEXT F CLOSE NFILE PRINT "Cargando los dibujos.": PRINT "Espere, por favor..." NFILE = FREEFILE OPEN Archiv$ + "._SP" FOR BINARY AS NFILE LIMITF = UBOUND(SPRITES%) 'X = 0: Y = 0 F = 0 DO UNTIL EOF(1) GET NFILE, , SPRITES%(F) 'MK$ = MKI$(SPRITES%(F)) 'SPRITES%(F) = CVI(RIGHT$(MK$, 1) + LEFT$(MK$, 1)) IF F = LIMITF THEN EXIT DO F = F + 1 LOOP CLOSE NFILE END SUB SUB Centrar (Lin, MSG$) X2 = 40 - LEN(MSG$) / 2 IF X2 = 0 THEN LOCATE Lin, 1 ELSE LOCATE Lin, X2 PRINT MSG$ END SUB SUB LUCHA (X, Y) SHARED Energia, ObjetCogido Venem = ValorM(X, Y) SELECT CASE Venem CASE 30 TO 32 'Anillo Ataque2 = 1: Efecto = 15 'Soborno = 500: ObjetDesea = 0: Enigma = -1 CASE 33 TO 35 'Devorador Ataque2 = 2: Efecto = 10 'Soborno = 500: ObjetDesea = 0: Enigma = 0 END SELECT IF Ataque2 = 0 THEN EXIT SUB SOUND 250, .4: SOUND 100, .8: SOUND 250, .4 SELECT CASE ObjetCogido CASE 20 'Hacha Ataque1 = 1 CASE 21 'Espada Ataque1 = 2 END SELECT Suerte1 = INT(RND * Ataque1 * 10): Suerte2 = INT(RND * Ataque2 * 10) IF Suerte1 > Suerte2 THEN PonerM X, Y, 0 ELSE 'Si han tenido el mismo resultado, ambos pierden IF Suerte1 = Suerte2 THEN PonerM X, Y, 0 'Si el malo ha tenido mucha suerte, el bueno pierde m s vida. IF Suerte2 > Suerte1 * 10 THEN Efecto = Efecto * 2 Energia = Energia - Efecto LINE (256, 0)-(319, 199), 0, BF LINE (280, 0)-(296, 200 - Energia), 7, B LINE (280, 200 - Energia)-(296, 199), 7, BF IF Energia < 0 THEN Centrar 12, "Est s Muerto" END END IF END IF END SUB SUB MostrarP (X, Y) DEF SEG = MAQSEG% 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT POKE MAQDESP% + 1, Y: POKE MAQDESP% + 2, 0 POKE MAQDESP% + 4, X: POKE MAQDESP% + 5, 0 POKE MAQDESP% + 7, SPRSEG% MOD 256 POKE MAQDESP% + 8, INT(SPRSEG% / 256) POKE MAQDESP% + 10, SPRDESP% MOD 256 POKE MAQDESP% + 11, INT(SPRDESP% / 256) 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT 'END CALL ABSOLUTE(MAQDESP%) DEF SEG END SUB SUB PonerM (X, Y, Objeto) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT SUB MEMUBIC& = MAPADESP% + (X * 256& + Y) POKE MEMUBIC&, Objeto DEF SEG END SUB SUB SPRITEPSET2 (N%) DIM SPR%(514) N2% = N% * 512 GET (0, 0)-(31, 31), SPR%(0) FOR F = 0 TO 511 SPR%(F + 2) = SPRITES%(N2% + F) NEXT 'SPR%(0) = 32: SPR%(1) = 32 PUT (288, 0), SPR%(0), PSET END SUB FUNCTION ValorM (X, Y) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT FUNCTION MEMUBIC& = MAPADESP% + (X * 256& + Y) ValorM = PEEK(MEMUBIC&) DEF SEG END FUNCTION FUNCTION VALORMAPA% (X, Y) DEF SEG = MAPASEG% MEMUBIC% = MAPADESP% + (Y * 256 + X) VALORMAPA% = PEEK(MEMUBIC%) DEF SEG END FUNCTION
DECLARE SUB ReorgaMapa () DECLARE SUB SPRITEPSET2 (n%) DECLARE SUB CARGASPRITES () DECLARE SUB PONERM (X%, Y%, Objeto%) DECLARE SUB MOSTRARP (X%, Y%) DECLARE FUNCTION VALORMAPA% (X%, Y%) DEFINT A-Z PRINT "MAPAGEST." PRINT "Creador de mapas para juegos que utilizan SPRGEST." SLEEP 5: I$ = INKEY$: I$ = "" CLS DIM SHARED NULL AS STRING * 1: NULL = CHR$(0) 'Este programa utiliza SPRGEST para poner gr ficos en pantalla. 'Lo que sigue son matrices est ticas '$STATIC DIM SHARED RUTINAMAQUINA%(1 TO 16), MAQDESP%, MAQSEG% 'Inicializar la rutina secundaria de c¢digo m quina. MAQDESP% = VARPTR(RUTINAMAQUINA%(1)) MAQSEG% = VARSEG(RUTINAMAQUINA%(1)) DEF SEG = MAQSEG% RESTORE RutiMaqData FOR F = 0 TO 15 READ DATO$ POKE MAQDESP% + F, VAL("&h" + LTRIM$(DATO$)) NEXT DEF SEG DIM SHARED MAPADESP%, MAPASEG% 'Tomar ubicaci¢n de INT 60h DEF SEG = 0 I60 = 4 * &H60 des = PEEK(I60) + 256 * PEEK(I60 + 1) MAPASEG% = PEEK(I60 + 2) + 256 * PEEK(I60 + 3) DEF SEG = MAPASEG% FOR F = 1 TO 8 IF PEEK(des + F + 1) <> ASC(MID$("SPR_GEST", F, 1)) THEN PRINT "ERROR: SPRGEST (gestor de sprites y memoria) no cargado." SYSTEM END IF NEXT UBI = des + 10 MAPADESP% = PEEK(UBI) + 256 * PEEK(UBI + 1) 'No podr‚ utilizar los 256 sprites, puesto que ocupan mucho m s de '64Kb. '$STATIC DIM SHARED SPRITES%(32766), SPRDESP%, SPRSEG% 'DIM SHARED SPRIT%(FRE(1) / 2) SPRDESP% = VARPTR(SPRITES%(0)) SPRSEG% = VARSEG(SPRITES%(0)) SCREEN 13 FOR F = 0 TO 10 STEP 2 FOR G = 0 TO 10 STEP 2 PONERM F, G, 0 PONERM F + 1, G, 1 PONERM F, G + 1, 1 PONERM F + 1, G + 1, 0 NEXT NEXT PONERM 0, 1, 1 PONERM 1, 0, 1 CARGASPRITES X = 0: Y = 0 SPRACT% = 0 LSTSPRACT% = -1 DO IF SPRACT% <> LSTSPRACT% THEN SPRITEPSET2 (SPRACT%) END IF LSTSPRACT% = SPRACT% MOSTRARP X1, Y1 LINE (X0 * 32, Y0 * 32)-(X0 * 32 + 31, Y0 * 32 + 31), 7, B LINE (X0 * 32 + 1, Y0 * 32 + 1)-(X0 * 32 + 30, Y0 * 32 + 30), 0, B DO: IN$ = INKEY$: LOOP UNTIL IN$ > "" SELECT CASE IN$ CASE NULL + CHR$(68) INPUT "Grabar: Entre el nombre del archivo mapa:"; Armapa$ IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BSAVE Armapa$, MAPADESP%, 32768! DEF SEG END IF CASE NULL + CHR$(67) INPUT "Cargar: Entre el nombre del archivo mapa:"; Armapa$ IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BLOAD Armapa$, MAPADESP% DEF SEG END IF 'Cambiado 256 a 61 (en realidad s¢lo hay 63 dibujos (o menos)) CASE "+": SPRACT% = SPRACT% + 1: IF SPRACT% > 62 THEN SPRACT% = 0 CASE "*": SPRACT% = SPRACT% + 1: IF SPRACT% > 62 THEN SPRACT% = 62 - SPRACT% CASE "-": SPRACT% = SPRACT% - 1: IF SPRACT% < 0 THEN SPRACT% = 61 CASE "/": SPRACT% = SPRACT% - 10: IF SPRACT% < 0 THEN SPRACT% = 62 + SPRACT% CASE "4", NULL + "K" X0 = X0 - 1 IF X0 < 0 THEN X0 = 0: IF X1 > 0 THEN X1 = X1 - 1 END IF CASE "8", NULL + "H" Y0 = Y0 - 1 IF Y0 < 0 THEN Y0 = 0: IF Y1 > 0 THEN Y1 = Y1 - 1 END IF CASE "6", NULL + "M" X0 = X0 + 1 IF X0 > 7 THEN X0 = 7: IF X1 < 119 THEN X1 = X1 + 1 END IF CASE "2", NULL + "P" Y0 = Y0 + 1 IF Y0 > 5 THEN Y0 = 5: IF Y1 < 248 THEN Y1 = Y1 + 1 END IF CASE CHR$(13) PONERM X0 + X1 + 1, Y0 + Y1 + 1, SPRACT% 'PLAY "C63" MOSTRARP X1, Y1 CASE CHR$(27): EXIT DO CASE NULL + CHR$(59)'F2 ReorgaMapa MOSTRARP X1, Y1 CASE CHR$(10) 'CTR_RET VM = VALORMAPA%(X1 + X0 + 1, Y1 + Y0 + 1) IF VM >= 0 AND VM <= 62 THEN SPRACT% = VM END SELECT IF INSTR("24568", IN$) > 0 THEN PONERM X0 + X1 + 1, Y0 + Y1 + 1, SPRACT% LOOP RutiMaqData: 'Rutina en c¢digo m quina DATA b8,00,00,bb,00,00,b9,00,00,ba,00,00,cd,60,cb,90 DatoJCarJuego: 'Datos de las paredes de varias direcciones del juego "JUEGO". DATA 12,3,2,18,17,16,15,14,7,6,5,4,8,11,10,9: SUB CARGASPRITES DO INPUT "Entre el nombre del juego de sprites:"; Archiv$ IF INSTR(Archiv$, ".") > 0 THEN PRINT "Lo siento, no puede especificar una extensi¢n." ELSE EXIT DO END IF LOOP Archiv$ = LTRIM$(RTRIM$(Archiv$)) PRINT "Cargando la paleta; espere, por favor..." DIM RGB AS STRING * 3 NFILE = FREEFILE OPEN Archiv$ + "._PA" FOR BINARY AS NFILE FOR F = 0 TO 255 GET NFILE, , RGB PALETTE F, CVL(RGB + NULL) NEXT F CLOSE NFILE PRINT "Cargando los dibujos; espere, por favor..." NFILE = FREEFILE OPEN Archiv$ + "._SP" FOR BINARY AS NFILE LIMITF = UBOUND(SPRITES%) 'X = 0: Y = 0 F = 0 DO UNTIL EOF(1) GET NFILE, , SPRITES%(F) 'MK$ = MKI$(SPRITES%(F)) 'SPRITES%(F) = CVI(RIGHT$(MK$, 1) + LEFT$(MK$, 1)) IF F = LIMITF THEN EXIT DO F = F + 1 LOOP CLOSE NFILE END SUB SUB MOSTRARP (X, Y) DEF SEG = MAQSEG% 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT POKE MAQDESP% + 1, Y: POKE MAQDESP% + 2, 0 POKE MAQDESP% + 4, X: POKE MAQDESP% + 5, 0 POKE MAQDESP% + 7, SPRSEG% MOD 256 POKE MAQDESP% + 8, INT(SPRSEG% / 256) POKE MAQDESP% + 10, SPRDESP% MOD 256 POKE MAQDESP% + 11, INT(SPRDESP% / 256) 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT 'END CALL ABSOLUTE(MAQDESP%) DEF SEG END SUB SUB PONERM (X, Y, Objeto) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT SUB MEMUBIC& = MAPADESP% + (X * 256& + Y) POKE MEMUBIC&, Objeto DEF SEG END SUB SUB ReorgaMapa CLS PRINT " Petici¢n de reorganizaci¢n del mapa." PRINT PRINT " ATENCIàN: si su mapa no utiliza un jue-" PRINT " go de objetos compatible con ®JUEGO¯, " PRINT " esta opci¢n podr¡a arruinar su trabajo." PRINT INPUT "¨Proseguir?"; A$ IF A$ <> "S" AND A$ <> "s" THEN EXIT SUB RESTORE DatoJCarJuego FOR F = 0 TO 15 READ CADV CAD$ = CAD$ + CHR$(CADV) NEXT FOR FX = 0 TO 127 FOR FY = 0 TO 255 VMACT = VALORMAPA(FX, FY) 'Utilizo IF...THEN IF ... THEN IF... THEN porque suele ser 'm s r pido que AND. '1)- S¢lo se act£a sobre bloques de pared est ndar (2...18 excepto 13) IF VMACT >= 2 THEN IF VMACT <= 18 THEN IF VMACT <> 13 THEN VBL = 0 IF FX > 0 THEN VMIZQ = VALORMAPA(FX - 1, FY) ELSE VMIZQ = 0 IF FX < 127 THEN VMDCH = VALORMAPA(FX + 1, FY) ELSE VMDCH = 0 IF FY > 0 THEN VMARR = VALORMAPA(FX, FY - 1) ELSE VMARR = 0 IF FY < 255 THEN VMABA = VALORMAPA(FX, FY + 1) ELSE VMABA = 0 IF VMIZQ >= 2 THEN IF VMIZQ <= 18 THEN IF VMIZQ <> 13 THEN VBL = VBL + 1 IF VMDCH >= 2 THEN IF VMDCH <= 18 THEN IF VMDCH <> 13 THEN VBL = VBL + 2 IF VMARR >= 2 THEN IF VMARR <= 18 THEN IF VMARR <> 13 THEN VBL = VBL + 4 IF VMABA >= 2 THEN IF VMABA <= 18 THEN IF VMABA <> 13 THEN VBL = VBL + 8 PONERM FX, FY, ASC(MID$(CAD$, 1 + VBL, 1)) END IF END IF END IF NEXT LOCATE 15, 1: PRINT USING "###.## % del mapa completado."; (FX / 127) * 100 NEXT END SUB SUB SPRITEPSET2 (n%) DIM SPR%(514) N2% = n% * 512 GET (0, 0)-(31, 31), SPR%(0) FOR F = 0 TO 511 SPR%(F + 2) = SPRITES%(N2% + F) NEXT 'SPR%(0) = 32: SPR%(1) = 32 PUT (288, 0), SPR%(0), PSET END SUB FUNCTION VALORMAPA% (X, Y) DEF SEG = MAPASEG% IF X < 0 OR Y < 0 THEN BEEP: EXIT FUNCTION IF X > 127 OR Y > 255 THEN BEEP: EXIT FUNCTION MEMUBIC& = MAPADESP% + (X * 256& + Y) VALORMAPA% = PEEK(MEMUBIC&) DEF SEG END FUNCTION