Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
cursos:ensamblador:rutinas_save_load [13-01-2024 10:34] – sromero | cursos:ensamblador:rutinas_save_load [19-01-2024 11:58] (actual) – sromero | ||
---|---|---|---|
Línea 45: | Línea 45: | ||
|< 70% 20% 20% 60% >| | |< 70% 20% 20% 60% >| | ||
^ Byte ^ Longitud ^ Descripción ^ | ^ Byte ^ Longitud ^ Descripción ^ | ||
- | | 0 | 1 | Byte Flag ($00 ó $FF) | | + | | 0 | 1 | Byte Flag ($00 ó $ff) | |
| 1 | 1 | Tipo de bloque (0-3)| | | 1 | 1 | Tipo de bloque (0-3)| | ||
| 2 | 10 | Nombre de fichero (rellenado con espacios en blanco) | | | 2 | 10 | Nombre de fichero (rellenado con espacios en blanco) | | ||
Línea 55: | Línea 55: | ||
| | ||
- | El byte de flag (Byte 0) y el de Checksum (byte 18) no forman parte exactamente de la cabecera, sino del bloque cargado en sí mismo (también están presente cuando cargamos datos y no cabeceras), pero se han incluído dentro de la tabla para hacerla de lectura más sencilla. Puede decirse que el byte-flag es el byte prefijo de todo bloque de datos (considerando una cabecera de 17 bytes como un bloque de datos) y el checksum es el byte sufijo de ese mismo bloque. Concretamente, | + | El byte de flag (Byte 0) y el de Checksum (byte 18) no forman parte exactamente de la cabecera, sino del bloque cargado en sí mismo (también están presente cuando cargamos datos y no cabeceras), pero se han incluído dentro de la tabla para hacerla de lectura más sencilla. Puede decirse que el byte-flag es el byte prefijo de todo bloque de datos (considerando una cabecera de 17 bytes como un bloque de datos) y el checksum es el byte sufijo de ese mismo bloque. Concretamente, |
El byte de tipo de bloque indica qué datos se van a cargar a continuación, | El byte de tipo de bloque indica qué datos se van a cargar a continuación, | ||
Línea 105: | Línea 105: | ||
</ | </ | ||
- | Así pues, la rutina de la ROM del Spectrum se encarga (tanto al grabar como al leer) de codificar pulsos de diferentes duraciones para almacenar los ceros y unos de forma consecutiva. Nosotros aprovecharemos (como veremos a continuación) dicha rutina para cargar o salvar bloques de datos a nuestro antojo sin tener que programar esas temporizaciones y lecturas/ | + | Así pues, la rutina de la ROM del Spectrum se encarga (tanto al grabar como al leer) de codificar pulsos de diferentes duraciones para almacenar los ceros y unos de forma consecutiva. Nosotros aprovecharemos (como veremos a continuación) dicha rutina para cargar o salvar bloques de datos a nuestro antojo sin tener que programar esas temporizaciones y lecturas/ |
El nivel más bajo al que necesitamos llegar es el siguiente: | El nivel más bajo al que necesitamos llegar es el siguiente: | ||
Línea 116: | Línea 116: | ||
* Cada bloque tiene la siguiente estructura lógica (formato de los datos DENTRO de un bloque): | * Cada bloque tiene la siguiente estructura lógica (formato de los datos DENTRO de un bloque): | ||
- | * Flag byte, con un valor de $00 para bloques de cabecera o $FF para bloques de datos. | + | * Flag byte, con un valor de $00 para bloques de cabecera o $ff para bloques de datos. |
* Los datos en sí mismos: 17 bytes para cabeceras, o la longitud concreta de los datos para los bloques de datos. | * Los datos en sí mismos: 17 bytes para cabeceras, o la longitud concreta de los datos para los bloques de datos. | ||
* Un byte de checksum, calculado de forma que haciendo un '' | * Un byte de checksum, calculado de forma que haciendo un '' | ||
Línea 128: | Línea 128: | ||
* Los 1s y los 0s se almacenan en cinta como pulsos de duraciones concretas. | * Los 1s y los 0s se almacenan en cinta como pulsos de duraciones concretas. | ||
* Las rutinas de la ROM nos permiten leer y escribir en cinta bloques de datos, realizando ellas la temporización adecuada para convertir nuestros "datos en memoria" | * Las rutinas de la ROM nos permiten leer y escribir en cinta bloques de datos, realizando ellas la temporización adecuada para convertir nuestros "datos en memoria" | ||
- | * Sólo necesitaríamos escribir una rutina propia de carga (que detecte pulsos, temporice, etc) si quisiéramos programar nuestra propia carga, por ejemplo para cargar a diferente velocidad que el Spectrum (ultracargas), | + | * Sólo necesitaríamos escribir una rutina propia de carga (que detecte pulsos, temporice, etc) si quisiéramos programar nuestra propia carga, por ejemplo para cargar a diferente velocidad que el Spectrum (ultracargas), |
\\ | \\ | ||
Línea 139: | Línea 139: | ||
</ | </ | ||
- | Este comando BASIC salvaría (SAVE), un total de 2 bytes (2) de datos (CODE), empezando en 0 (0) a cinta. En resumen, salvaría el contenido de la dirección de memoria | + | Este comando BASIC salvaría (SAVE), un total de 2 bytes (2) de datos (CODE), empezando en 0 (0) a cinta. En resumen, salvaría el contenido de la dirección de memoria |
< | < | ||
Línea 173: | Línea 173: | ||
| ff | f3 af | a3 | | | ff | f3 af | a3 | | ||
- | En este caso el byte flag es 0xFF (bloque de tipo " | + | En este caso el byte flag es $FF (bloque de tipo " |
\\ | \\ | ||
Línea 189: | Línea 189: | ||
| IX | Dirección inicio de memoria donde almacenar los datos que se van a cargar. | | | IX | Dirección inicio de memoria donde almacenar los datos que se van a cargar. | | ||
| DE | Longitud del bloque de datos a cargar. | | | DE | Longitud del bloque de datos a cargar. | | ||
- | | A | Flag Byte, normalmente | + | | A | Flag Byte, normalmente |
| CF (CarryFlag) | 1=LOAD, 0=VERIFY | | | CF (CarryFlag) | 1=LOAD, 0=VERIFY | | ||
Línea 198: | Línea 198: | ||
* "D BREAK - CONT repeats" | * "D BREAK - CONT repeats" | ||
- | | + | |
| | ||
<code z80> | <code z80> | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
Línea 213: | Línea 213: | ||
<code z80> | <code z80> | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
Línea 230: | Línea 230: | ||
| IX | Dirección inicio de memoria de los datos que se van a grabar. | | | IX | Dirección inicio de memoria de los datos que se van a grabar. | | ||
| DE | Longitud del bloque de datos a grabar (se grabarán los datos desde IX a IX+DE). | | | DE | Longitud del bloque de datos a grabar (se grabarán los datos desde IX a IX+DE). | | ||
- | | A | Flag Byte, 0x00 para grabar cabeceras o 0xFF (255) para grabar datos. | | + | | A | Flag Byte, $00 para grabar cabeceras o $FF (255) para grabar datos. | |
| CF (CarryFlag) | 0 (SAVE) | | | CF (CarryFlag) | 0 (SAVE) | | ||
Línea 245: | Línea 245: | ||
<code z80> | <code z80> | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
Línea 368: | Línea 368: | ||
ORG 32000 | ORG 32000 | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
END 32000 | END 32000 | ||
Línea 419: | Línea 419: | ||
El código comentado está extraído del documento "//The Complete Spectrum ROM Disassembly//", | El código comentado está extraído del documento "//The Complete Spectrum ROM Disassembly//", | ||
- | <code z80> | + | <code z80> |
; THE ' | ; THE ' | ||
; This subroutine is called to LOAD the header information (from 07BE) | ; This subroutine is called to LOAD the header information (from 07BE) | ||
; and later LOAD, or VERIFY, an actual block of data (from 0802). | ; and later LOAD, or VERIFY, an actual block of data (from 0802). | ||
0556 LD-BYTES: | 0556 LD-BYTES: | ||
- | | + | |
- | ; cannot hold +FF.) | + | ; cannot hold $FF.) |
- | | + | |
- | ; header and +FF for a block of | + | ; header and $FF for a block of |
; data. | ; data. | ||
; The carry flag is reset for | ; The carry flag is reset for | ||
; VERIFYing and set for | ; VERIFYing and set for | ||
; LOADing. | ; LOADing. | ||
- | | + | |
- | | + | |
; disabled. | ; disabled. | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | ; (+22 for ' | + | ; ($22 for ' |
; - the present EAR state.) | ; - the present EAR state.) | ||
- | | + | |
; The first stage of reading a tape involves showing that a pulsing | ; The first stage of reading a tape involves showing that a pulsing | ||
; signal actually exist (i.e. ' | ; signal actually exist (i.e. ' | ||
- | 056B LD-BREAK | + | 056B LD-BREAK |
; being pressed. | ; being pressed. | ||
- | 056C LD-START | + | 056C LD-START |
- | | + | |
; approx. 14,000 T states. But if | ; approx. 14,000 T states. But if | ||
; an ' | ; an ' | ||
Línea 463: | Línea 463: | ||
; that the signal is still pulsing. | ; that the signal is still pulsing. | ||
- | | + | |
- | 0574 LD-WAIT | + | 0574 LD-WAIT |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
; period. | ; period. | ||
; Now accept only a ' | ; Now accept only a ' | ||
- | 0580 LD-LEADER | + | 0580 LD-LEADER |
- | | + | |
- | | + | |
; period. | ; period. | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
; been found. | ; been found. | ||
; After the leader come the ' | ; After the leader come the ' | ||
- | 058F LD-SYNC | + | 058F LD-SYNC |
- | | + | |
- | | + | |
- | | + | |
- | CP | + | CP |
- | | + | |
- | | + | |
- | | + | |
; (Return carry flag reset.) | ; (Return carry flag reset.) | ||
Línea 501: | Línea 501: | ||
; VERIFied. But the first byte is the type flag. | ; VERIFied. But the first byte is the type flag. | ||
- | | + | |
- | XOR +03 ; on will be BLUE & YELLOW. | + | XOR $03 ; on will be BLUE & YELLOW. |
- | | + | |
- | | + | |
; byte to zero. | ; byte to zero. | ||
- | | + | |
; flag byte. | ; flag byte. | ||
- | | + | |
; LOADING loop. | ; LOADING loop. | ||
Línea 516: | Línea 516: | ||
; the last byte is the ' | ; the last byte is the ' | ||
- | 05A9 LD-LOOP | + | 05A9 LD-LOOP |
- | | + | |
; handling the first byte. | ; handling the first byte. | ||
- | | + | |
; tape. | ; tape. | ||
- | | + | |
; required. | ; required. | ||
- | | + | |
; next byte. | ; next byte. | ||
- | 05B3 LD-FLAG | + | 05B3 LD-FLAG |
; place temporarily. | ; place temporarily. | ||
- | | + | |
- | | + | |
; tape. (Carry flag reset.) | ; tape. (Carry flag reset.) | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
; after the jump. | ; after the jump. | ||
Línea 540: | Línea 540: | ||
; tested against the original byte. | ; tested against the original byte. | ||
- | 05BD LD-VERlFY | + | 05BD LD-VERlFY |
- | | + | |
- | | + | |
; flag reset.) | ; flag reset.) | ||
; A new byte can now be collected from the tape. | ; A new byte can now be collected from the tape. | ||
- | 05C2 LD-NEXT | + | 05C2 LD-NEXT |
- | 05C4 LD-DEC | + | 05C4 LD-dec |
- | | + | |
- | | + | |
- | 05C8 LD-MARKER | + | 05C8 LD-MARKER |
; from a ' | ; from a ' | ||
; The ' | ; The ' | ||
- | 05CA LD-8-BITS | + | 05CA LD-8-BITS |
; ' | ; ' | ||
- | | + | |
; exceeded. (Carry flag reset.) | ; exceeded. (Carry flag reset.) | ||
- | | + | |
; approx. 2,400 T states; resetting | ; approx. 2,400 T states; resetting | ||
- | | + | |
; setting it for a ' | ; setting it for a ' | ||
- | | + | |
; register. | ; register. | ||
- | | + | |
; next bit. | ; next bit. | ||
- | | + | |
; bits to be fetched. | ; bits to be fetched. | ||
; The ' | ; The ' | ||
- | | + | |
- | | + | |
- | | + | |
; Passes round the loop are made until the ' | ; Passes round the loop are made until the ' | ||
; At that point the ' | ; At that point the ' | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
; byte. | ; byte. | ||
- | CP | + | CP |
- | | + | |
; (Carry flag reset if in error.) | ; (Carry flag reset if in error.) | ||
Línea 599: | Línea 599: | ||
; is required and LD-EDGE-1 is used to find the time before the next ' | ; is required and LD-EDGE-1 is used to find the time before the next ' | ||
- | 05E3 LD-EDGE-2 | + | 05E3 LD-EDGE-2 |
- | | + | |
; is an error. | ; is an error. | ||
- | 05E7 LD-EDGE-1 | + | 05E7 LD-EDGE-1 |
- | 05E9 LD-DELAY | + | 05E9 LD-DELAY |
- | | + | |
- | | + | |
; The sampling loop is now entered. The value in the B register is | ; The sampling loop is now entered. The value in the B register is | ||
; incremented for each pass; ' | ; incremented for each pass; ' | ||
- | 05ED LD-SAMPLE | + | 05ED LD-SAMPLE |
- | | + | |
; ' | ; ' | ||
- | | + | |
- | IN A,(+FE) ; i.e. BREAK & EAR. | + | IN A,($fe) ; i.e. BREAK & EAR. |
- | | + | |
- | | + | |
; if BREAK was pressed. | ; if BREAK was pressed. | ||
- | | + | |
- | AND +20 ; 'last edge-type'; | + | AND $20 ; 'last edge-type'; |
- | | + | |
; A new ' | ; A new ' | ||
; So change the border colour and set the carry flag. | ; So change the border colour and set the carry flag. | ||
- | | + | |
- | | + | |
- | | + | |
- | AND +07 ; Keep only the border colour. | + | AND $07 ; Keep only the border colour. |
- | OR | + | OR |
- | OUT (+FE),A ; Change the border colour (RED/ | + | OUT ($fe),A ; Change the border colour (RED/ |
; CYAN or BLUE/ | ; CYAN or BLUE/ | ||
- | | + | |
- | | + | |
; Note: The LD-EDGE-1 subroutine takes 465 T states, plus an additional 58 T | ; Note: The LD-EDGE-1 subroutine takes 465 T states, plus an additional 58 T | ||
Línea 641: | Línea 641: | ||
; allowance is made for ten additional passes through the sampling loop. | ; allowance is made for ten additional passes through the sampling loop. | ||
; The search is thereby for the next edge to be found within, roughly, | ; The search is thereby for the next edge to be found within, roughly, | ||
- | ; 1,100 T states (465 + 10 * 58 + overhead). This will prove successful | + | ; 1,100 T states (465 $ 10 * 58 $ overhead). This will prove successful |
; for the sync ' | ; for the sync ' | ||
</ | </ | ||
+ | |||
+ | |||
\\ | \\ | ||
===== Ficheros ===== | ===== Ficheros ===== |