Hola de nuevo:
En primer lugar @BlackHole, agradecerte una vez más tu ayuda y tu trabajo.

Esta información creo que ya la había puesto en algún otro Post pero por si acaso te sirve de algo lo vuelvo a poner aquí (que más vale que sobre que no que falte)

Así pues tenemos que en
MSX hay 3 tipos de Carga/Grabación desde/en Cassette:
-CLOAD/CSAVE.
-LOAD/SAVE.
-BLOAD/BSAVE.Hay 2 velocidades diferentes para grabar nuestros Programas:
- 1200 baudios.
- 2400 baudios.Cada Byte se graba siempre añadiendo un bit por la Izquierda (un 0) que indica el comienzo, luego iría el Byte propiamente dicho, y al final se añaden dos bits (dos CEROS) que indican el final del Byte.
Los Ficheros-Programas para grabarse en Cinta se graban en 2 Bloques:
- Un primer Bloque (
Descriptor de Fichero) que nos indica el tipo de Fichero.
- Un segundo Bloque que contiene los
Datos propiamente dichos.
Cada Tipo de Fichero (CLOAD, LOAD, BLOAD) tiene sus peculiaridades:
1. Ficheros
CLOAD --> (BASIC)
■ Descriptor de Fichero, formado por:
-Cabecera Larga.
-10 bytes con el valor "D3" (el valor "D3" nos indica que es un Fichero CLOAD)
-6 bytes que contienen el nombre del Fichero.
■ Datos propiamente dichos del Fichero, formados por:
-Cabecera Corta
-Caracteres del Programa BASIC "Tokenizados"
-7 bytes con el valor "00" que indican el final del Fichero.
2.Ficheros
LOAD/OPEN --> (ASCII)
■ Descriptor de Fichero, formado por:
-Cabecera Larga
-10 bytes con el valor "EA" (ese valor "EA" nos indica que es un fichero de tipo LOAD/OPEN)
-6 bytes con el nombre del Fichero.
■ Datos propiamente dichos del Fichero, formados por:
-Cabecera Corta.
-Bloque de 256 bytes
-Cabecera Corta.
-Bloque de 256 bytes
-Cabecera Corta.
-Bloque de 256 bytes
..........................
..........................
-Cabecera Corta.
-Un último Bloque que contiene 256 bytes con el valor "1A" (ese valor "1A" indica el final del Fichero)
3.Ficheros
BLOAD --> Código Máquina:
■ Descriptor de Fichero, formado por:
-Cabecera Larga.
-10 bytes que contienen el valor "D0" (este valor "D0" nos indica que es un Fichero de Tipo BLOAD)
-6 bytes con el nombre del Fichero.
■ Datos propiamentes dichos del Fichero, formados por:
-2 bytes, que contienen la Dirección de Inicio.
-2 bytes, que contienen la Dirección Final.
-2 bytes, que contienen la Dirección de Ejecución.
-El Volcado de los Datos del Programa que están en memoria.
-La Instrucción
TAPION (Dir.
&H00E1), hace un "Motor On" y lee una Cabecera del Cassette (tanto larga como corta).
-La Instrucción
TAPIN (Dir.
&H00E4), lee solamente un Byte del Cassette.
-La Instrucción
TAPIOF (Dir.
&H00E7), pone fin a la Lectura desde el Cassette.
Pongo aquí también, por si sirve de algo, un Programa en Ensamblador que teóricamente reconoce e identifica cada tipo de Carga. Según el Autor, este Programa ".Asm" parece funcionar con los bloques "
Bsave" y "
Csave" pero, curiosamente, aunque carga los bloques "
Save" el código no aparece "tokenizado" en el debugger, de forma que no se puede Listar.
Código: Seleccionar todo
CSAVE_FILE equ 0xD3 ; eof = n data hasta 7bytes 0x0
SAVE_FILE equ 0xEA ; eof = n bloques 256 bytes hasta CTRL+Z
BSAVE_FILE equ 0xD0
INI_BASIC equ 0x8001 ; lol!
INI_PRG equ 0xF000
; --------------------------------------
.bios
.basic
.org INI_PRG
.start MAIN
MAIN: di
xor a ; limpiando la casa
ld hl, iniram
ld bc, endram-iniram-1
call CLSRAM
call LHEADER ; leemos una cabecera
ret
; --------------------------------------
; inicia o detiene el motor del cassette
MOTORON: ld a, 1
bmotor: call STMOTR
ret
MOTOROFF: xor a
jr bmotor
; --------------------------------------
; salimos (por error de lectura) o paramos el cassete
EXIT: pop hl
STOP: call TAPIOF
ret
; --------------------------------------
; leemos datos (un byte) del cassete; C si se produce un error
READ: exx
call TAPIN
jr c, EXIT
exx
ret
; --------------------------------------
; leemos la cabecera larga del cassete; tipo = 10 bytes + nombre = 6 bytes
LHEADER: call TAPION
jr c, EXIT
ld b, 10 ; 10 bytes
ld hl, tipo_fichero
bucH: call READ
ld [hl], a
djnz bucH
ld b, 6 ; 6 bytes
ld hl, nom_fichero
bucN: call READ
ld [hl], a
inc hl
djnz bucN
call STOP
ld a, [tipo_fichero] ; tipo de fichero
cp BSAVE_FILE
jp z, BLOAD ; cargamos binario
cp SAVE_FILE
jp z, LOAD ; cargamos basic SAVE
cp CSAVE_FILE
jp z, CLOAD ; cargamos basic CSAVE
; TODO: fichero desconocido
; TODO: presentar informacion
; TODO: grabar fichero a disco
ret
; --------------------------------------
; cload tiene una cabecera corta que leemos con TAPION y luego
; los datos hasta encontrar 7 ceros seguidos
CLOAD: call rstzeros
xor a
ld [INI_BASIC-1], a ; 0 en 0x8000; requerido
ld hl, INI_BASIC
push hl
call TAPION
pop hl
jr c, EXIT
bcld: call READ
ld [hl], a
inc hl
cp 0
call nz, rstzeros
call z, inczeros
ld a, [temp1]
cp 7 ; termina con 7 ceros
jr nz, bcld
jr STOP
rstzeros: xor a
ld [temp1], a
ret
inczeros: ld a, [temp1]
inc a
ld [temp1], a
ret
; --------------------------------------
; load contiene multiples bloques de 256 bytes hasta 0x1a (ctrl+z)
; cada bloque tiene su cabecera corta que leemos con TAPION
LOAD: xor a
ld [INI_BASIC-1], a ; 0 en 0x8000; requerido
ld hl, INI_BASIC
bld1: push hl
call TAPION
pop hl
jp c, EXIT
ld b, 0 ; carga bloques de 256 bytes
bld2: call READ
cp 0x1a ; ctrl + z
jp z, STOP
ld [hl], a
inc hl
djnz bld2 ; fin de bloque
push hl
call TAPIOF
pop hl
jr bld1
; --------------------------------------
; bload tiene una cabecera corta seguida de 6 bytes con
; las direcciones de inicio, fin y ejecución del programa
; a continuación va el bloque de datos, todo seguido
BLOAD: xor a
ld hl, inifile
ld bc, finfile-inifile-1
call CLSRAM ; borra dirs fichero
call TAPION
jp c, EXIT
ld b, 6 ; 6 bytes
ld hl, inifile
bblh: call READ
ld [hl], a
inc hl
djnz bblh
call MOTOROFF
call calclng ; calculamos longitud
push hl
call MOTORON
pop bc ; longitud
ld hl,INI_BASIC ; inicio (temporal)
bbld: call READ
ld [hl], a
inc hl
dec bc
ld a, b
or c
jr nz, bbld
jp STOP
calclng: ld ix,inifile
ld e, [ix+0]
ld d, [ix+1] ; de = ini (real)
ld l, [ix+2]
ld h, [ix+3] ; hl = fin (real)
sbc hl, de ; longitud = fin - ini
ret
; -------------------------------------
; rellenamos bc+1 bytes de ram con el valor de A
CLSRAM: ld [hl], a
ld d, h
ld e, l
inc de
ldir
ret
; --------------------------------------
iniram: defb 0
tipo_fichero: defs 1
nom_fichero: defs 6
inifile: defs 2
finfile: defs 2
exefile: defs 2
temp1: defs 1
endram: defb 0
Como comentaba en otras ocasiones hay un Documento que explica-recoge bastante bien el tipo de Cargas que nos podemos encontrar y cómo "desprotegerlas". Vienen varios ejemplos de diferentes Cargas de tipo "Turbo". Por ejemplo hay una peculiaridad con los Juegos de la Compañia "GREMLIN" ya que todos todos TODOS sus juegos siguen el mismo patrón de carga Turbo, por lo que todos sus Juegos se desprotegían de la misma manera. El Documento también recoge otro tipo de Carga Turbo (la que usaba por ejemplo "Topo Soft" en sus Juegos).
Podéis descargar dicho Documento desde aquí: --->
Curso de Desprotección de ProgramasGracias & Saludetes.
