Código: Seleccionar todo
dos_open equ 262
dos_close equ 265
dos_read equ 274
dos_write equ 277
dos_set1346 equ 319
inicio equ 24576
; inicio
org inicio
ld iy,tabla
; paginar DOS
ld a,(23388)
ld bc,32765
res 4,a
or 7
di
ld (23388),a
out (c),a
ei
; deshabilitar cache
ld de,0
ld hl,128
call dos_set1346
jp nc,0
; abrir fichero
ld bc,$0501
ld de,$0002 ; debería ser 3?
ld hl,fichero
call dos_open
jp nc,0
; repetir
bucle:
; leer tabla
ld a,(iy+0)
; si no he terminado de leer entonces
bit 7,a
jr nz,cerrar
; leer bloque
and 7
ld c,a
ld b,5
ld l,(iy+1)
ld h,(iy+2)
ld e,(iy+3)
ld d,(iy+4)
call dos_read
jp nc,0
; finsi
ld hl,5
push iy
pop bc
add hl,bc
push hl
pop iy
jr bucle
; fin del bucle
; cerrar fichero
cerrar:
ld b,5
call dos_close
; paginar BASIC
di
ld a,$10
ld bc,32765
ld (23388),a
out (c),a
ei
; retornar
retornar:
ld iy,23610
ret
; variables
fichero:
db 'GOKUMAL.BIN',$ff
tabla:
db 0
dw 16384
dw 6912
db 1
dw 49152
dw 14729
db 3
dw 49152
dw 14819
db 4
dw 49152
dw 14555
db 6
dw 49152
dw 9497
db 0
dw 24200
dw 35187
db $FF
Este cargador está preparado para cargar el juego "Goku Mal" y no está optimizado para que sea más claro trabajar con él. Ocupa algo más de 150 bytes y no tiene un control de errores... salvo que si algo va mal, bloquea el equipo. Supuestamente debería funcionar tanto para disquetes como para disco duro/flash.
El código viene a ser algo así:
Código: Seleccionar todo
INICIALIZAR
ABRIR FICHERO
REPETIR
LEER TABLA
SI PAGINAS>128
LEER BLOQUE
FINSI
HASTA PAGINAS>128
CERRAR FICHERO
El formato de la tabla es el siguiente:
Código: Seleccionar todo
1 byte - Flags
bit 7 - Marcador de fin
bits 2..0 - Página a colocar en $c000~$ffff
2 bytes - Dirección inicial del bloque
2 bytes - Longirud del bloque
Para generar el fichero GOKUMAL.BIN, he extraído los bloques de datos, después los he unido a lo burro con copy /b gokumal.scr+gokumal.1+gokumal.3+gokumal+4+gokumal.6+gokumal.c GOKUMAL.BIN y por último he metido ese fichero a un disquete con P3Explorer. El resultado es un fichero headerless con todos los datos del juego unidos.
He definido el primer byte como flags, de manera que (ampliando la rutina) sea posible hacer calls al cargar algunos bloques o usar bloques comprimidos.
Comentarios (y posibles mejoras/tratamiento de errores):
- La rutina paginar DOS puede comprimirse algo... dado que sabemos que vamos a la ROM2/RAM7 y que al final vamos a volver a la ROM3/RAM0, no es necesario comprobar el valor de BANKM (aunque sí que es necesario actualizarlo).
- Si la rutina deshabilitar caché falla, la página 1 se corromperá al cargar. Si no utilizamos la página 1, podemos quitarla y ahorrar 9 bytes.
- Si abrir fichero falla, es de suponer que el fichero no se ha abierto y podríamos retornar al BASIC.
- Se utiliza el fichero número 5 porque (a veces) los 3 primeros pueden estar ya abiertos.
- Si falla leer_bloque, se podría intentar saltar a cerrar fichero y retornar al BASIC.
- Estoy seguro de que se pueden optimizar todos esos (IY+x), y el código que avanza IY 5 bytes.
- Si falla cerrar fichero, la forma ideal de tratar este error es llamar a dos_abandon.
- Hubiera sido un detalle apagar la disquetera, bien usando dd_l_off_motor o con los puertos.
- Como hemos estado mangoneando con IY, hay que restaurarlo antes de volver a BASIC. Si no tenemos intención de volver a BASIC, en retornar podríamos poner el stack en su sitio y saltar con un jp.
- Tengo que averiguar si hay alguna manera de crear REMs de una longitud arbitraria (para esconder este tipo de códigos en el BASIC). Hacerlos a mano es un coñazo.
El fichero de muestra se puede descargar aquí.