===SPRGES===
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 (320x200, 256 colores, el mejor modo gráfico para juegos usando gráficos VGA estándar).
El programa estaba creado en una mezcla de [[:es:cutressembler:start|CSEMBL]] (para la parte del TSR) y basic (para el juego en cuestión).
(Puede ver los componentes Qbasic en [[es:basic:qbasic: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:
* sprges3 (TSR gestor de gráficos, 32x32 pixels, pantalla MDPA 320x200x256).
* Sprges16 (TSR gestor de gráficos, 16x16 pixels, pantalla MDPA 320x200x256).
* RMSPRG (Elimina de memoria el TSR)
* Sprges3
: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___$"
* Sprges16
;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