Buenas, un poco de literatura!!!
Pues como he conseguido meter dos programas con el arranque en $0801 en el mismo PRG?
Bien, analizando la cinta con el FinalTAP podemos extraer facilmente los datos que se componen de...
Dos partes:
- Las intrucciones en castellano: Que se componen de una parte en BASIC con los textos. Y una parte en codigo máquina que es el cambio de las fuentes. Osea, dos partes.
- El juego propiamente dicho, que no está traducido. Es decir, el original en ingles.
Los dos programas se inician en $0801, por lo que no pueden convivir en memoria a no ser que se adapten.
Pero antes... tenemos las instrucciones en BASIC y vamos a hablar de ellas.
Las instrucciones disponen de una parte en codigo máquina, que es el cambio de texto. Y del arranque de la cinta cuando ya hemos leido las instrucciones y carga el juego en cinta.
Como ya no cargamos el juego en cinta, sino de la memoria, pues nos cargamos esa linea por un END (por el momento)
Ponemos...
60 END y listo. Se para el programa.
Pero... al haber modificado el programa en BASIC, se ha corrido la memoria del CM y ahora los caracteres redefinidos se convierten en basura.
Así que... vuelvo a cargar el programa original y me fijo donde acaba el programa en BASIC y donde empieza el CM.
Se suele saber donde acaba el programa en BASIC porque se puede observar en el visor hexadecimal los valores $00 $00.
Esto lo miro rapidamente con el DirMaster, que permite ver los archivos rapidamente.
Entonces, ya desde el VICE y conociendo cual es la parte en código máquina, la grabo a disco como INTROASM. Me lo graba desde una dirección de memoria que siempre dependerá de la longitud del programa BASIC. No todos los cargadores BASIC contiene el mismo número de caracteres, por lo que me lo voy a encontrar diferente en cada juego.
Por otro lado, grabo el cargador en BASIC modificado en la linea 60. (No va a ser la ultima modificación).
EL final de un programa en BASIC es...
10DB 8E 00 00 STX $0000
10DE 00 BRK
$8E es el token en BASIC del commando RETURN, no de la Tecla RETURN.
$00 que es el RETURN final de linea.
$00 $00 que es el final del programa en BASIC.
Por lo que al final de programa BASIC tendremos tres ceros: $00 $00 $00.
Estos hay que copiarlos cuando se modifica el programa en BASIC, o dejar que lo haga el propio ordenador.
En el BLAGGER, el ultimo cero está en $10DE. Y ahí empiezan los datos de los caracteres redefinidos hasta el ....
27FE 20 FF FF JSR $FFFF
Este es el final del bloque del cargador BASIC
Curiosamente, practicamente todos los cargadores de POKE S.A. tienen los caracteres redefinidos cargados en la misma posición de memoria, por lo que se pueden reciclar para otros juegos cuando se modifica la parte BASIC del cargador.
Me guardo estos dos programas. INTROBAS.PRG y INTROASM.PRG
Ahora el juego
Viendo el volcado realizado de la cinta, tenemos el juego, pero claro... no puede convivir con las intrucciones en castellano. Por lo que toca moverlo de sitio. El problema, es que para moverlo, es demasiado grande, así que...
Sacando el arranque del juego del cargador de la cinta, lo comprimo con el Exomizer, dejando un ejecutable mucho mas pequeño. Le hacemos una descompresión con colorinos, que me gusta más.
ACTUALIZACION: Realizo el volcado del juego cargandolo en cinta y parando el VICE metiendo la dorección de arranque... Le meto un blucle en $0400...
0400 JMP $0400
y G $0400
Y ahora podemos hacer un Frezee... entramos en el Monitor... cambiamos el JMP $0400 por JMP $Arranque del juego...
Le metemos desconectar la pantalla antes... que no me acordaba...
Salimos del monitor y hacemos el volcado con el AR a disco. Luego lo comprimimos con el EXOMIZER con colorines.
lo llamaremos JUEGOEX.PRG
Vale... ahora hay que meterlo en memoria. Pero quiero meterlo en memoria por encima del programa BASIC. Y cuando acabe de ejecutarse el programa BASIC, el JUEGO se colocará en la posición de memoria que le toca y se ejecutará.
El programa INTRO ocupa hasta la posición...$27E0 (aproximando) Con las dos partes, BASIC y ASM
Y el JUEGOEX.PRG, lo cargaremos con el... ya no me acuerdo, si con el VICE o con el ACTION REPLAY
VICE:
L "JUEGOEX" 8 4000
o desde AR:
L "JUEGOEX",8,4000
Bien, ahora queremos mover ese juego que lo hemos cargado en $4000 y bajarlo a $0801 para poder ejecutarlo en su sitio natural. (Sobreescribiendo lo que hubiera ahí)
Pues bien, ahí entra una pequeña rutina para mover bloques grandes que me he currado, que lo que hace es precisamente eso, MOVER MEMORIA.
Pero la gracia es... ¿Donde meto esta rutina? Pues la meto en la posición de memoria $02A7, que hay unos 87 bytes libres que me permitirán meter la pequeña rutina.
Es esta:
* = $02A7 ; Definir las direcciones y el tamaño del bloque
; Direcciones de origen y destino
FROM = $4000 ; Dirección de inicio del bloque fuente
TO = $0801 ; Dirección de inicio del bloque destino
SIZEH = $36 ; Parte alta de $3600 (13824 bytes)
SIZEL = $00 ; Parte baja de $3600 (13824 bytes)
FROMPTR = $FB ; Puntero al origen (en página cero)
TOPTR = $FD ; Puntero al destino (en página cero)
LDA $D011 ; Vamos a desconectar la pantalla
AND #$EF ; Ponemos el bit 5 a cero
STA $D011 ; Y dejamos el valor en la direccion
LDY #$00 ; Inicializar el índice Y a 0
LDA #<FROM ; Cargar parte baja de la dirección origen
STA FROMPTR ; Guardar en el puntero de origen
LDA #>FROM ; Cargar parte alta de la dirección origen
STA FROMPTR+1 ; Guardar en el puntero de origen + 1
LDA #<TO ; Cargar parte baja de la dirección destino
STA TOPTR ; Guardar en el puntero de destino
LDA #>TO ; Cargar parte alta de la dirección destino
STA TOPTR+1 ; Guardar en el puntero de destino
LDX SIZEH ; Cargar la parte alta del tamaño en X
BEQ REMAINING ; Si no hay páginas completas, saltar a los bytes restantes
PAGE_LOOP:
LDA (FROMPTR),Y ; Cargar un byte de la dirección origen
STA (TOPTR),Y ; Guardar el byte en la dirección destino
INY ; Incrementar el índice Y
BNE PAGE_LOOP ; Si no hay desbordamiento, continuar
INC FROMPTR+1 ; Incrementar la parte alta de la dirección origen
INC TOPTR+1 ; Incrementar la parte alta de la dirección destino
DEX ; Decrementar el contador de páginas
BNE PAGE_LOOP ; Continuar mientras X no sea 0
REMAINING:
LDX SIZEL ; Cargar la parte baja del tamaño en X
BEQ DONE ; Si no hay bytes restantes, terminar
BYTE_LOOP:
LDA (FROMPTR),Y ; Cargar un byte de la dirección origen
STA (TOPTR),Y ; Guardar el byte en la dirección destino
INY ; Incrementar el índice Y
DEX ; Decrementar el contador de bytes restantes
BNE BYTE_LOOP ; Continuar mientras X no sea 0
DONE:
LDA $D011 ; Restablecemos pantalla
ORA #$10
STA $D011
JMP $080D ; Regresar al inicio del programa Exomizer
Esta rutina se llama desde el cargador de instrucciones en BASIC,
Ahora es cuando cambiamos la linea 60 END y ponermos 60 SYS 679 ($02A7)
Está compilada con el compilador de ASM del C64Studio.
Para evitar gliches durante el movimiento de memoria, apagamos la pantalla, movemos todo el bloque de memoria del juego. (En el propio codigo fuente viene la dirección origen ($4000), destino ($0801) y tamaño del bloque (Depende del tamaño del juego y ese dato nos lo da el VICE o el AR cuando carga el juego en memoria)
Vale, pues juntamos todos estos trozos en memoria. El BASIC se carga normal. EL INTROASM y el JUEGOEX lo cargamos desde el VICE. Y el MOVEDOR de memoria, también desde el VICE.
Ahora todo tiene un orden...
INTROBAS.. INTROASM... llamamos am MOVER MEMORIA... MUEVE el juego de $4000 a $0801... y hacemos un SYS al arranque del JUEGO, pero no es el arranque REAL. Porque el arranque REAL se lo dimos al EXOMIZER. Lo que hacemos es mandar arranque a DESCOMPRIMIR en MEMORIA con un SYS 2061 ($080D)
Ahora tenemos que meter todo en un unico bloque.
Ahora es cuando entra en funcionamiento el Action Replay. Tenemos que hacer un Snapshot de la memoria con todas estas piezas.
Pero... un Snapshot durante una ejecución, llena el arranque de basura. Por lo que tenemos que capturar la memoria y arrancar después de restaurar.
Un truco (Que me estoy durmiendo)
Borro la pantalla a negro: POKE 53280,0:POKE 53281,0...
Ponemos cursor en negro... CTRL-1.
Y un CLEAR/HOME.
Tenemos pantalla en negro... y todo preparado para arrancar. Asi que pulsamos el botón mágico y entramos en el Action REPLAY... que Guay!
Pero antes de hacer un BackUp... entramos en el MONITOR de Codigo Maquina.
Y vamos a aprovechar una pequeña jugarreta que aprendí cuando estaba crackeando los juegos de IDEALOGIC.
Escribir en el BUFER de teclado y realizar la captura de memoria.
Nos vamos a la posición $0277 y escribimos la siguiente secuencia:
$52 $55 $4e $0d
Que significa RUN (Return)
Y activamos la longitud del BUFFER de teclado en la posición $00C6 y ponemos el valor $04. (Longitud 4)
Vale! Ya está todo listo para hacer el BackUp. Pulsamos F1... y hacemos el BackUp con la letra C para guardar en modo Standard.
Vale! Ya lo tenemos todo guardado en un único bloque PRG.
Pero... un BackUp de Action Replay no es autoejecutable. Necesitamos que se descomprima automaticamente.
Esto lo hacemos nuevamente con el Exomizer. Hacemos una compresión con arranque en basic.
exomizer sfx basic -n prueba.prg -o juegoex.prg
Y ya tenemos todo autoarrancable.
Descomprime AR... se ejecuta... se activa el bufer de teclado y hace run... se ejecuta la intro de instrucciones en basic... cuando damos a no leer las instrucciones se llama al programa de movimiento de memoria... al terminar de moverse se llama al juego en su posición original... se descomprime en memoria... y a jugar!!!!
Y continuando con otros juegos... Son of Blagger, GUARDIAN y EAGLE, el copiador de memoria lo metí en la memoria $8000, así que tuve que compilarlo de nuevo.
Del LOADER, con textos diferentes, el ASM siempre ha permanecido en la misma dirección. Menos trabajo.
Los juegos, los he subido de la colección ONELOAD a la zona $4000.
Y mi movedor... lo he subido de la $02a7 a la zona $8000.
Se llama con un SYS 32768
Y toda la memoria se graba a disco mediante el Action Replay con el comando S "JUEGOMEM",8,0801,8050
(Tambien se puede gramar a memoria con el VICE)
La compresión con el Exomizer...
exomizer sfx basic -n juegomem.prg -o juego-ex.prg
Y listo!!! Ya está realizado sin nesidad de ACTION REPLAY ni llenar el BUFER del teclado de RUNs ni nada de eso.
Si hubiera empezado por poner el programa arriba de la memoria... me hubiera ahorrado algunos pasos.
En el 3D WATER SKI, resulta que si se dejan textos en pantalla, como el arranque del Commodore, luego aparecen en la pantalla de inicio del juego. No se hace un Clear Screen correcto, por lo que antes de lanzar el juego, hacemos una llamada a una rutina del Kernel para borrar pantalla. Luego, lo lanzamos.
Una rutina para borrar la pantalla:
JSR $E544 (Del Kernel)
Y luego podemos arancar el juego.
Bueno, es un poco lío lo escrito porque he aprovechado pare mezclar otros juegos y a medida que va evolucionando el comentario, se va simplificando el procedimiento.
Quedaros son el prodedimiento de meter la rutina de mover memoria en el $8000 y así solo volcando la memoria desde $0801 a $8050 y comprimiento con Exomizer (o el que mas rabia de) y ejecutando el programa BASIC, funcionaría el juego.