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). (Puede ver los componentes Qbasic en sprges)
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.
El programa se compone de 3 archivos com:
:sprgest_001 ;Parte previa. ;Carga del programa en una Int libre ;DOS get vector 60h MOV AX, 3560 INT 21 CMP BX,0 JNZ %VERR% PUSH ES POP BX CMP BX,0 JNZ %VERR% PUSH CS POP DS MOV DX,%VTSRINI% MOV AH,25 INT 21 MOV DX,%DES_INI_MAPA% ;El mapa ocupa 8000h (256x128) bytes. ;Lo ideal ser¡a que ocupase 64Kb (256x256), pero entonces no podr¡a cargarse a ;la vez que el programa (tama¤o m ximo de programa .COM=64Kb) ADD DX, 8000 PUSH DX MOV DX,%VTXTINI% MOV AH,9 INT 21 POP DX INT 27 INT 20 :VERR MOV DX, %VERRM% MOV AH,9 INT 21 INT 20 :VERRM DB "ERROR: INT 60h ESTµ SIENDO UTILIZADA POR OTRO PROGRAMA." 0D 0A DB "INSTALACIàN ABORTADA" 24 :VTXTINI DB "SPRGEST.COM (GESTOR DE MAPAS PARA EL JUEGO MOYALABE) INSTALADO" 0D 0A 24 :VTSRINI JMP %VTSRINI2% ;Lo que sigue es una cadena de identificaci¢n. DB "SPR_GEST" DW %DES_INI_MAPA% :VTSRINI2 ;SPR_GEST ;Llamada: AX=Y; BX=Y; sprites ubicados en CX:DX; INT 60 ;RUTINA PRINCIPAL PUSH DS PUSH ES PUSH AX PUSH BX PUSH CX PUSH DX ;Me aseguro de que DS y CS tengan el mismo valor. PUSH CS POP DS ;IF AX<0 CMP AX,0 JGE %SG001% XOR AX,AX ;END IF :SG001 ;IF AX>F9 CMP AX,F9 JLE %SG002% MOV AX,F9 ;END IF :SG002 ;IF BX<0 CMP BX,0 JGE %SG003% XOR BX,BX ;END IF :SG003 ;IF BX>77 CMP BX,77 JLE %SG004% MOV BX,77 ;END IF :SG004 PUSH AX PUSH BX XOR BH,BH :BUCLE1 ; XOR BH,BH CAMBIADO A MµS ARRIBA XOR AH,AH INC BL ;La siguiente l¡nea evita que AL crezca sin parar. PUSH AX :BUCLE2 ; XOR AH,AH CAMBIADO A MµS ARRIBA ;Las dos l¡neas siguientes las cambio para ;evitar efectos indeseados: ;ADD AL,AH ;ADD BL,BH INC AL PUSH AX PUSH BX MOV [%PONERV1%],AH MOV [%PONERV2%],BH XOR AH,AH XOR BH,BH CALL %PONER% POP BX POP AX INC AH CMP AH,6 JL %BUCLE2% POP AX INC BH CMP BH,8 JL %BUCLE1% POP BX POP AX ;DEVUELVO LOS VALORES INICIALES A TODOS LOS REGISTROS ;QUE PUEDAN HABER CAMBIADO: POP DX POP CX POP BX POP AX POP ES POP DS IRET :PONER ;XMAPA,YMAPA=BL,AL ;XPANT,YPANT=[PONERV2],[PONERV1] PUSH AX PUSH BX PUSH CX PUSH DX PUSH DS PUSH ES PUSH CX POP ES MOV CL,8 XCHG AX,BX ;Me gusta m s SHL que MUL SHL AX,CL ;Lo que hemos hecho ha sido multiplicar por ;256 el valor de AL y a¤adirlo a BX. ADD BX,AX ADD BX,%DES_INI_MAPA% ;Ponemos en AX el n£mero de SPRITE: MOV AL,[BX] MOV AH,0 ;multiplicamos AX por 64 (Seg*64=DESP*(32*32)) MOV CL,6 ;AQUÖ PONÖA "SHR..." SHL AX,CL PUSH ES POP CX ADD AX,CX PUSH AX POP ES ;Lo que hemos hecho es cambiar el segmento y no el desplazamiento. ;Esto se debe a que los sprites variable que vamos a utilizar ocupan ;m s de 64Kb. ;Los sprites se cargar n desde un programa BASIC. XOR AX,AX XOR BX,BX MOV AX, [%PONERV2%] MOV BX, [%PONERV1%] ;ESTO ESTABA MAL: ;;Cambio CL de 5 a 4 (2^4=32) ;2^5=32 MOV CL,5 SHL AX,CL XCHG AX,BX SHL AX,CL XCHG BX,DX ;AX: Y_COORD (PONERV1) ;DX: X_COORD (PONERV2) MOV CX,140 ;Multiplica AX por CX: ;140h= 20*16=320 ;MUL cambia el valor de DX PUSH DX MUL CX POP DX ;FIN_BLOQUE... ;;La coord. inicial del sprite es B800:(AX+DX) ;LA COORDENADA INICIAL ES A000:(AX+DX) PUSH AX ;MOV AX,B800 MOV AX,A000 PUSH AX POP DS POP AX ADD DX,AX MOV CX,DX ;(DS:CX) XOR DX,DX :BUC3 XOR AX,AX :BUC4 ES: MOV AH,[BX] XCHG BX,CX MOV [BX],AH XCHG BX,CX INC CX INC BX INC AL CMP AL,20 JL %BUC4% INC DL ADD CX,120 ;120=140h-20h=320-32 CMP DL,20 JL %BUC3% POP ES POP DS POP DX POP CX POP BX POP AX RET :PONERV1 DW 0 :PONERV2 DW 0 :DES_INI_MAPA dB "MAPA___$MAPA___$MAPA___$MAPA___$" dB "[ MAZE MAP INFORMATION ]" DB "[INFORMACIàN DE MAPEADO] dB "MAPA___$MAPA___$MAPA___$MAPA___$"
;SPRGESTV.2 16x16 :sprgest_001 ;Parte previa. ;Carga del programa en una Int libre MOV DX,%VTXTPRES% MOV AH,9 INT 21 ;DOS get vector 60h MOV AX, 3560 INT 21 CMP BX,0 JNZ %VERR% PUSH ES POP BX CMP BX,0 JNZ %VERR% PUSH CS POP DS MOV DX,%VTSRINI% MOV AH,25 INT 21 MOV DX,%DES_INI_MAPA% ;El mapa ocupa 8000h (256x128) bytes. ;Lo ideal ser¡a que ocupase 64Kb (256x256), pero entonces no podr¡a cargarse a ;la vez que el programa (tama¤o m ximo de programa .COM=64Kb) ADD DX, 8000 PUSH DX MOV DX,%VTXTINI% MOV AH,9 INT 21 POP DX INT 27 INT 20 :VERR MOV DX, %VERRM% MOV AH,9 INT 21 INT 20 :VTXTPRES DB "SPRGE16.COM V.2/16 Gestor sprites 16x16 modo 13h." :VERRM DB "ERROR: INT 60h ESTµ SIENDO UTILIZADA POR OTRO PROGRAMA." 0D 0A DB "INSTALACIàN ABORTADA" 24 :VTXTINI DB "SPRGE16.COM instalado. / 33 Kilobytes reservados." 0D 0A 24 :VTSRINI JMP %VTSRINI2% ;Lo que sigue es una cadena de identificaci¢n. DB "SPRGE16" DW %DES_INI_MAPA% :VTSRINI2 ;SPR_GEST_V2._16x16 ;Llamada: AX=Y; BX=Y; sprites ubicados en CX:DX; INT 60 ;RUTINA PRINCIPAL PUSH DS PUSH ES PUSH AX PUSH BX PUSH CX PUSH DX ;Me aseguro de que DS y CS tengan el mismo valor. PUSH CS POP DS ;IF AX<0 CMP AX,0 JGE %SG001% XOR AX,AX ;END IF :SG001 ;IF AX>79 CMP AX,79 JLE %SG002% MOV AX,79 ;END IF :SG002 ;IF BX<0 CMP BX,0 JGE %SG003% XOR BX,BX ;END IF :SG003 ;IF BX>F7 CMP BX,F7 JLE %SG004% MOV BX,F7 ;END IF :SG004 PUSH AX PUSH BX XOR BH,BH :BUCLE1 ; XOR BH,BH CAMBIADO A MµS ARRIBA XOR AH,AH :BUCLE2 ; XOR AH,AH CAMBIADO A MµS ARRIBA ADD AL,AH ADD BL,BH PUSH AX PUSH BX MOV [%PONERV1%],AH MOV [%PONERV2%],BH XOR AH,AH XOR BH,BH CALL %PONER% POP BX POP AX INC AH CMP AH,C JL %BUCLE2% INC BH CMP BH,10 JL %BUCLE1% POP BX POP AX ;DEVUELVO LOS VALORES INICIALES A TODOS LOS REGISTROS ;QUE PUEDAN HABER CAMBIADO: POP DX POP CX POP BX POP AX POP ES POP DS IRET :PONER ;XMAPA,YMAPA=BL,AL ;XPANT,YPANT=[PONERV2],[PONERV1] PUSH AX PUSH BX PUSH CX PUSH DX PUSH DS PUSH ES PUSH CX POP ES MOV CL,8 XCHG AX,BX ;Me gusta m s SHL que MUL SHL AX,CL ;Lo que hemos hecho ha sido multiplicar por ;256 el valor de AL y a¤adirlo a BX. ADD BX,AX ADD BX,[%DES_INI_MAPA%] ;No me f¡o de la siguente l¡nea: ;MOV BX,[BX] (la quito) ;AX ya se ha corrido 8 veces a la izq. ;Es decir, ya se ha multiplicado por 16 PUSH ES POP CX ADD AX,CX PUSH AX POP ES ;Lo que hemos hecho es cambiar el segmento y no el desplazamiento. ;Esto se debe a que los sprites variable que vamos a utilizar ocupan ;m s de 64Kb. ;Los sprites se cargar n desde un programa BASIC. XOR AX,AX XOR BX,BX MOV AL, [%PONERV2%] MOV BL, [%PONERV1%] 'Cambio CL de 5 a 4 (2^4=32) MOV CL,4 SHL AX,CL XCHG AX,BX SHL AX,CL XCHG BX,DX ;AX: Y_COORD ;DX: X_COORD MOV CX,140 ;Multiplica AX por CX: MUL CX ;FIN_BLOQUE... ;;La coord. inicial del sprite es B800:(AX+DX) ;LA COORDENADA INICIAL ES A000:(AX+DX) PUSH AX ;MOV AX,B800 MOV AX,A000 PUSH AX POP DS POP AX ADD DX,AX MOV CX,DX ;(DS:CX) XOR DX,DX :BUC3 XOR AX,AX :BUC4 ES: MOV AH,[BX] XCHG BX,CX MOV [BX],AH XCHG BX,CX INC CX INC BX INC AL CMP AL,10 JLE %BUC4% INC DL ADD CX,12F ;130=140h-20h=320-16 CMP DL,10 JL %BUC3% POP ES POP DS POP DX POP CX POP BX POP AX RET :PONERV1 DW 0 :PONERV2 DW 0 :DES_INI_MAPA dB "MAPA___$MAPA___$MAPA___$MAPA___$" dB "[ MAZE MAP INFORMATION ]" DB "[INFORMACIàN DE MAPEADO] dB "MAPA___$MAPA___$MAPA___$MAPA___$"
* RMSPRG