Página 1 de 2

Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 1:54 pm
por opqa
Pongo esto aquí porque me parece interesante y porque no lo he visto en ningún otro sitio.

Cuando se programa cualquier cosa de cierta envergadura para el Amstrad lo habitual es "cargarse" el firmware y usar funciones dedicadas para escribir en pantalla, leer el teclado, manejar las interrupciones (o simplemente ignorarlas), etc. Estas funciones son menos versátiles que las del firmware, pero normalmente mucho más rápidas.

El problema viene cuando queremos hacer un juego "multicarga", o un programa que acceda a disco para cargar datos de vez en cuando. Las funciones de acceso a disco son más complejas que las habituales de escritura en pantalla y lectura de teclado. Se puede hacer y de hecho grandes juegos como el ORION Prime lo hacen (y de paso usan formatos de disco personalizados que aprovechan más el espacio del mismo).
Pero no siempre vamos a tener el tiempo y las ganas de hacer esto con nuestros juegos. Lo más cómodo en estos casos es "tirar de firmware" para cargar archivos "normales" en memoria, pero... ¿Es posible hacer esto si nos lo hemos "cargado" previamente?

Bueno, pues la respuesta es que sí, se puede, es algo "complejo", pero no mucho, y lo más importante, ahorra bastante espacio en RAM puesto que no tenemos que reservar espacio para rutinas de lectura de disco. A continuación adjunto un código muy comentado (hay mucho más texto que código), de un programa que simplemente se "carga" el firmware de la forma habitual, para a continuación restaurarlo y usarlo para cargar una imagen en la memoria de video. Se puede tomar como plantilla de referencia para usar en cualquier desarollo.

Espero que sea de vuestro interés.

Edito: Lo resubo con algunos cambios y correcciones en los comentarios

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 6:12 pm
por gg
Yo solo he hecho uso de lo que comentas una vez y debo admitir que intenté repetirlo años después y ya no me acordaba.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 6:19 pm
por gg
Ahora, al verlo todo tan bien explicadito y en español, diría que la segunda vez me salté pasos. Me lo apunto y ya lo probaré.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 6:24 pm
por opqa
¿y donde esta explicado esto en inglés? Porque mira que lo he buscado, y lo único que he visto es cómo hacer para restaurar el AMSDOS nada más empezar el programa. Pero claro, no es lo mismo, porque en esos ejemplos todo el jumpblock sigue en su sitio, no es necesario empezar de 0.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 6:41 pm
por gg
No me hagas mucho caso porque fue hace tiempo, pero creo que fue en cpcwiki. De todas formas, creo que no estaba tan completo o, al menos, yo no lo veía así de claro.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 10 Oct , 2014 11:37 pm
por opqa
En realidad aun no lo he probado en funcionamiento real, me acabo de dar cuenta de que es muy posible que me haya dejado algo importante. Antes de activar las interrupciones del firmware tiene pinta de que sea necesario invocar la función KL CHOKE OFF (&BCC8), que borra cierta área de memoria que usan las interrupciones para ejecutar eventos programados por el usuario.

En el ejemplo adjuntado no sería necesario porque previamente he borrado todo ese banco de memoria, pero en un caso real en el que tengamos datos obsoletos en esa zona de memoria podría llevar a un cuelgue activar las interrupciones sin haberla borrado previamente.

Los cambios en el código serían de esto:

Código: Seleccionar todo

; Ahora que ya esta copiada la invocamos, pero antes
; hay que desactivar las interrupciones, puesto que tambien
; restaura la rutina de interrupciones del firmware
di
call &4000 ; JUMP_RESTORE

; Antes de volver a activar las interrupciones del fimware
; hay que tener una precaucion, hay que fijar la pareja de
; registros BC del set de registros alterno para que coincida
; con el estado actual del modo grafico (0,1 o 2) y las ROMS
; (desactivadas ambas)
exx
ld bc, &7f8c OR MODE
exx

; Activamos las interrupciones, ahora el firmware vuelve a tener
; el control de la maquina
ei

; Ahora hay que restarurar el KERNEL jumpblock, para ello usamos
; una funcion del propio firmware cuya direccion hemos guardado
; al principio, esta ya se puede ejecutar desde cualquier sitio
; porque ahora seran las funciones del HIGH jumpblock las que se
; encargaran de activar/desactivar la LOWER ROM cuando sea necesario
call firmware_JUMP_RESTORE
...
a esto:

Código: Seleccionar todo

; Ahora que ya esta copiada la invocamos, pero antes
; hay que desactivar las interrupciones, puesto que tambien
; restaura la rutina de interrupciones del firmware
di
call &4000 ; JUMP_RESTORE

; Antes de volver a activar las interrupciones del fimware
; hay que tener una precaucion, hay que fijar la pareja de
; registros BC del set de registros alterno para que coincida
; con el estado actual del modo grafico (0,1 o 2) y las ROMS
; (desactivadas ambas)
exx
ld bc, &7f8c OR MODE
exx

; Ahora hay que restarurar el KERNEL jumpblock, para ello usamos
; una funcion del propio firmware cuya direccion hemos guardado
; al principio, esta ya se puede ejecutar desde cualquier sitio
; porque ahora seran las funciones del HIGH jumpblock las que se
; encargaran de activar/desactivar la LOWER ROM cuando sea necesario
call firmware_JUMP_RESTORE

; Borramos la cola de eventos y lista de temporizadores del firmware
call &bcc8 ; KL CHOKE OFF

; Activamos las interrupciones, ahora el firmware vuelve a tener
; el control de la maquina
ei
Lo probaré en "acción" y si veo que funciona actualizaré el .zip

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Sab 11 Oct , 2014 9:35 am
por opqa
Mmmm, pues me acabo de dar cuenta de que la "solución" (todavía no se si es realmente un problema) tampoco es buena, la llamada a JUMP RESTORE vuelve con las interrupciones activadas y antes no podemos llamar a KL CHOKE OFF. Creo que lo mejor para curarse en salud es borrar antes de empezar esa zona de memoria "a mano" (son sólo 2KBs), quedaría así:

Código: Seleccionar todo

; Borramos la zona de memoria que contiene (entre otras cosas)
; la cola de eventos y lista de temporizadores del firmware,
; por si acaso hay algo que pueda colgar la maquina cuando activemos
; sus interrupciones

ld hl,&b100
ld de,&b101
ld bc,&07ff
ld (hl),a
ldir

; Ahora que ya esta copiada la invocamos, pero antes
; hay que desactivar las interrupciones, puesto que tambien
; restaura la rutina de interrupciones del firmware
di
call &4000 ; JUMP_RESTORE

; Antes de volver a activar las interrupciones del fimware
; hay que tener una precaucion, hay que fijar la pareja de
; registros BC del set de registros alterno para que coincida
; con el estado actual del modo grafico (0,1 o 2) y las ROMS
; (desactivadas ambas)
exx
ld bc, &7f8c OR MODE
exx

; Activamos las interrupciones, ahora el firmware vuelve a tener
; el control de la maquina
ei

; Ahora hay que restarurar el KERNEL jumpblock, para ello usamos
; una funcion del propio firmware cuya direccion hemos guardado
; al principio, esta ya se puede ejecutar desde cualquier sitio
; porque ahora seran las funciones del HIGH jumpblock las que se
; encargaran de activar/desactivar la LOWER ROM cuando sea necesario
call firmware_JUMP_RESTORE

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Jue 05 Mar , 2015 5:29 pm
por KaosOverride
Una puntualizacion que igual os ayuda un poco, de mi experiencia usando AMSDOS en Marron en la Euskal, ya que la intro, juego y final se cargan con llamada a Amsdos.

Como decis, al deshabilitar el firmware no tenemos ni firmware base ni Amsdos, pero al restaurar la tabla de interrupciones recuperamos el firmware y el Amsdos. La historia esta en cargar el codigo con un LOAD" y CALL desde un basic, o en hacer un RUN" al binario.

Si haces LOAD"" y CALL, desactivas el firmware parcheando el vector de interrupcion, y al restaurarlo sigues con AMSDOS, bien...

Si haces RUN"" a pelo, se carga el codigo, y antes de llamar a la direccion de ejecucion de la cabecera amsdos, se pega una limpia de las ROM extendidas (Incluida AMSDOS) y cualquier llamada a las funciones de fichero deriba a un intento de carga desde CASSETTE ya que solo el firmware base esta disponible.

Aun asi, el firmware base del CPC dispone de llamadas con las que poder re-inicializar el Amsdos o lo que querramos necesitar.

El problema es que en el RUN" corremos el riesgo casi seguro de que se pierda el valor de AMSDOS de si estamos en B: o A: asi que es un tema a controlar antes de inicializar las ROM extendidas...

Creo que era por esto que muchos cracks como los de XOR solo van en la unidad A:, y habria que reescribirlos para que sean mas amistosos conservando el valor de la unidad en uso, llamandolos desde un BASIC y agregando al codigo original un chequeo de la variable antes de reinicializar AMSDOS...

No se si os valdra de algo, es lo que me encontre yo en su momento :)

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 06 Mar , 2015 9:40 am
por Mode 2
Muy interesante este hilo y posiblemente necesario para uno de los juegos en los que estoy. Gracias.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 06 Mar , 2015 9:46 am
por Artaburu
Muy interesante este hilo y posiblemente necesario para uno de los juegos en los que estoy. Gracias.
:mrgreen:

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Vie 06 Mar , 2015 10:41 pm
por KaosOverride
De todas formas, a ver si lo subo al hilo de Basic y otros lenguajes, o lo tenia ya subido..., un crt0 para sdcc que permite cargar muy bajito (0x140 o 0x200) mediante RUN"", no reinicializar AMSDOS y volver al basic. Realmente es un minibasic+bin, al estilo de los compactados de cngsoft, que con el Run"" carga el bin y el minibasic, que es solo un call al inicio de ejecucion del codigo bin. Seguro lo adaptais facil de asm de sdcc a vuestros proyectos puramente en asm.

Lo unico te obliga a ubicar el codigo desde 0x140 (o 0x200, no recuerdo bien) pero no destroza a AMSDOS, puedes controlar en las variables del firmware la unidad activa, y guarrear con AMSDOS sin perder la unidad actual.

Ahh, otra cosa, las Rom inicializalas a tintas todas a cero, que Parados, Maxam etc muestran texto...

Edit: aqui esta www.amstrad.es/forum/viewtopic.php?p=46916#p46916

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Lun 09 Mar , 2015 3:15 pm
por pacomix
Una preguntilla... ¿cuál es la razón de regresar al basic o reponer el firmware? ¿usar el acceso a disco? Si es así hay una rutina que ocupa creo que unos 512 bytes (o 300 y pico si no recuerdo mal) que carga ficheros con cabeceras amsdos.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Lun 09 Mar , 2015 3:39 pm
por KaosOverride
Yo entiendo que lo interesante de mantener el firmware + Roms auxiliares en uso, es el poder acceder a ficheros no solo en la unidad A: o B:, sino en futuros roms que soporten unidades C:, D:, hasta d3 red, etc... Y soportar otros sistemas de archivos como Fat, etc. Sino estamos cayendo en el problema de solo cargar de data, system, ibm y de A y B, y ahi quedarse...

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Dom 01 Ene , 2023 8:42 pm
por dragon131
Pues yo sí muero en el intento. Supongamos que tienes un juego petado desde 0000 hasta cfff.

¿Que zonas de memoria ram hay que salvar antes de que el firmware las sobreescriba.?.
Una preguntilla... ¿cuál es la razón de regresar al basic o reponer el firmware? ¿usar el acceso a disco? Si es así hay una rutina que ocupa creo que unos 512 bytes (o 300 y pico si no recuerdo mal) que carga ficheros con cabeceras amsdos.
Esa subrutina donde está?.

Re: Cómo restaurar el firmware (y no morir en el intento)

Publicado: Sab 18 Mar , 2023 9:56 pm
por pacomix
Pues yo sí muero en el intento. Supongamos que tienes un juego petado desde 0000 hasta cfff.

¿Que zonas de memoria ram hay que salvar antes de que el firmware las sobreescriba.?.
Una preguntilla... ¿cuál es la razón de regresar al basic o reponer el firmware? ¿usar el acceso a disco? Si es así hay una rutina que ocupa creo que unos 512 bytes (o 300 y pico si no recuerdo mal) que carga ficheros con cabeceras amsdos.
Esa subrutina donde está?.
Lo acabo de mirar. Ocupa 797 bytes y requiere un buffer de 384 bytes (en pantalla mismo si es entre cargas). La tengo adaptada para que se compile como una funci'on de C y ser compilada con el SDCC. Si te interesa te la paso.