MZ-80A RomDisk — Guia del Desarrollador

Guia del Desarrollador del RomDisk

Esta guia es un recorrido detallado por el codigo fuente del firmware del PCB Sharp MZ-80A RomDisk y el entorno de desarrollo. Explica conceptos del lenguaje ensamblador Z80 para desarrolladores que pueden no estar familiarizados con el lenguaje, describe en profundidad el mecanismo de conmutacion de bancos especifico del RomDisk, recorre cada modulo fuente y muestra como anadir nuevos comandos, anadir nuevas variantes de hardware SPI y depurar firmware en hardware real.
El firmware del RomDisk es una variante del Rom Filing System (RFS). Salvo indicacion contraria, todas las descripciones aqui se aplican a compilaciones con BUILD_ROMDISK EQU 1 en rfs_definitions.asm. Para la arquitectura de hardware y detalles de construccion del PCB, consulte la pagina de hardware del RomDisk. Para el uso de cara al usuario, consulte el Manual de Usuario RFS.

Introduccion al Ensamblador Z80 para No-Programadores de Assembly

Todo el firmware del RomDisk esta escrito en lenguaje ensamblador Z80 -- el lenguaje de instrucciones nativo del procesador Zilog Z80 utilizado en la serie Sharp MZ. A diferencia de los lenguajes de alto nivel, el ensamblador se mapea casi directamente al hardware fisico: cada instruccion se traduce en uno o unos pocos bytes que la CPU ejecuta directamente.

Registros
El Z80 no tiene "variables" -- en su lugar tiene un pequeno conjunto de registros (ubicaciones de almacenamiento rapido dentro de la CPU). Los mas utilizados en RFS:
Register Size Role
A 8-bit Accumulator — the primary register for arithmetic, logic, and I/O operations. Almost every instruction involves A.
B, C 8-bit General purpose. BC together forms a 16-bit pair, commonly used as a loop counter or byte count.
D, E 8-bit General purpose. DE together is a 16-bit pair, commonly used as a source or destination pointer.
H, L 8-bit General purpose. HL together is the main 16-bit memory pointer — most memory read/write instructions use HL.
IX, IY 16-bit Index registers — used for base+offset memory addressing. Slower than HL but convenient for structured data.
SP 16-bit Stack Pointer — points to the top of the call stack. PUSH and POP use SP automatically.
PC 16-bit Program Counter — the address of the current instruction. Incremented automatically; modified by jumps and calls.
F 8-bit Flags register — individual bits set by arithmetic operations: Z (zero), C (carry), S (sign), P/V (parity/overflow).

Instrucciones Clave
  • LD dest, src -- Cargar (copiar) datos. LD A, B copia B en A. LD A, (HL) lee el byte en la direccion de memoria contenida en HL hacia A. LD (0x1200), A escribe A en la direccion de memoria 0x1200.
  • CALL addr -- Llamar a una subrutina. Empuja la direccion de retorno (siguiente instruccion) en la pila y salta a addr. Equivalente a una llamada de funcion.
  • RET -- Retorno de subrutina. Saca la direccion de retorno de la pila y salta a ella.
  • JP addr -- Salto incondicional a addr. JP Z, addr salta solo si el flag Zero esta activado (es decir, la ultima operacion produjo cero).
  • JR offset -- Salto relativo corto (-128 a +127 bytes). Mas rapido y compacto que JP para ramificaciones cercanas.
  • DJNZ offset -- Decrementar B y saltar si No es Zero. La instruccion de bucle canonica del Z80: LD B, 10 / LOOP: ... / DJNZ LOOP repite 10 veces.
  • ADD A, n -- Sumar n a A. SUB n resta. AND n, OR n, XOR n -- logica bit a bit sobre A.
  • IN A, (port) -- Leer del puerto de E/S hacia A. OUT (port), A -- escribir A al puerto de E/S. Asi es como el Z80 se comunica con el hardware (el controlador de disquetes WD1773, registros de desplazamiento SPI, latch de banco, etc.).
  • PUSH rr / POP rr -- Guardar/restaurar un par de registros de 16 bits en/desde la pila.
  • EI / DI -- Habilitar / Deshabilitar interrupciones. El codigo que no debe ser interrumpido (por ejemplo, operaciones de cinta criticas en tiempo) se envuelve entre DI y EI.

Modos de Direccionamiento
El Z80 ofrece varias formas de especificar de donde provienen o a donde van los datos:
  • Inmediato: LD A, 42 -- el valor esta integrado en los propios bytes de la instruccion.
  • Registro: LD A, B -- los datos provienen de o van a un registro.
  • Indirecto (via HL): LD A, (HL) -- HL contiene una direccion de memoria; los datos se leen de esa direccion.
  • Extendido (direccion directa): LD A, (0x1200) -- la direccion es una constante literal de 16 bits en la instruccion.
  • Indexado: LD A, (IX+5) -- IX contiene una direccion base; se suma 5 para obtener la direccion efectiva. Se usa en RFS para acceder a campos dentro de estructuras de datos de formato fijo.

Sintaxis del Ensamblador GLASS
RFS utiliza el ensamblador GLASS Z80 (incluido como tools/glass.jar). Caracteristicas clave de la sintaxis:
  • Los comentarios comienzan con ; -- todo a la derecha de un punto y coma se ignora.
  • Las etiquetas son identificadores seguidos de :. Una etiqueta al inicio de una linea nombra la direccion de la siguiente instruccion.
  • EQU define una constante: BELL EQU 007H -- el ensamblador reemplaza cada ocurrencia de BELL con 0x07.
  • DB (Define Byte) inserta bytes sin procesar: DB 0x41, 0x42 emite dos bytes. Se usa para cadenas, tablas de busqueda y entradas de tabla de comandos.
  • DW (Define Word) inserta valores de 16 bits little-endian: DW HANDLER emite la direccion de la etiqueta HANDLER.
  • ORG addr establece el origen del ensamblaje -- el codigo subsiguiente se ensambla como si residiera en addr.
  • INCLUDE "file.asm" incluye textualmente otro archivo en la posicion actual.
  • IF / ENDIF ensamblaje condicional: IF HW_SPI_ENA = 1 ... ENDIF -- las instrucciones encerradas solo se ensamblan cuando la condicion es verdadera. Asi es como RFS selecciona entre SPI hardware, SPI software y SPI por puerto paralelo desde un unico arbol de fuentes.

Arbol de Fuentes

Path Contents
README.md Top-level project overview
README_CPM.md CP/M-specific notes
schematics/ KiCad schematics for PCB v1.1, v2.0, v2.1
pcb/ KiCad PCB layout files
software/RFS/ RFS firmware submodule (also at /dvlp/Projects/RFS)
software/RFS/asm/ All Z80 assembly source files
software/RFS/asm/include/ Shared configuration and utility includes
software/RFS/tools/ Build scripts and GLASS assembler (glass.jar)
software/RFS/build.sh Top-level build script

Los archivos fuente de ensamblador y sus funciones:

File Bank Role
rfs.asm User ROM Bank 0 Entry point, command table, bank-switch stubs, jump table
rfs_bank1.asm User ROM Bank 1 Floppy disk controller
rfs_bank2.asm User ROM Bank 2 SD card controller (SPI driver, SDCFS)
rfs_bank3.asm User ROM Bank 3 Memory utilities (D, M, CP, T2SD, SD2T)
rfs_bank4.asm User ROM Bank 4 CMT (cassette tape) controller
rfs_bank5.asm User ROM Bank 5 Reserved / unused
rfs_bank6.asm User ROM Bank 6 Messages, help screen, ASCII↔Sharp character conversion
rfs_bank7.asm User ROM Bank 7 Memory test (R command), timer test (T command)
rfs_mrom.asm Monitor ROM Bank 3 MZF ROM scanning and loading (ROMDIR, ROMLOAD)
cbios.asm Monitor ROM Bank 2 CP/M CBIOS entry point table and ROM disk controller
cbios_bank1–4.asm User ROM Banks 8–11 CP/M CBIOS subsystems
monitor_sa1510.asm SA-1510 Monitor ROM reference
monitor_80c_sa1510.asm SA-1510 Monitor ROM (80-column variant)
ipl.asm Initial Program Loader
include/rfs_definitions.asm All configuration constants
include/rfs_utilities.asm Shared utility macros
include/macros.asm Assembler macro definitions
include/cpm_definitions.asm CP/M CBIOS constants

Configuracion: rfs_definitions.asm

Este es el archivo de configuracion central, incluido por todos los demas archivos fuente mediante INCLUDE "rfs_definitions.asm". Todas las opciones en tiempo de ensamblaje se controlan aqui. Las secciones clave:

Flags de Compilacion y SPI
; SPI hardware selection — exactly ONE must be 1:
HW_SPI_ENA    EQU 1    ; Hardware SPI on RomDisk v2+ PCB (74HCT595/165 shift registers)
SW_SPI_ENA    EQU 0    ; Software bit-bang SPI via Z80 I/O port bits
PP_SPI_ENA    EQU 0    ; Parallel printer port SPI (v1 boards only)

; Platform options:
FUSIONX_ENA   EQU 1    ; Include tranZPUter FusionX support
KUMA80_ENA    EQU 0    ; Target has Kuma 40/80 upgrade installed
VIDEOMODULE_ENA EQU 0  ; Target has 40/80 column colour video module

; Build target — exactly ONE must be 1:
BUILD_ROMDISK EQU 1    ; Build for the MZ-80A RomDisk card
BUILD_SFD700  EQU 0    ; Build for the SFD-700 floppy interface
BUILD_PICOZ80 EQU 0    ; Build for the picoZ80 board

; Debugging:
ENADEBUG      EQU 0    ; Enable debug output during assembly (1 = enable)
Exactamente un flag BUILD_* y exactamente un flag SPI deben estar establecidos a 1 a la vez. Establecer mas de uno producira codigo incorrecto o ambiguo -- varios bloques condicionales en rfs_bank2.asm utilizan cadenas IF/ELSE/ENDIF anidadas que asumen exclusion mutua. Cuando FUSIONX_ENA = 1, se ensambla codigo adicional para la gestion de memoria FusionX del tranZPUter en los stubs de conmutacion de banco; es seguro dejarlo habilitado en compilaciones estandar del RomDisk ya que la ruta FusionX solo se toma en tiempo de ejecucion cuando se detecta hardware FusionX.

Constantes de Direccion
UROMADDR     EQU 0E800H          ; Base of User ROM window
UROMBSTBL    EQU UROMADDR + 020H ; Bank-switch table entry point (0xE820)
RFSJMPTABLE  EQU UROMADDR + 0B0H ; Jump table start (0xE8B0)
FDCROMADDR   EQU 0F000H          ; Floppy AFI ROM address

; Bank control registers (only accessible after coded latch unlock):
BNKCTRLRST   EQU 0EFF8H    ; Read here 16 times to unlock control registers
BNKCTRLDIS   EQU 0EFF9H    ; Read here once to re-lock (disable) control registers
HWSPIDATA    EQU 0EFFBH    ; Hardware SPI data register (read/write)
HWSPISTART   EQU 0EFFCH    ; Hardware SPI start trigger (write to begin transfer)
BNKSELMROM   EQU 0EFFDh    ; Monitor ROM bank select register
BNKSELUSER   EQU 0EFFEh    ; User ROM bank select register
BNKCTRL      EQU 0EFFFH    ; Bank control register (read/write)
Notese que BNKCTRLRST a BNKCTRL (0xEFF8-0xEFFF) comparten el mismo espacio de direcciones que los 8 bytes superiores de la ventana de Flash ROM. Al reiniciar, estas direcciones se comportan como lecturas ordinarias de Flash ROM. El circuito de latch codificado -- un contador preseteado 74HCT191 -- debe desbloquearse antes de que las escrituras a BNKSELMROM, BNKSELUSER o BNKCTRL surtan efecto. Consulte la seccion de conmutacion de bancos a continuacion para la secuencia completa de desbloqueo.

Definiciones de Caracteres y Control
Los caracteres de control ASCII estandar se definen como constantes con nombre para hacer el codigo fuente auto-documentado:
BELL    EQU 007H    ; Terminal bell
CR      EQU 00DH    ; Carriage return
LF      EQU 00AH    ; Line feed
CS      EQU 00CH    ; Clear screen (FF)
SPACE   EQU 020H    ; ASCII space
DELETE  EQU 07FH    ; Delete key

Conmutacion de Bancos en Detalle

El mecanismo de conmutacion de bancos del RomDisk es fundamentalmente diferente del utilizado por TZFS. TZFS utiliza los modos de gestion de memoria del CPLD del tranZPUter para remapear rangos de direcciones en hardware. El RomDisk en cambio utiliza un latch de banco fisico -- un flip-flop tipo D 74HCT273 -- accedido a traves de registros de E/S mapeados en memoria en la parte superior del espacio de direcciones de la User ROM. Comprender este mecanismo es esencial antes de modificar cualquier archivo fuente.

Por que se Necesita la Conmutacion de Bancos
El Sharp MZ-80A solo otorga 2 KB de espacio de direcciones a la User ROM (0xE800-0xEFFF). 2 KB solo pueden contener unos pocos cientos de instrucciones -- ni de lejos suficiente para un sistema de archivos, controlador de disquetes, driver de tarjeta SD, controlador de cinta y utilidades de memoria. La solucion es conmutar fisicamente que pagina de 2 KB de un chip Flash mas grande es visible en 0xE800-0xEFFF. El PCB del RomDisk contiene un chip Flash de 512 KB dividido en bancos de 2 KB, con hasta 12 bancos accesibles a la vez. Conmutar entre ellos bajo demanda da a RFS efectivamente 24 KB de codigo ROM mientras el monitor SA-1510 solo ve una ventana estatica de 2 KB.

El Latch Codificado (Tarjetas v2.0 y Posteriores)
Los registros de seleccion de banco comparten lineas de direccion con los 8 bytes superiores de la Flash ROM (0xEFF8-0xEFFF). Si el registro de seleccion de banco fuera escribible en todo momento, cualquier escritura perdida a ese rango de direcciones -- o incluso ciclos de refresco del Z80 alcanzando ese rango -- conmutaria silenciosamente los bancos a mitad de ejecucion. El PCB RomDisk v2.0 introdujo un latch codificado para prevenir esto.
El latch codificado esta construido a partir de un contador preseteado 74HCT191. En su estado por defecto (contador no en Terminal Count), la ruta de E/S del registro de control de banco esta deshabilitada -- las escrituras a BNKSELMROM, BNKSELUSER y BNKCTRL no tienen efecto. Para habilitar la ruta, el software debe leer de la direccion BNKCTRLRST (0xEFF8) exactamente 16 veces. Cada lectura incrementa el contador en uno. Cuando el contador alcanza Terminal Count (16), activa la senal de habilitacion que activa la ruta de escritura del registro de control de banco.
Despues de completar la conmutacion de banco, el software lee de BNKCTRLDIS (0xEFF9) una vez. Esto reinicia el 74HCT191 a su valor inicial, desactivando la ruta del registro de control nuevamente. El latch debe desbloquearse de nuevo antes de cada secuencia subsiguiente de conmutacion de banco.
La tarjeta RomDisk v2.1 anadio una puerta AND (denominada D1/D2 en el esquema) para evitar que los ciclos de refresco de DRAM del Z80 incrementen accidentalmente el contador. Sin esta puerta, los ciclos periodicos de refresco del bus que el Z80 genera automaticamente podrian incrementar el contador por si solos, potencialmente alcanzando Terminal Count sin ninguna accion deliberada del software y causando conmutaciones de banco espurias durante el arranque.

La Secuencia de Conmutacion de Banco
Una conmutacion de banco completa para la User ROM requiere los siguientes pasos:
  1. Desbloquear el latch codificado: Leer de la direccion BNKCTRLRST (0xEFF8) exactamente 16 veces. Cada lectura es una lectura ficticia -- el dato devuelto es el byte de la Flash ROM en esa direccion y puede descartarse. Use un contador de bucle en el registro B (establecido a 16), pero vea la advertencia critica a continuacion sobre la ubicacion del DJNZ.
  2. Escribir el numero de banco: Escribir el numero de banco deseado (0-7 para bancos de User ROM) en BNKSELUSER (0xEFFE). El 74HCT273 captura el valor en el flanco ascendente del strobe de escritura. Para la seleccion de banco de Monitor ROM, escribir en BNKSELMROM (0xEFFD) en su lugar.
  3. Re-bloquear el latch: Leer de BNKCTRLDIS (0xEFF9) una vez. Esto reinicia el contador 74HCT191 y deshabilita la ruta de escritura del registro de control hasta la proxima secuencia de 16 lecturas.
El stub de conmutacion de banco en cada banco (comenzando en UROMBSTBL, 0xE820) realiza esta secuencia automaticamente. El stub tambien guarda y restaura el numero de banco de llamada para que despues de que la rutina destino retorne, el stub pueda conmutar de vuelta al banco original. Como el stub esta en un offset fijo dentro de cada banco, el banco 0 siempre puede encontrar el stub en el banco 3 (o cualquier otro banco) calculando UROMBSTBL -- incluso si nunca ha visto las direcciones internas del banco 3.

Critico: Nunca Colocar un Bucle que Abarque 0xEFF8-0xEFFF
Esta es la restriccion de implementacion mas importante en toda la base de codigo del RomDisk. El Z80 obtiene bytes de instruccion leyendo de la direccion del Program Counter. Si cualquier busqueda de instruccion o lectura de datos ocurre dentro del rango 0xEFF8-0xEFFF, incrementa el contador 74HCT191. Una instruccion DJNZ en, digamos, 0xEFF7 buscara su opcode de 0xEFF7 (sin efecto), luego su byte de offset de 0xEFF8 (incrementa el contador), y en iteraciones subsiguientes del bucle continuara incrementando el contador en cada pasada. Si el bucle se ejecuta 16 o mas veces antes de cualquier conmutacion de banco intencional, el contador alcanza Terminal Count, los registros de control se activan, y la proxima escritura a cualquier direccion en 0xEFF8-0xEFFF realizara una conmutacion de banco no intencionada -- reemplazando instantaneamente el codigo en ejecucion con un banco diferente.
La regla es simple: ninguna instruccion de bucle (DJNZ, JR, JP) puede tener su destino de salto o sus propios bytes de opcode/operando dentro de 0xEFF8-0xEFFF. El ensamblador GLASS no detecta ni advierte automaticamente sobre esto; es responsabilidad del programador. Al anadir codigo a cualquier banco, verifique que el binario ensamblado no coloque ninguna instruccion de bucle cerca de la parte superior de la ventana de 2 KB.

Conmutacion de Banco FusionX (FUSIONX_ENA = 1)
Cuando FUSIONX_ENA = 1, los stubs de conmutacion de banco incluyen bloques de ensamblaje condicional que sustituyen las direcciones del puerto de gestion de memoria FusionX por los registros de latch codificado. En una tarjeta tranZPUter FusionX, el mecanismo de paginacion de Flash ROM es reemplazado por la gestion de memoria del CPLD FusionX, que acepta numeros de banco a traves de un esquema de puerto de E/S diferente sin la secuencia de desbloqueo de 16 lecturas. El conjunto de comandos RFS, el sistema de archivos SDCFS y todo el comportamiento visible para el usuario permanecen identicos en FusionX -- solo difieren las escrituras de seleccion de banco de bajo nivel.

Formato de Tabla de Comandos (rfs.asm)
El despachador de comandos del monitor en rfs.asm utiliza una tabla de comandos compacta. Cada entrada describe un comando y se estructura de la siguiente manera:
; One command table entry:
;
;   DB  FLAGS          ; 1 byte: END|MATCH|BANK[5:3]|SIZE[2:0]
;   DB  "COMMAND"      ; SIZE bytes: the command string (no null terminator)
;   DW  HANDLER_ADDR   ; 2 bytes: address of the handler routine in the named bank
;
; Flags byte bit fields:
;   Bit 7 = 1: End of table marker (last entry).
;   Bit 6 = 1: Exact match required (entire input must match; no trailing characters).
;   Bits 5:3   Bank number where HANDLER_ADDR lives (0–7 maps to User ROM banks 0–7).
;   Bits 2:0   Length of the command string in bytes (1–7).
;
; Example — the 'D' (dump) command, handler in bank 3, 1-character string:
    DB  000H | 000H | 018H | 001H    ; not-end, not-exact, bank 3 (011<<3=0x18), length 1
    DB  "D"
    DW  DUMPX
El despachador lee la linea de entrada del monitor, recorre la tabla, y para cada entrada:
  1. Compara los primeros SIZE caracteres de la entrada con la cadena del comando.
  2. Si el flag EXACT esta activado, verifica tambien que no hay mas caracteres no-espacio a continuacion.
  3. Si coincide, extrae el numero de banco y la direccion del manejador de la entrada de la tabla.
  4. Realiza la conmutacion de banco al banco destino a traves del stub en UROMBSTBL.
  5. Llama al manejador con la entrada restante (parametros) disponible en el buffer de entrada del monitor.
Notese que las entradas se verifican en orden -- las cadenas de comando mas largas deben aparecer antes de sus prefijos mas cortos en la tabla. Por ejemplo, LTNX debe preceder a LT, que debe preceder a L, de lo contrario la entrada mas corta coincidira primero y el comando mas largo nunca sera alcanzado.

Recorrido por los Modulos

rfs.asm -- Despachador de Comandos (User ROM Bank 0)
Funcion: El punto de entrada para toda la funcionalidad RFS. Cuando el monitor SA-1510 no reconoce un comando, pasa el control al punto de entrada de la User ROM en UROMADDR (0xE800). Esta direccion es siempre el banco 0.
Secciones clave:
  • Entrada ROM (ROMFS, 0xE800): Un NOP seguido de una llamada a macro que selecciona el Monitor ROM banco 0, luego un JP para saltar sobre el area de la tabla de conmutacion de bancos. En arranque en frio (detectado verificando si ROMBK1 tiene un valor ilegal >= 8), se realiza la secuencia de configuracion del latch codificado de 16 lecturas y se pone a cero el area inferior de la pila. Los bancos iniciales de MROM y UROM se seleccionan entonces del estado guardado en ROMBK1/ROMBK2.
  • Stub de conmutacion de banco (UROMBSTBL, 0xE820): Dieciseis pasarelas de llamada entre bancos -- BKSW0to0 a BKSW0to7 -- una para cada transicion banco 0->N. Cada pasarela empuja el numero de banco de llamada y el numero de banco destino en la pila, luego llama a la secuencia comun BKSW0_0 que realiza el desbloqueo del latch codificado, escribe el nuevo banco en BNKSELUSER y salta a la direccion del manejador destino. Al retornar (BKSWRET0), el banco original se restaura mediante la misma secuencia.
  • Tabla de saltos (RFSJMPTABLE, 0xE8B0): Instrucciones JP de direccion fija para funciones que el Monitor ROM o los ganchos de interceptacion del SA-1510 necesitan llamar: PRTMZF, PRTDBG, CMT_RDINF, CMT_RDDATA, CMT_WRINF, CMT_WRDATA, CMT_VERIFY, CMT_DIR, CNV_ATOS.
  • Tabla de comandos (CMDTABLE): La lista de comandos de compilacion RomDisk/picoZ80. Los comandos incluyen: seleccion de unidad (0-9), modo 40/80 columnas, B (campana), BASIC, C (limpiar), CP, CPM, D (volcado), EC (borrar), F (arranque disquete), f (AFI ROM), H (ayuda), IR/IC (directorio), J (salto), LC/LR/LT y sus variantes NX (cargar SD/ROM/cinta), M (editar), P (prueba impresora), R (prueba DRAM), SD2T, SC/ST (guardar), T (prueba temporizador), T2SD, V (verificar).
  • Inicializacion (MONITOR -> SIGNON): Verifica la presencia de la tarjeta tranZPUter a traves del puerto de E/S CPLDINFO. Establece el numero de unidad SD inicial a 0. Detecta el banco activo del Monitor ROM para determinar el modo de visualizacion de 40 o 80 columnas y configura la pantalla en consecuencia. En compilaciones con modulo de video, escribe el modo de visualizacion en el latch DSPCTL.
  • Despachador de comandos (ST1X): Lee el buffer de entrada del monitor, recorre CMDTABLE, extrae banco y direccion del manejador ante una coincidencia, llama al stub de conmutacion de banco, y al retornar vuelve al bucle para esperar el siguiente comando. Si ninguna entrada coincide, devuelve el control al monitor SA-1510 para que pueda imprimir su error "?".

rfs_bank1.asm -- Controlador de Disquetes (User ROM Bank 1)
Funcion: Implementa los comandos de arranque desde disquete. En la compilacion RomDisk este banco proporciona los comandos completos F (arranque con seleccion de unidad) y f (salto directo a AFI ROM).
Funciones clave:
  • FLOPPY (comando F): Solicita un numero de unidad si no se proporciona en la linea de comandos. Escribe los bytes de seleccion de unidad y habilitacion del motor en el puerto de E/S 0xDC (el puerto de control del FDC WD1773). Espera a que el motor del eje alcance la velocidad de operacion (tipicamente 300-500 ms, medido por un bucle de retardo contado por ciclos de CPU). Lee el sector de arranque, verifica el byte de firma de disco arrancable y pasa el control al codigo del cargador de arranque encontrado en el sector.
  • FDCK (comando f): Lee el byte en FDCROMADDR (0xF000) para verificar que la AFI ROM esta presente y no es cero. Si se encuentra, llama a 0xF000 directamente, entregando el control a la ROM original de arranque de disquetes del SA-1510. Es util como respaldo cuando la logica de seleccion de unidad WD1773 en FLOPPY no es necesaria.

rfs_bank2.asm -- Controlador de Tarjeta SD (User ROM Bank 2)
Funcion: El subsistema completo de tarjeta SD -- inicializacion del driver SPI, protocolo de comandos de tarjeta SD y las rutinas de directorio y E/S de archivos del SDCFS. El codigo del driver SPI se selecciona en tiempo de ensamblaje por los flags HW_SPI_ENA, SW_SPI_ENA y PP_SPI_ENA.
Funciones clave:
  • SDINIT: Implementa la secuencia de inicializacion SPI de la tarjeta SD. Desactiva chip select, llama a SPIINIT para entrenar la tarjeta al reloj SPI, luego activa chip select y envia CMD0 (GO_IDLE_STATE) con hasta SD_RETRIES intentos. En caso de exito, envia CMD8 (SEND_IF_COND) para detectar tarjetas SD v2, luego ACMD41 (SD_SEND_OP_COND) para transicionar fuera del estado idle. Maneja tarjetas SD v1, SD v2, SDHC, SDXC y MMC v3 verificando la respuesta OCR de CMD58.
  • SDREAD / SDWRITE: Lectura (CMD17, READ_SINGLE_BLOCK) y escritura (CMD24, WRITE_BLOCK) a nivel de sector. SDREAD espera el token de inicio de datos (0xFE) luego lee 512 bytes al buffer RAM SDBUF. SDWRITE envia el token de inicio de datos, 512 bytes de datos y un CRC ficticio, luego espera a que se libere la senal de ocupado.
  • SDDIR: Lee el directorio de los primeros 8 KB de la imagen de la unidad SD activa en una cache de directorio residente en RAM. Cada entrada de directorio tiene formato de cabecera MZF (128 bytes): tipo de archivo, nombre de archivo (17 bytes, codificacion Sharp), tamano de datos, direccion de carga, direccion de ejecucion.
  • SDLOAD: Dado un numero de archivo de la cache de directorio, calcula la direccion de sector alineada a 64 KB del bloque de datos del archivo, lee los bytes del tamano de datos del archivo y los carga directamente en la direccion Z80 almacenada en el campo de direccion de carga de la entrada del directorio.
  • SDSAVE: Asigna una nueva ranura de directorio o encuentra una entrada existente con el mismo nombre para sobrescribir. Escribe los campos de cabecera MZF (sector de inicio, tamano, direccion de carga, direccion de ejecucion), luego escribe los datos del archivo en el bloque de 64 KB correspondiente en la tarjeta SD.
  • SPIINIT: Entrena la tarjeta SD al reloj SPI. Bajo HW_SPI_ENA, escribe 0xFF a HWSPIDATA y dispara HWSPISTART 10 veces (enviando 80 bits '1'). Bajo PP_SPI_ENA (bit-bang por puerto paralelo), conmuta la linea de reloj 80 veces con los datos en alto.
  • SPICS: Establece la linea de chip select de la tarjeta SD. A = 0 activa CS (bajo), A = 0xFF desactiva CS (alto). Bajo HW_SPI_ENA, modifica los bits SDCS y BBCLK de BNKCTRL y escribe de vuelta al registro de hardware.
  • SPIOUT: Envia un byte A a la tarjeta SD. Bajo HW_SPI_ENA: escribe A a HWSPIDATA y dispara HWSPISTART -- dos escrituras de memoria, aproximadamente 1 us por byte a 8 MHz de reloj SPI. Bajo PP_SPI_ENA: envio bit a bit del byte MSB-primero conmutando las lineas de reloj y datos en el puerto paralelo, 3 instrucciones OUT por bit.
  • SPIIN: Recibe un byte de la tarjeta SD. Bajo HW_SPI_ENA: dispara HWSPISTART para recibir 8 bits, luego lee HWSPIDATA. Bajo PP_SPI_ENA: recibe cada bit leyendo el registro de entrada del puerto paralelo.

rfs_bank3.asm -- Utilidades de Memoria (User ROM Bank 3)
Funcion: Implementa los comandos D (volcado hexadecimal), M (edicion de memoria) y CP (copia de memoria), disponibles en todas las compilaciones. Los comandos T2SD (cinta a SD) y SD2T (SD a cinta) tambien estan en este banco.
DUMPX (comando D): Lee hasta 20 lineas de 16 bytes cada una del rango de direcciones destino. Para cada linea, imprime la direccion hexadecimal de 4 digitos, 16 valores hexadecimales de bytes con un espacio cada 4 bytes, y los 16 caracteres ASCII correspondientes (punto para bytes no imprimibles). El Sharp MZ utiliza una codificacion de caracteres propietaria -- el banco 6 proporciona la tabla de conversion Sharp-a-ASCII utilizada aqui.
MCORX (comando M): Editor de memoria interactivo. Presenta cada byte en secuencia mostrando la direccion y el valor hexadecimal actual. El usuario escribe un nuevo valor hexadecimal de 1 o 2 digitos y presiona Enter para escribirlo, o presiona Enter solo para dejar el byte sin cambios. Ctrl+C o la tecla de escape sale.
MCOPY (comando CP): Copia de bloque de memoria. Acepta direccion de origen, direccion de destino y conteo de bytes desde la linea de comandos como valores hexadecimales de 4 digitos. Realiza una copia hacia adelante o hacia atras segun sea necesario para manejar correctamente regiones superpuestas.
T2SD y SD2T: Copia bidireccional cinta<->SD. T2SD llama a la rutina de carga CMT del banco 4 para leer un archivo de cinta (incluyendo su cabecera MZF) en RAM, luego llama a la rutina SDSAVE del banco 2 para escribirlo en la unidad SD activa. SD2T llama a SDLOAD del banco 2 para cargar un archivo en RAM, luego llama a la rutina de guardado CMT del banco 4 para escribirlo en cinta. Ambos comandos usan los campos de la cabecera MZF (nombre de archivo, tamano, direccion de carga, direccion de ejecucion) para mantener el directorio consistente entre medios.

rfs_bank4.asm -- Controlador CMT (User ROM Bank 4)
Funcion: Implementa los comandos LT/LTNX (carga de cinta), ST (guardado en cinta) y V (verificacion de cinta).
El Sharp MZ-80A utiliza una interfaz de casete Kansas City Standard a 1200 baudios. Los bytes se codifican como rafagas de tono de 1200 Hz (bit 0) o 2400 Hz (bit 1). Las rutinas de cinta son criticas en tiempo -- deben medir la frecuencia del tono entrante y generar la forma de onda saliente con precision de microsegundos. Utilizan el Temporizador de Intervalos Programable 8253 (o bucles de retardo contados por ciclos de CPU en plataformas sin el temporizador) para medir periodos de bits. Las interrupciones se deshabilitan (DI) durante todas las operaciones de cinta para prevenir interrupciones de temporizado.
LOADTAPE / LOADTAPENX: Lee la cabecera MZF de la cinta (128 bytes: tipo de archivo, nombre de archivo, tamano de datos, direccion de carga, direccion de ejecucion), muestra el nombre del archivo, luego lee los bytes de datos a la direccion de carga. LOADTAPE auto-ejecuta saltando a la direccion de ejecucion tras una carga exitosa; LOADTAPENX retorna al prompt de comandos RFS en su lugar.
SAVEX (comando ST): Escribe la cabecera MZF seguida de los bytes de datos en cinta. Acepta direccion de inicio, direccion de fin y direccion de ejecucion desde la linea de comandos, o solicita si no se proporcionan.
VERIFYX (comando V): Lee un archivo de cinta y lo compara byte a byte contra la RAM en la direccion de carga original. Informa cualquier discrepancia con su direccion y valores esperado/real.
El formato de cabecera MZF utilizado por las rutinas de cinta es identico al formato de entrada de directorio del SDCFS. Esto no es accidental -- es la razon por la que la copia cinta-a-SD es completamente transparente y por la que los programas cargados con LT pueden re-guardarse en tarjeta SD con SC sin ninguna conversion de cabecera.

rfs_bank5.asm -- Reservado (User ROM Bank 5)
Funcion: Actualmente reservado y sin uso en la compilacion RomDisk. La ranura del banco existe en la imagen de la Flash ROM y contiene el stub de conmutacion de banco en el offset estandar, pero no hay comandos accesibles por el usuario mapeados aqui. Este banco esta disponible para expansion futura -- por ejemplo, anadir un protocolo de transferencia XModem, un cargador hexadecimal o drivers de hardware adicionales mapeados en memoria.

rfs_bank6.asm -- Mensajes y Tablas de Caracteres (User ROM Bank 6)
Funcion: Almacena el texto de la pantalla de ayuda, todas las cadenas de mensajes de error y estado, y la tabla de conversion del juego de caracteres Sharp MZ a ASCII.
HELPSCR (comando H, aproximadamente linea 282): Una secuencia de cadenas terminadas en CR, una por linea de la pantalla de ayuda. La variante BUILD_ROMDISK lista todos los comandos del RomDisk incluyendo T2SD, SD2T, F[X], f, LC, SC, EC, IR/IC y los digitos de seleccion de unidad 0-9. La lista termina con un unico byte 000H. El comando H recorre esta lista, imprimiendo cada cadena hasta encontrar el terminador.
PRINTMSG / PRTFN: Utilidades de impresion de cadenas. PRINTMSG maneja bytes marcadores incrustados (por ejemplo, 0xFF para insertar un valor de la pila) para mensajes de diagnostico formateados. PRTFN imprime un nombre de archivo Sharp MZ (17 bytes en codificacion Sharp) como texto ASCII usando la tabla de conversion ATBL.
ATBL (tabla de conversion ASCII-a-Sharp): Una tabla de busqueda de 256 bytes que mapea codigos de caracteres ASCII a sus equivalentes Sharp MZ y viceversa. La serie Sharp MZ utiliza una codificacion de caracteres propietaria de 8 bits donde los caracteres imprimibles tienen puntos de codigo diferentes a ASCII -- muchos caracteres comunes (letras, digitos, puntuacion) estan desplazados o reordenados. Cualquier codigo que muestre un nombre de archivo almacenado en codificacion Sharp en el terminal debe pasar cada byte a traves de esta tabla.

rfs_bank7.asm -- Comandos de Diagnostico (User ROM Bank 7)
Funcion: Implementa los comandos R (prueba de DRAM) y T (prueba de temporizador) en la compilacion RomDisk.
MEMTEST (comando R): Realiza una prueba de patron de bit ambulante de escritura/verificacion a traves de todo el espacio de RAM del usuario (0x1200-0xCFFF). Escribe cada uno de los 8 patrones de un solo bit (0x01, 0x02, 0x04, ..., 0x80) en cada byte del rango, luego lee y verifica cada byte. Cualquier discrepancia se reporta con su direccion y los valores esperado/real. Ejecute este comando despues de anadir cualquier estructura de datos nueva residente en RAM para verificar que el direccionamiento es correcto antes de que las nuevas estructuras sean usadas por otro codigo.
TIMERTST (comando T): Ejerce el Temporizador de Intervalos Programable 8253 programandolo en varios modos y verificando que cuenta y expira como se espera. Util para diagnosticar maquinas donde las operaciones de cinta son poco fiables -- un comportamiento incorrecto del 8253 se manifiesta como errores sistematicos de temporizado en las mediciones de tasa de bits del CMT.

rfs_mrom.asm -- Utilidades de Monitor ROM (Monitor ROM Bank 3)
Funcion: Proporciona las rutinas de escaneo de ROM y carga de archivos MZF que deben ejecutarse desde el espacio de Monitor ROM en lugar del espacio de User ROM.
Por que un banco de Monitor ROM separado? Los comandos IR y LR enumeran imagenes de programas MZF almacenados en los bancos superiores de la Flash de User ROM (los bancos de User ROM por encima de 11 contienen programas MZF empaquetados). Para escanear uno de estos bancos, el firmware debe conmutar la ventana de User ROM para apuntar a ese banco. Pero el codigo de escaneo en si reside en la User ROM -- si conmuta el banco de User ROM, reemplaza instantaneamente su propio codigo con un banco diferente y se cuelga.
La solucion es colocar el bucle de escaneo en el Monitor ROM banco 3. La conmutacion de banco del Monitor ROM (via BNKSELMROM) es completamente independiente de la conmutacion de banco de la User ROM (via BNKSELUSER). El codigo ejecutandose en el Monitor ROM banco 3 puede ciclar libremente a traves de los bancos de User ROM 12, 13, 14... para enumerar sus cabeceras MZF sin perturbar jamas el codigo del Monitor ROM que realmente se esta ejecutando.
Funciones clave:
  • ROMDIR: Escanea todos los bancos de User ROM por encima de 11, lee cada cabecera MZF de 128 bytes desde el inicio de cada banco y construye un directorio ROM residente en RAM. El directorio es usado por el comando IR para mostrar una lista de programas residentes en ROM.
  • ROMLOAD: Dado un numero de archivo del directorio ROM, conmuta la ventana de User ROM al banco apropiado, lee la cabecera MZF para encontrar la direccion de carga y el tamano de datos, copia los datos del programa desde la User ROM a la direccion de carga destino en RAM, y opcionalmente salta a la direccion de ejecucion. La variante LRNX retorna al prompt de comandos RFS en lugar de auto-ejecutar.

Driver SPI: Hardware vs Software

El driver SPI en rfs_bank2.asm esta implementado de tres formas, seleccionadas completamente en tiempo de ensamblaje. La seleccion se controla mediante los tres flags mutuamente exclusivos en rfs_definitions.asm:
HW_SPI_ENA   EQU 1    ; 74HCT595/74HCT165 hardware shift registers on RomDisk v2+ PCB
SW_SPI_ENA   EQU 0    ; Software bit-bang SPI using the RomDisk v2+ I/O port bits
PP_SPI_ENA   EQU 0    ; Software bit-bang SPI via the Sharp MZ-80A parallel printer port

SPI Hardware (HW_SPI_ENA = 1)
Disponible en PCB RomDisk v2.0 y posteriores. El PCB lleva un registro de desplazamiento de salida serie 74HCT595 (MOSI/CLK) y un registro de desplazamiento de entrada paralela 74HCT165 (MISO/CLK) cronometrados por logica de hardware dedicada funcionando a 8 MHz -- ocho veces el reloj de bus de 2 MHz del Z80.
Enviar un byte son dos escrituras de memoria: escribir el byte en HWSPIDATA (0xEFFB), luego escribir cualquier valor en HWSPISTART (0xEFFC). El hardware envia los 8 bits automaticamente en aproximadamente 1 us. Recibir un byte es similar: escribir en HWSPISTART para recibir 8 bits, luego leer HWSPIDATA. El Z80 solo necesita el tiempo para ejecutar dos instrucciones de escritura de memoria entre bytes -- los registros de desplazamiento de hardware operan concurrentemente.
Como HWSPIDATA y HWSPISTART residen dentro del rango del latch codificado 0xEFF8-0xEFFF, solo son accesibles mientras los registros de control estan desbloqueados (es decir, despues de la secuencia de 16 lecturas). Las rutinas SDINIT, SDREAD y SDWRITE en el banco 2 asumen que los registros de control ya estan desbloqueados cuando son llamadas, lo cual siempre es el caso dentro del entorno de ejecucion RFS.

SPI Software (SW_SPI_ENA = 1)
Disponible en PCB RomDisk v2.0 y posteriores como alternativa de menor costo a los registros de desplazamiento de hardware. El firmware conmuta manualmente bits individuales del registro BNKCTRL (0xEFFF) para controlar las lineas de reloj SPI (BBCLK) y datos MOSI (BBMOSI), y lee el bit MISO de BNKCTRL para los datos entrantes. Cada bit requiere multiples escrituras a BNKCTRL -- conmutar reloj alto, conmutar reloj bajo -- dando aproximadamente 20-40 us por byte a 2 MHz de reloj Z80, aproximadamente 40x mas lento que el SPI hardware.
El bloque de codigo SW_SPI_ENA en SPIOUT envio bit a bit cada byte MSB-primero usando un bucle que lee el estado actual de BBMOSI y BBCLK, modifica el bit relevante y escribe de vuelta a BNKCTRL. Aplica el mismo requisito de desbloqueo del latch codificado -- BNKCTRL solo es escribible despues de la secuencia de 16 lecturas.

SPI por Puerto Paralelo (PP_SPI_ENA = 1)
La implementacion original del RomDisk v1, utilizando el puerto de impresora paralelo Centronics del Sharp MZ-80A como un bus SPI improvisado. Las lineas de datos del puerto de impresora (D0-D7) se reasignan: un bit controla el reloj SPI (CLOCK), un bit controla los datos MOSI (DOUT), un bit controla el chip select (CS), y un bit lee los datos MISO (DIN) del registro de estado del puerto.
Enviar un byte en SPIOUT (ruta PP_SPI_ENA): el byte se rota a la izquierda tres veces para alinear el bit 7 con la posicion del pin DOUT, luego un bucle de 8 iteraciones controla DOUT y el reloj alto/bajo usando tres instrucciones OUT (SPI_OUT), A por bit. SPIINIT envia 80 bits '1' conmutando las lineas de reloj y datos 80 veces con DJNZ. Todos los accesos al puerto paralelo usan instrucciones de puerto de E/S (IN / OUT) en lugar de registros mapeados en memoria.
PP_SPI_ENA no requiere el desbloqueo del latch codificado -- el puerto paralelo reside en el espacio de direcciones de E/S del Z80, no en el espacio de direcciones de memoria, asi que siempre es accesible. Esto fue intencional para el diseno v1 donde el circuito del latch codificado aun no existia.

Elegir una Variante SPI
  HW_SPI_ENA SW_SPI_ENA PP_SPI_ENA
PCB required v2.0+ v2.0+ v1.x
Approx. byte rate ~1 µs/byte ~30 µs/byte ~50 µs/byte
Coded latch required Yes Yes No
Additional ICs 74HCT595, 74HCT165 None None
Suitable for All current builds Low-cost v2 variant Legacy v1 boards

Anadir un Nuevo Comando de Monitor

El siguiente ejemplo anade un comando PEEK que lee e imprime un unico byte de una direccion dada. El manejador pertenece al banco 3 (utilidades de memoria).

Paso 1: Escribir el manejador en rfs_bank3.asm

; In rfs_bank3.asm (bank 3, memory utilities):
PEEK:   CALL  HLHEX              ; Parse 4-digit hex address from input buffer into HL
        LD    A,(HL)              ; Read the byte at that address
        CALL  PRTHX              ; Print A as 2 hex digits
        RET
Los parametros estan disponibles en el buffer de entrada del monitor inmediatamente despues de la cadena del comando. HLHEX es una rutina de utilidad (disponible en el banco 5 o via la tabla de saltos) que lee 4 digitos hexadecimales del buffer de entrada y devuelve el valor de 16 bits en HL. PRTHX imprime el acumulador como dos digitos hexadecimales en mayusculas.

Paso 2: Anadir una entrada en la tabla de comandos en rfs.asm

; In rfs.asm, within the CMDTABLE block (inside IF BUILD_ROMDISK+BUILD_PICOZ80 = 1):
;
; Flags byte: not-end (bit7=0), not-exact (bit6=0),
;             bank 3 (bits5:3 = 011 = 0x18), length 4 (bits2:0 = 100 = 0x04)
    DB  000H | 000H | 018H | 004H
    DB  "PEEK"
    DW  PEEK
Coloque esta entrada antes de cualquier entrada mas corta que comparta los mismos caracteres iniciales para evitar que la entrada mas corta coincida primero. El byte de flags se construye como: 000H (no fin de tabla) OR 000H (no coincidencia exacta) OR 018H (banco 3: 0b011 desplazado a la izquierda 3 = 0x18) OR 004H (longitud de cadena de comando 4).

Paso 3: Anadir texto de ayuda en rfs_bank6.asm

; In rfs_bank6.asm, within the HELPSCR block (before the 000H terminator):
    DB  "PEEKXXXX - read byte at XXXX",    00DH
La pantalla de ayuda usa mayusculas en todo momento (los caracteres en minuscula son dificiles de incrustar en la codificacion de caracteres Sharp sin calcular manualmente los valores de byte).

Paso 4: Compilar

cd /dvlp/Projects/MZ80A_RFS/software/RFS
./build.sh
El ensamblador reportara un error si el banco 3 ahora excede los 2 KB. Si eso ocurre, busque codigo muerto, cadenas de mensajes no utilizadas o rutinas de utilidad duplicadas que puedan eliminarse de ese banco o moverse al banco 5 (actualmente vacio).

Anadir Soporte de Nuevo Hardware

Anadir una Nueva Variante SPI
Para anadir una nueva variante de hardware SPI -- por ejemplo, un segundo diseno de puerto paralelo con asignaciones de bits diferentes (PP2_SPI_ENA):
  1. Anadir el flag a rfs_definitions.asm:
PP2_SPI_ENA  EQU 0    ; Second parallel port SPI variant (custom hardware)
  1. Anadir una asercion al inicio de rfs_bank2.asm para detectar la habilitacion dual accidental:
; Guard: only one SPI flag may be set at a time.
; GLASS does not have a built-in ASSERT directive, so encode this as a build-time
; value check. If more than one flag is set, the total sum exceeds 1 and the error
; manifests as wrong code being assembled into the SPI driver functions.
; (Document this constraint prominently in the comment block above SDINIT.)
  1. Anadir bloques de ensamblaje condicional en rfs_bank2.asm para cada funcion SPI (SPIINIT, SPICS, SPIOUT, SPIIN). Siga el patron IF/ELSE/ENDIF anidado existente:
SPIOUT:     IF HW_SPI_ENA = 1
              ; Hardware SPI path (existing code)
              LD    (HWSPIDATA),A
              LD    (HWSPISTART),A
              RET
            ELSE
              IF SW_SPI_ENA = 1
                ; Software bit-bang path (existing code)
              ELSE
                IF PP2_SPI_ENA = 1
                  ; New PP2 path:
                  ; (implement bit-bang for the new port layout here)
                  RET
                ELSE
                  ; Original PP_SPI_ENA (centronics) path (existing code)
                ENDIF
              ENDIF
            ENDIF
  1. Definir las nuevas constantes de puerto en rfs_definitions.asm junto con las constantes existentes SPI_OUT, DOUT_MASK, CLOCK_HIGH etc., protegidas con IF PP2_SPI_ENA = 1 ... ENDIF para evitar conflictos de simbolos.
  2. Actualizar build.sh si la nueva variante requiere un diseno de imagen Flash diferente o un nombre de archivo de salida diferente.

Anadir una Nueva Compilacion de Plataforma
Para portar RFS a una nueva plataforma de hardware (por ejemplo, una nueva reimplementacion basada en FPGA del MZ-80A):
  1. Anadir un flag BUILD_* en rfs_definitions.asm: BUILD_NEWBOARD EQU 0.
  2. Anadir constantes de direccion si la nueva tarjeta mapea ventanas de ROM en direcciones diferentes. La variacion mas comun es la direccion base de la User ROM y las direcciones de los registros de control de bancos.
  3. Anadir bloques de ensamblaje condicional a lo largo del codigo fuente para cada punto donde el comportamiento del hardware difiere: direcciones de E/S del latch de banco, registros del controlador SPI, deteccion de presencia de tarjeta SD, conmutacion del modo de visualizacion y el codigo de deteccion de plataforma del punto de entrada MONITOR en rfs.asm.
  4. Anadir una nueva variante de stub de conmutacion de banco en cada archivo de banco si el mecanismo de seleccion de banco de la nueva plataforma difiere tanto del latch codificado como del esquema de puertos FusionX. El stub en UROMBSTBL debe funcionar correctamente en arranque en frio antes de que se haya ejecutado cualquier inicializacion.
  5. Actualizar build.sh con una nueva seccion de compilacion que establezca BUILD_NEWBOARD=1 y produzca la imagen ROM apropiada para el diseno del nuevo chip Flash.

Consejos de Depuracion

Habilitar salida de depuracion: Establezca ENADEBUG EQU 1 en rfs_definitions.asm antes de compilar. Esto incluye instrucciones de impresion de diagnostico adicionales en puntos estrategicos de la secuencia de inicializacion de la tarjeta SD, respuestas de SDCMD y analisis del directorio SDCFS. El codigo extra es condicional y no tiene efecto en el tamano de la imagen ROM del RomDisk cuando esta deshabilitado.
Volcar el area de entrada del User ROM banco 0: Escriba D E800 para volcar los primeros 320 bytes del banco actual de User ROM. Los primeros bytes deberian mostrar el NOP en 0xE800, seguido por los bytes de la macro HWSELROM, seguido por una instruccion JP. El stub de conmutacion de banco en 0xE820 deberia contener patrones reconocibles de secuencias PUSH AF / LD A, n. Si el volcado parece datos aleatorios, el latch codificado puede no haberse inicializado correctamente y se esta seleccionando el banco incorrecto.
Verificar el registro de control de banco: Escriba D EFF8 para volcar el area del registro de control de banco. Despues de realizar una conmutacion de banco manual, el byte en 0xEFFF deberia reflejar el numero de banco que escribio. Si no cambia, verifique que la secuencia de desbloqueo del latch codificado de 16 lecturas se esta ejecutando antes de la escritura.
Verificar el conteo de desbloqueo del latch codificado: Si las escrituras al registro de control de banco parecen no tener efecto, la causa mas comun es que la secuencia de 16 lecturas no se esta completando. Esto puede ocurrir si una instruccion de bucle en el banco realiza lecturas de 0xEFF8-0xEFFF durante la ejecucion normal (vea la advertencia sobre DJNZ en la seccion de conmutacion de bancos). Cuente los ciclos de lectura en la secuencia de desbloqueo y verifique que el contador del bucle esta establecido exactamente a 16.
v2.1 arranca al monitor SA-1510 sin el prompt + RFS: Si la maquina arranca en el monitor nativo SA-1510 y la linea de inicio + RFS de RFS no aparece, el punto de entrada de la User ROM en 0xE800 no se esta llamando. Verifique que el latch codificado no esta siendo disparado inadvertidamente por ciclos de refresco de DRAM -- la puerta AND (D1/D2) en v2.1 fue anadida especificamente para prevenir que los ciclos de refresco incrementen el contador 74HCT191. En tarjetas v2.0 sin esta puerta, los ciclos de refresco pueden alcanzar Terminal Count antes de que se ejecute el punto de entrada de la ROM.
Ejecutar MEMTEST despues de anadir datos residentes en RAM: Escriba R inmediatamente despues de anadir nuevas estructuras de datos o variables residentes en RAM para detectar errores de direccionamiento tempranamente. Una direccion fallida en el rango 0x1200-0xCFFF que se correlaciona con el tamano de una nueva estructura indica un error de uno en el calculo de la direccion en lugar de un chip de RAM defectuoso.
Fallos de inicializacion de tarjeta SD: Si los comandos SD devuelven codigos de respuesta inesperados con ENADEBUG habilitado, verifique que el temporizado del chip select SPI es correcto -- CS debe estar activado (bajo) antes de CMD0 y mantenido durante todo el intercambio de comando/respuesta. Bajo HW_SPI_ENA, verifique que el bit SDCS en BNKCTRL se esta estableciendo y limpiando correctamente por SPICS. Bajo PP_SPI_ENA, verifique que el registro de salida del puerto paralelo esta inicializado antes de la primera llamada a SPIINIT.
Fallos de llamada entre bancos: Si una llamada entre bancos parece ejecutar codigo incorrecto o retorna con corrupcion de registros, verifique que el stub de conmutacion de banco en el banco destino coincide byte a byte con el del banco 0. Cada banco debe tener una copia identica del stub en UROMBSTBL. Use D E820 para volcar el stub del banco 0, luego conmute al banco destino manualmente y vuelque el mismo rango de direcciones para comparar.

Sitios de Referencia

Resource Link
RomDisk hardware page /sharpmz-upgrades-romdisk/
RFS project page /sharpmz-upgrades-rfs/
RFS User Manual /sharpmz-upgrades-rfs-usermanual/
RFS Technical Guide /sharpmz-upgrades-rfs-technicalguide/
RFS Developer’s Guide (RFS) /rfs-developersguide/
TZFS Developer’s Guide /tzfs-developersguide/
tranZPUter FusionX page /tranzputer-fusionx/
GLASS Z80 Assembler Bundled in software/RFS/tools/glass.jar
Zilog Z80 CPU User Manual Standard datasheet — bus timing, instruction set, register reference
WD1773 FDC Datasheet Western Digital — floppy disk controller I/O port reference
SD Card Physical Layer Spec SD Association — CMD0/CMD8/ACMD41/CMD17/CMD24 protocol
Sharp MZ-80A Service Manual Hardware schematics, SA-1510 ROM listing, memory map