CP/M v2.23

Descripcion general

Linux y Windows son hoy en dia los sistemas operativos basicos en uso en los microordenadores, pero hace anos todo empezo con Digital Research creando el Control Program/Monitor (CP/M). CP/M fue uno de los primeros sistemas operativos reales para microordenadores que proporcionaba medios comunes para ejecutar aplicaciones en hardware diverso. Cualquier maquina que ejecute CP/M tiene acceso a miles de programas y asi comenzo la busqueda de poner CP/M en funcionamiento en el Sharp MZ80A.

Micro Technology creo una version de CP/M para el Sharp MZ80A, pero como carecia de una pantalla de 80 columnas, no resultaba muy util sin una mejora. Un vistazo alrededor mostro que terceros como Kuma desarrollaron una mejora de 80 columnas que podia conseguirse mas tarde a traves del SUC, pero CP/M en el MZ80A, aunque mencionado en muchos articulos, es en realidad bastante dificil de obtener en 2020. Diversos sitios excelentes como original.sharpmz.org ofrecen las versiones 80K/80B/800 pero no para el MZ80A.

Desarrolle la placa de mejora de color de 80 columnas y el Rom Filing System con el objetivo principal de hacer realidad CP/M en el MZ80A. Es muy facil en el proyecto de emulador de hardware basado en FPGA anadir cambios para dar cabida a diversas salidas de columnas, color o graficos, pero hacerlo en el hardware original real realizando cambios minimos en una maquina vintage fue mas un reto y tambien algo de deseo personal desde que posei esta maquina por primera vez en 1983. La mayoria de las mejoras que se ven del pasado requieren cortes y puentes en la PCB original, lo cual especificamente no queria; quiero mantener el hardware original tal como lo hizo Sharp! El unico cambio que hago en mis mejoras a la PCB original es zocalar un chip (IC8 74LS165, el registro de desplazamiento de video) lo cual podria hacerse facilmente si fallara en uso y fuera reemplazado, de ese modo la maquina es 100% original y puede devolverse a su estado de fabrica original muy facilmente.

Asi pues empece a intentar poner CP/M en funcionamiento, incluso con una plethora de informacion en la red, no fue una tarea facil. En primer lugar, obtener la version de CP/M de Micro Technology para el MZ80A resulto muy esquiva, asi que recurri a las versiones MZ80K y MZ80B. Entonces me tope con los diversos formatos de disco peculiares, con el MZ80A disenado para leer datos invertidos sumandose al embrollo. Para resumir, acabe decidiendo escribir mi propia version basada en ROM del CBIOS y mezclarla con el BDOS+CCP de CP/M v2.23. Esta seccion detalla la informacion sobre este trabajo en consecuencia.

Proceso de arranque de CP/M

El arranque de CP/M se produce en dos fases:

  1. Usando el software original de control del disquete AFI, leer un sector de arranque invertido, comprobar que contiene en 0x0000 el codigo de control 0x02 + “IPLPRO”, y luego pasar el control al cargador de arranque encapsulado
  2. Cargar, comenzando en 0x9C00, el CCP, el BDOS y el CBIOS. El CBIOS toma ahora el control y aplica un formato de disco diferente y usa una logica de controlador FDC diferente (es decir, vuelve a invertir los datos).
Con este fin desensamble la ROM AFI del MZ80A (que puede encontrarse en el repositorio) para entender que acciones realizaba. La carga inicial comprueba si el disco es un disco arrancable en el MZ80A. Para el MZ80K el marcador de un disco arrancable (ademas de que el formato es muy diferente y no invierte los datos) era 01 + IPLPRO en los bytes iniciales del primer sector. Para el MZ80B esto era 03 + IPLPRO.

Como no tenia una copia de CP/M para MZ80A intente cargar la version MZ80K, pero los datos no invertidos significaban que tenia que convertir un disco de arranque MZ80K a formato MZ80A. Una vez hecho esto, intente arrancar CP/M pero habia incompatibilidades, por ejemplo el controlador de disco!! Entonces dedique tiempo a examinar las versiones MZ80B y MZ800 de CP/M de Micro Technologies, que de nuevo usaban formatos de disco diferentes y al final decidi que el mejor enfoque seria construir un CP/M a medida y escribir mi propio CBIOS.


Actualizacion — soporte directo de discos MZ-80K: el cargador de arranque CP/M del RFS y el CBIOS ahora detectan automaticamente el formato de disco original del MZ-80K de forma directa, por lo que ya no es necesario convertir primero los discos MZ-80K al formato MZ-80A. Al arrancar a traves de la tarjeta MZ80AFI, el controlador informa del tamano de sector existente en el disco (128 bytes para un disco MZ-80K, 256 bytes para un disco MZ-80A). Un disco no invertido de 128 bytes que contiene el marcador 01h + IPLPRO es reconocido como un disco CP/M del MZ-80K: las pistas reservadas del sistema se cargan en orden y se pasa el control al cargador de arranque encapsulado (JP 09803H). Una vez en ejecucion, los discos CP/M originales del MZ-80K se montan directamente para lectura como unidades CP/M C: y D:, junto con las unidades de tarjeta SD y de ROM. Esto funciona en un MZ-80A real equipado con la tarjeta MZ80AFI, y en la picoZ80 ejecutando ya sea la persona MZ-80A o la nueva persona MZ-80K con una interfaz MZ80AFI.

CBIOS

CP/M esta construido a partir de 3 modulos distintos, el CCP (Console Command Processor), el BDOS (Basic Disk Operating System) y el CBIOS (Custom Basic Input Output System). Generalmente el CCP + BDOS son estandar y el CBIOS se personaliza segun el hardware subyacente.

Los 3 componentes se cargarian arrancando desde el disquete, cargados en memoria (0x9C00 para el MZ80K/A) y se pasaria el control al CBIOS que configuraria la maquina antes de entregar el control al CCP. En condiciones normales de funcionamiento, cualquier aplicacion cargada llamaria al BDOS para realizar servicios tales como escribir en la consola, obtener entrada de teclas, acceso a disco, etc., desde una API bien definida, pero si no necesitaba los servicios del BDOS podia llamar al CBIOS directamente usando su API y a su vez podia usar la RAM del CCP+BDOS para ganar mas espacio de programa. Cuando una aplicacion termina, salta al vector 0x0000 iniciando un arranque en caliente (Warm start) que implica la recarga del CCP+BDOS.

La forma en que esta escrito CPM no se presta a ser almacenado en ROM, ya que se automodifica/usa variables incrustadas, pero para el CBIOS es otra historia. Es posible colocar el CBIOS en ROM para ganar mas RAM y, teniendo acceso al Rom Filing System con sus bancos de ROM paginados, esta es la via que tome.

Para crear un CBIOS hay que proporcionar los siguientes metodos de la API:

Metodo de la API Descripcion
BOOT Arranque en frio, inicia todo el hardware antes de la invocacion del CCP.
WBOOT Arranque en caliente, deshace cualquier cambio de hardware y luego recarga el CCP+BDOS antes de invocar el CCP.
CONST Estado de la consola, comprueba si hay una pulsacion de tecla esperando a ser leida.
CONIN Entrada de consola, obtiene una tecla del teclado, espera si no hay ninguna disponible.
CONOUT Salida de consola, envia un caracter a la pantalla.
LIST Salida del dispositivo de listado, envia un caracter al dispositivo de listado (es decir, la impresora).
PUNCH Salida del dispositivo perforador, envia un caracter al dispositivo perforador (si, en los anos 70 se usaban cinta o tarjetas perforadas)!
READER Entrada del lector, lee un caracter del dispositivo lector (es decir, cinta de papel)!
HOME Mueve la cabeza del disco actualmente seleccionado a la pista 0.
SELDSK Selecciona/activa un disco.
SETTRK Establece la pista del disco para la siguiente operacion de lectura/escritura.
SETSEC Establece el sector del disco en la pista seleccionada para la siguiente operacion de lectura/escritura.
SETDMA Establece la direccion de memoria del disco, la ubicacion donde se leeran/almacenaran los datos.
READ Lee un sector del disco.
WRITE Escribe un sector del disco.
LISTST Estado del dispositivo de listado, comprueba si el dispositivo de listado esta listo para aceptar un nuevo caracter.
SECTRN Traduccion de sector, traduccion de sector logico a fisico para adaptarse a hardware especifico o mejorar la respuesta del subsistema de disco.
Parece un requisito sencillo, pero luego hay que considerar que una maquina como el MZ80A no tiene su propia BIOS y el firmware en su ROM, cuando se ejecuta bajo CP/M, se reubica en 0xC000 y por tanto resulta inutilizable. Ademas el firmware de control del disquete es muy basico y solo se ocupa de arrancar un disco.

Un requisito adicional por encima de los mecanismos basicos de entrada/salida de caracteres que CP/M proporciona, es que la mayoria de las aplicaciones esperan que haya un terminal inteligente (Smart Terminal) delante de la maquina CP/M para proporcionar funcionalidad avanzada de pantalla y teclado. Esto normalmente seria en forma de un terminal tal como un DEC VT52 o VT100. Como el MZ80A tiene su propia pantalla y teclado, esta funcionalidad inteligente tiene que escribirse.

Asi pues, para escribir el CBIOS, es necesario codificar los siguientes submodulos de firmware:

Submodulo Descripcion
E/S basica de pantalla Las funciones de bajo nivel para colocar un caracter en la pantalla, borrar la pantalla, etc.
E/S avanzada de pantalla Inteligencia para posicionar la salida en pantalla, borrar porciones de la pantalla, atributos especiales como negrita, etc.
E/S de teclado Escanear y devolver codigos de tecla, mapear a ASCII segun se requiera.
E/S de disco Proporcionar facilidades para leer y escribir multiples sectores de disco.
Habiendo desensamblado previamente el monitor Sharp SA-1510 tenia una buena posicion de partida para proporcionar las facilidades basicas de pantalla y teclado; desensamblar el firmware AFI del disquete proporciono una vision del codigo necesario para leer un disquete, mas especialmente de sus carencias. El MZ80A es un ordenador de 2MHz y no tiene la velocidad para atender el flujo de entrada/salida del disco, tiene que apoyarse en una pieza de hardware que pagina un banco de ROM basado en la senal de Solicitud/Disponibilidad de Datos (Data Request/Ready) del FDC. Asi pues los componentes del FDC requirieron un trabajo significativo. Para la E/S avanzada de pantalla, decidi usar el estandar ANSI y conseguir el emulador de terminal del Amstrad CPC de Ewen McNeill. Inicialmente pense que seria una simple extraccion e insercion de su analizador ANSI, pero esto resulto ser una cantidad de trabajo importante. A veces la opcion mas facil es la mas dificil!!

Toda esta funcionalidad ocupa espacio y se ha repartido de la siguiente manera:

ROM Direccion Descripcion
MROM de 4K (Monitor ROM reubicada desde 0x0000 - 0x0FFF) 0xC000 - 0xCFFF CBIOS que proporciona la API de CP/M, rutinas de inicializacion, rutinas del controlador de disco ROM, rutinas de interrupcion.
ROM paginada de 2K 0xE800 - 0xEFFF, Banco 12 Sonido y melodia basicos, RTC, teclado y funcionalidad auxiliar.
ROM paginada de 2k 0xE800 - 0xEFFF, Banco 13 E/S de pantalla y analizador de terminal ANSI.
ROM paginada de 2k 0xE800 - 0xEFFF, Banco 14 Funcionalidad del controlador de tarjeta SD.
ROM paginada de 2k 0xE800 - 0xEFFF, Banco 15 Funcionalidad del controlador de disquete.

Unidades de disco CPM

Como esta implementacion de CPM y BIOS a medida usa 3 controladores de unidades de disco diferentes, algunos de los cuales pueden no estar presentes en un momento dado, las unidades se crean dinamicamente dentro de CPM durante el arranque en frio.

El orden de las unidades se muestra en la siguiente tabla. Los discos CP/M originales del MZ-80K (y del MZ-80A) leidos a traves de la tarjeta MZ80AFI aparecen como las unidades de Disco Floppy en esta tabla — normalmente C: y D: cuando tambien hay presente una unidad de ROM y/o una tarjeta SD.

Rom Drive # Presente 0 1 2 Presente 0 1 2
Unidad ROM n/a   A A,B n/a   A A,B
Disco Floppy Si A,B B,C C,D No      
Tarjeta SD Si C,D,E,F D,E,F E,F,G Si A,B,C,D,E B,C,D,E C,D,E,F
Tarjeta SD No       Si      
El limite en el numero de unidades es CPM (limite de 16 unidades) y la cantidad de RAM asignada a las unidades, gobernada por la variable 'CSVALVEND - CSVALVMEM' que se establece en el fichero CPM_Definitions.asm del repositorio. La asignacion de unidades es dinamica, por lo que cuanta mas memoria se asigne mas unidades estaran disponibles. La tarjeta SD puede contener cientos de unidades de disco SD de 16MB, asi que el problema es puramente la RAM asignada para su uso.

Caracteristicas

Ademas de la funcionalidad estandar de la BIOS, se han anadido las siguientes caracteristicas al CBIOS.

  • Reloj en tiempo real con granularidad de 50mS
  • Teclado controlado por interrupciones con buffer y autorrepeticion.
  • Bloqueo de teclas en tres modos: Normal, Caps Lock, Shift Lock
  • Funcionalidad de terminal ANSI
  • Unidades de disquete reasignables de tamano 1.44M, 720K y 320K
  • Arranque y lectura directos de discos CP/M originales (sin convertir) del MZ-80K a traves de la tarjeta MZ80AFI, detectados automaticamente por el tamano de sector y montados como unidades C:/D:
  • Unidades ROM reasignables de tamano 240K (modificable mediante configuracion)
  • Discos duros de tarjeta SD de 16Mb reasignables.
  • Salida al monitor mediante SHIFT+GRAPH+BREAK.

Configuracion y compilacion automatizadas (recomendado)

CP/M para RFS se ensambla y empaqueta como parte de la compilacion normal de RFS, por lo que la forma mas facil de producir el CBIOS, la aplicacion MZF de CP/M y las imagenes de disco de CP/M es el script de configuracion automatizado para tu plataforma. Cada script es autonomo — copia solo el archivo unico para tu sistema operativo y ejecutalo. Instala los prerrequisitos, clona el repositorio de RFS, descarga el paquete de contenido de ~110 MB (RFS_Files.zip, que incluye el software de CP/M) y puede ejecutar la primera compilacion por ti, sin requerir conocimientos profundos de la cadena de herramientas. Los pasos manuales, herramienta por herramienta, mas abajo son para usuarios avanzados y recompilaciones parciales.
Script Plataforma Notas
setup_RFS.sh macOS / Linux / WSL Instala un JRE de Java (ensamblador GLASS), una cadena de herramientas de C + make (para compilar el submodulo incluido cpmtools), perl, git, unzip, curl, y (en macOS) GNU coreutils. La primera compilacion es ./build.sh -m.
setup_RFS_windows_native.ps1 Windows 10 / 11 — nativo, sin WSL (recomendado) Usa winget para instalar Git for Windows y un JRE Temurin 17, y despues compila a traves de Git Bash. No se necesita compilador de C — se incluyen los precompilados tools\cpmcp.exe y tools\sdtool.exe.
setup_RFS_windows.ps1 Windows 10 / 11 — via WSL2 / Ubuntu Instala WSL2 + Ubuntu si faltan (reinicio unico), y despues ejecuta setup_RFS.sh dentro de Ubuntu.

macOS / Linux / WSL — setup_RFS.sh

chmod +x setup_RFS.sh
./setup_RFS.sh

Windows 10 / 11 (nativo — recomendado) — setup_RFS_windows_native.ps1, desde un simbolo del sistema de PowerShell:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows_native.ps1

Windows 10 / 11 (via WSL2) — setup_RFS_windows.ps1, desde una PowerShell de Administrador:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows.ps1

Los scripts respetan las variables de entorno RFS_REPO_URL (por defecto https://git.eaw.app/eaw/RFS.git) y RFS_FILES_URL (ubicacion del paquete de contenido) para anular las preguntas interactivas. La compilacion escribe las imagenes ROM del Monitor/Usuario (con el CBIOS de CP/M y la aplicacion MZF de CP/M empaquetados) y la imagen de tarjeta SD que contiene las imagenes de disco de CP/M en el directorio roms/. Para el recorrido completo paso a paso, vease la Guia tecnica de RFS — Sistema de compilacion.


Construccion de CPM

Construir CP/M implica ensamblar el codigo fuente en lenguaje ensamblador Z80 en un binario de codigo maquina y luego crear un disco de arranque o, en el caso de esta implementacion, un CBIOS basado en ROM y una aplicacion arrancable en formato MZF que se almacena en ROM.

Para lograrlo se necesitan varias herramientas y por el momento es un proceso bastante manual.

Rutas

Para facilitar la lectura, los siguientes nombres cortos se refieren a la ruta correspondiente en este capitulo.

Nombre corto  
[<ABS PATH>] La ruta donde se extrajo este repositorio en su sistema.
<software> [<ABS PATH>]/MZ80A_RFS/software
<roms> [<ABS PATH>]/MZ80A_RFS/software/roms
<CPM> [<ABS PATH>]/MZ80A_RFS/software/CPM
<tools> [<ABS PATH>]/MZ80A_RFS/software/tools
<MZF> [<ABS PATH>]/MZ80A_RFS/software/MZF
<MZB> [<ABS PATH>]/MZ80A_RFS/software/MZB

Herramientas

Todo el desarrollo se ha realizado bajo Linux, especificamente Debian/Ubuntu. Uso Windows para grabar las RAM y para usar la version GUI de CP/M Tools, pero no he dedicado tiempo a construir el RFS bajo Windows. En su momento creare una imagen Docker con todas las herramientas necesarias instaladas, pero entretanto, para ensamblar el codigo Z80, los programas en C y trabajar con el software de CP/M y las imagenes de disco CP/M, necesitara obtener e instalar las siguientes herramientas.

Z80 Glass Assembler - Un ensamblador Z80 para convertir ficheros ensamblador en codigo maquina.
samdisk - Una herramienta de manipulacion de disco de bajo nivel basada en linea de comandos multiplataforma.
cpmtools - Una herramienta de manipulacion de discos CP/M de linea de comandos multiplataforma.
CPMToolsGUI - Una herramienta GUI basada en Windows para la manipulacion de discos CP/M.
z88dk - Un excelente kit de desarrollo en C para la CPU Z80.
sdcc - Otro excelente compilador de C para dispositivos pequenos (Small Device C compiler), siendo el Z80 uno de sus objetivos. z88dk proporciona una version mejorada (para el Z80) de esta herramienta dentro de su paquete.

Software

La construccion de las imagenes de software puede hacerse clonando el repositorio y ejecutando algunos de los scripts de shell y binarios proporcionados.

Script Descripcion
assemble_cpm.sh Un script de shell para construir el binario de CPM, la aplicacion CPM en formato MZF para cargar via RFS y las unidades ROM de CPM 0 y 1
assemble_rfs.sh Un script bash para construir las imagenes ROM del Rom Filing System.
assemble_roms.sh Un script bash para construir todas las ROMS estandar del MZ80A, tales como la ROM del monitor SA-1510.
make_roms.sh Un script bash para construir las ROMS del RFS adecuadas para programar en las Flash RAMS de 512KByte. Estas imagenes contienen las ROMS del RFS por bancos, las diversas ROMS del sistema tales como la SA-1510 y todos los programas MZF que va a cargar el RFS.
make_cpmdisks.sh Un script bash para construir un conjunto de discos CPM, para usar como imagenes Raw en la tarjeta SD o en las unidades ROM y como formatos CPC Extended Disk para usar en un emulador de disquete o copiar a un medio fisico.
make_sdcard.sh Un script bash para crear una imagen de tarjeta SD combinando la imagen RFS y varias unidades de disco CPM. Esta imagen se copia entonces de forma binaria a la tarjeta SD y se instala en el lector de tarjetas SD del RFS.
mzftool.pl Un script perl para crear/extraer y manipular imagenes MZF.
processMZFfiles.sh Un script bash para convertir un conjunto de programas MZF en imagenes sectorizadas adecuadas para usar en las ROMS del Rom Filing System.
sdtool Un binario creado en el repositorio src/tools que construye la imagen de tarjeta SD del RFS, creando un directorio y anadiendo aplicaciones MZF/binarias a la imagen de la unidad.

El sistema CP/M se construye en 4 partes,

1. el cpm22.bin que contiene el CCP, el BDOS y un stub del CBIOS.
2. el CBIOS por bancos que tiene su fuente principal en una ROM de 4K y 4 ROMS por bancos de 2K. Estas
   se generan para anadir a la Monitor ROM por bancos del RFS y a la User ROM por bancos.
3. hasta 2 (actualmente) unidades ROM CP/M de solo lectura que pueden asignarse a cualquier letra
   de unidad CP/M.
4. conversion de los binarios generados en 1. y 3. en imagenes MZF sectorizadas adecuadas
   para anadir directamente al Rom Filing System como un programa mas.

Todo lo anterior esta codificado en el script bash assemble_cpm.sh que puede ejecutarse de la siguiente manera:

cd <software>
tools/assemble_cpm.sh

El script esta actualmente configurado para generar 1 unidad ROM CPM de solo lectura. Para anadir una segunda unidad ROM CPM, siga estas instrucciones:

1. Edit the <tools>/make_cpmdisks.sh script and change the
   variable:
   from BUILDCPMLIST="cpm22 CPM_RFS_1"
   to   BUILDCPMLIST="cpm22 CPM_RFS_1 CPM_RFS_2"

   change the variable:
   from SOURCEDIRS="CPM_RFS_[1] CPM[0-9][0-9]_* CPM_MC_5 CPM_MC_C? CPM_MC_D? CPM_MC_E? CPM_MC_F? CPM[0-9][0-9]_MZ800*" to
   to   SOURCEDIRS="CPM_RFS_[1-2] CPM[0-9][0-9]_* CPM_MC_5 CPM_MC_C? CPM_MC_D? CPM_MC_E? CPM_MC_F? CPM[0-9][0-9]_MZ800*"
   
2. Create a directory (if it doesn't exist): 
   <CPM>/CPM_RFS_2

3. Fill the directory with required CPM files to be placed in the ROM.

4. Build the image by running the make_cpmdisks.sh script or as part of the sequence of commands listed below.

Para usar CPM, es necesario crear las imagenes MonitorROM y USERROM que pueden programarse en las 2x512KByte Flash RAMS. Ejecute los siguientes comandos para construir CPM junto con todo el RFS, las ROMS y las aplicaciones en ROM:

cd <software>
tools/assemble_cpm.sh
tools/assemble_rfs.sh
tools/assemble_roms.sh
tools/make_cpmdisks.sh
tools/make_roms.sh
tools/make_sdcard.sh

La salida de los comandos anteriores son las imagenes ROM <roms>/MROM_256.bin y <roms>/USER_ROM.256.bin que deben grabarse en Flash RAMS de 512Kbyte e insertarse en los zocalos del adaptador RFS.

Las imagenes de disco CPM pueden encontrarse en <CPM>/1M44/RAW para las imagenes raw o en <CPM>/1M44/DSK para las imagenes de disco en formato CPC Extended. Estas imagenes se construyen a partir de los directorios en <CPM>; cada directorio que empieza por CPM* se empaqueta en una imagen de unidad de 1.44MB. NB. Ademas, los directorios tambien se empaquetan en todos los demas discos soportados como imagenes en un directorio correspondiente, es decir <CPM>/SDC16M para la imagen de unidad de tarjeta SD de 16MB.

La imagen de la tarjeta SD puede encontrarse en <roms>/SHARP_MZ80A_RFS_CPM_IMAGE_1.img que contiene la imagen de disco RFS <roms>/SHARP_MZ80A_RFS_IMAGE_1.img al principio seguida de siete imagenes de unidad en formato CPM que, como se indica arriba, se almacenan en <CPM>/SDC16M/RAW. Estas imagenes se construyen a partir de los directorios en <CPM> pero se anaden manualmente a las imagenes finales mediante valores fijos en el script make_cpmdisks.sh.

Las aplicaciones que se almacenan en las unidades ROM se encuentran en el directorio <MZF>. Copie cualquier aplicacion que desee a este directorio y luego ejecute el siguiente comando para procesarlas en imagenes redondeadas a sector almacenadas en el directorio <MZB>.

cd <software>
tools/processMSFfiles.sh

Las aplicaciones reales que se incorporan a la ROM se seleccionan en el script <tools>/make_roms.sh. Este script lista todas las aplicaciones requeridas y empaquetara tantas como el espacio permita en la ROM. Para asegurarse de que su aplicacion aparezca en ROM, anadala al principio de la lista (solo el nombre de fichero, no la extension .MZF), es decir:

Edit the file <tools>/make_roms.sh
Locate the line: ROM_INCLUDE=
Below this line, add your application in the format: ROM_INCLUDE+="${MZBPATH}/<YOUR APPLICATION>.${SECTORSIZE}.bin"
ie. ROM_INCLUDE+="${MZB_PATH}/A-BASIC_SA-5510.${SECTORSIZE}.bin:"
Save the file and run the commands above to build the MonitorROM and USERROMs.

Formatos de disco

Como descubri, hay cientos de formatos de disco CP/M y la serie Sharp por si sola implementa 2-3 por maquina. Al decidir que formato usar para esta implementacion de CP/M examine los formatos existentes. Al no tener acceso a discos originales del Sharp MZ80A y estando estos en formato invertido no estandar de todos modos, siendo el MZ80B similar al MZ80A pero de capacidad ligeramente superior, siendo el MZ800 un hibrido y el MZ80K de baja capacidad, opte por usar formatos estandar para disquetes de 3.5” de 1.44MB y 720K, el mismo formato fisico que los discos del Sharp MZ80A, y la unidad ROM de 240K basada en ROM.

Los formatos que estoy usando pueden manipularse con cpmtools usando las siguientes definiciones diskdefs; coloque lo anterior en el fichero diskdefs ubicado con cpmtools o CPMToolsGUI para usarlas:

   # 320K Disk for the MZ80A - Same format as the MZ800
   # but implements a cylinder in uniform manner (ie. 1 cyl
   # = 1 track x 2(heads) where as the MZ800 implements as 
   # 160 tracks, 80 x Head 1 0->79 then 80 x Head 2 80->159.
   diskdef MZ80A-A
     seclen 256
     tracks 40
     sectrk 32
     blocksize 2048
     maxdir 64
     skew 0
     boottrk 1
     os 2.2
   end
   
   # A standard format 1.44Mb Floppy format for the MZ80A
   diskdef MZ80A-1440
     seclen 512
     tracks 80
     sectrk 36
     blocksize 2048
     maxdir 128
     skew 0
     boottrk 0
     os 2.2
   end
   
   # A standard format 720K Floppy format for the MZ80A.
   diskdef MZ80A-720
     seclen 256
     tracks 80
     sectrk 36
     blocksize 2048
     maxdir 128
     skew 0
     boottrk 0
     os 2.2
   end
   
   # A 240K Rom Filing System ROM Drive image.
   diskdef mz80a-rfs
     seclen 128
     tracks 15
     sectrk 128
     blocksize 1024
     maxdir 32
     skew 0
     boottrk 0
     os 2.2
   end

   # A 16Mb fixed disk SD Card Image.
   diskdef MZ80A-SDC16M
     seclen 512
     tracks 1024
     sectrk 32
     blocksize 8192
     maxdir 512
     skew 0
     boottrk 0
     os 2.2
   end   
Dentro de CP/M estos formatos fisicos de disco se representan en el bloque de parametros de disco de la siguiente manera. Normalmente no necesita preocuparse por estos ajustes ni por los diskdefs anteriores, solo es util saberlo si necesita anadir su propio formato a medida:
Definicion MZ80A 320K Rom Filing System 1.44MB 3.5” 720K 3.5” Imagen de tarjeta SD 16MB
SPT 64 128 144 72 128
BSH 4 3 4 4 6
BLM 15 7 15 15 63
EXM 1 0 0 0 3
DSM 155 240 719 359 2047
DRM 63 31 127 127 511
AL0 128 128 192 192 192
AL1 0 0 0 0 0
CKS 16 8 32 32 0
OFF 1 0 0 0 0
Para usar programas CP/M existentes de Sharp sera necesario extraer los programas del disco y anadirlos a un formato reconocido por esta implementacion. Con este fin, las siguientes secciones describen como extraer datos de los discos de las maquinas pertinentes.

Creacion de un disco CPM

En mi desarrollo use un emulador de disquete Lotharek HxC conectado a una tarjeta de interfaz Sharp MZ80-AFI. Usando esta configuracion es posible emular cualquier unidad de disco con la que el controlador de disquete Sharp MB8866 pueda comunicarse. Asi es como llegue a y probe los formatos de 3.5", ya que estas unidades aun pueden obtenerse y tienen capacidad suficiente para la mayoria de las operaciones de CP/M.

Para crear un disco CP/M que pueda usarse en el Sharp MZ80A con esta implementacion de CP/M, necesita anadir las definiciones anteriores a su fichero diskdefs de cpmtools. Una vez anadidas, copie una de las imagenes en blanco en \<CPM\>/BLANKFD con un nombre nuevo y uselo como disco de destino, o cree uno desde dentro de CPMTools usando la definicion de disco. A continuacion anade los programas requeridos al nuevo disco, lo cual en CPMToolsGUI es simplemente un procedimiento de arrastrar y soltar.

Para usar la nueva imagen CP/M raw en el emulador de disquete o en una unidad de disquete real, es necesario convertir la imagen raw a un formato que la mayoria de las herramientas de disquete puedan leer y escribir en un disquete. En el caso del emulador de disquete Lotharek, usando su herramienta HxCFloppyEmulator v2.2.2.1 mediante Load y Export to HFE se generara una imagen SD adecuada para imitar un disquete real.

Para convertir la imagen, use una de las siguientes:

For 1.44MB Drives use:
./samdisk copy <RAW IMAGE FILE, ie. CPM00_SYSTEM.RAW> <DSK IMAGE FILE, ie.CPM00_SYSTEM.DSK> --cyls=80 --head=2 --gap3=78 --sectors=36 --interleave=4
Samdisk will automatically recognise the format from the size of the file, ie. 1474560 bytes

For 720K Drives use:
./samdisk copy <RAW IMAGE FILE, ie. CPM00_SYSTEM.RAW> <DSK IMAGE FILE, ie.CPM00_SYSTEM.DSK> --cyls=80 --head=2 --gap3=78 --sectors=36 --size=2 --interleave=4
Samdisk will automatically recognise the format from the size of the file, ie. 737280 bytes

For the MZ80A 320K Drives use:
./samdisk copy CPM00_320K_SYSTEM.RAW CPM00_320K_SYSTEM.DSK --cyls=40 --gap3=78 --head=2 --sectors=16
Samdisk will automatically recognise the format from the size of the file, ie. 327680 bytes

The RFS ROM Drive does not need conversion, the RFS functionality assumes a raw image.

NB. Don't use Samdisk v4, it has a bug where it will place a random sector at the start of the disk. Many hours debugging were lost due to this bug. Best to use
samdisk v3.8.8

Los comandos samdisk anteriores crean una imagen en formato Amstrad CPC Extended DSK que puede leerse y procesarse con Lotharek HxCFloppyEmulator o con herramientas usadas para escribir disquetes fisicos.

Extraer discos CP/M del MZ80A

El Sharp MZ-80A almacena los datos del disquete en formato invertido — cada byte del disco es el complemento a nivel de bits del byte de datos real. Esto es una caracteristica de hardware del controlador de disquete del MZ-80A y significa que las imagenes de disco raw no pueden leerse directamente con CPMTools sin invertir primero cada byte.

La mayoria de las imagenes de disco CP/M del MZ-80A disponibles en linea estan en formato EDSK (Amstrad CPC Extended DSK). La geometria del disco es 40 cilindros, 2 cabezas, 16 sectores por pista, 256 bytes por sector (320KB en total).

Use samdisk para convertir la imagen EDSK en una imagen RAW plana:

  samdisk copy <MZ80A DISK NAME>.DSK <MZ80A DISK NAME>.RAW --cyls=40 --head=2 --sectors=16 --size=256

Ejecute el siguiente comando para invertir cada byte en la imagen RAW, convirtiendo el formato invertido del MZ-80A en datos estandar que CPMTools puede procesar:

  python3 -c "import sys; sys.stdout.buffer.write(bytes(~b & 0xFF for b in open('<MZ80A DISK NAME>.RAW','rb').read()))" > <MZ80A DISK NAME>_normal.RAW

Use el diskdef MZ80A-A (definido en la seccion de definiciones de disco anterior) con CPMTools para listar y extraer ficheros de la imagen procesada:

  # List files on the disk
  cpmls -f MZ80A-A <MZ80A DISK NAME>_normal.RAW

  # Copy all files to a local directory
  cpmcp -f MZ80A-A <MZ80A DISK NAME>_normal.RAW 0:*.* /output/directory/
Una vez extraidos, los programas pueden colocarse en una nueva imagen de disco en uno de los formatos soportados por esta implementacion de CP/M (MZ80A-1440, MZ80A-720, MZ80A-A o mz80a-rfs) usando CPMTools, y luego convertirse en una imagen para emulador de disquete con samdisk como se describe en la seccion Creacion de un disco CP/M anterior. Tenga en cuenta que al escribir de vuelta en un disco fisico en formato MZ-80A la inversion de bytes debe aplicarse a la inversa.

Extraer discos CP/M del MZ80K

El Sharp MZ-80K usa datos estandar (no invertidos) en sus disquetes, por lo que no se requiere inversion de bits. Sin embargo el formato de disco es diferente del MZ-80A y tiene menor capacidad — el MZ-80K fue disenado en torno a unidades de 5.25" de simple densidad y una sola cara. El sector de arranque de un disco CP/M del MZ-80K se identifica por los bytes marcadores 01h seguidos de la cadena ASCII IPLPRO al principio del primer sector.

Las imagenes de disco CP/M del MZ-80K estan disponibles normalmente en formato EDSK o raw. La geometria del disco es 40 cilindros, 1 cabeza, 18 sectores por pista, 128 bytes por sector (aproximadamente 90KB).

Use samdisk para extraer la imagen raw de una fuente EDSK:

  samdisk copy <MZ80K DISK NAME>.DSK <MZ80K DISK NAME>.RAW --cyls=40 --head=1 --sectors=18 --size=128
No se necesita inversion de bytes. Puede leer la imagen RAW directamente con CPMTools usando un diskdef adecuado para el formato del MZ-80K. La via de CPMTools que se muestra aqui sigue siendo util para archivar el contenido de los discos o para transferir ficheros a uno de los formatos MZ-80A soportados de forma nativa (como MZ80A-1440 o MZ80A-720). No obstante, tenga en cuenta que el CBIOS CP/M del RFS ahora tambien puede leer discos CP/M originales del MZ-80K de forma directa a traves de la tarjeta MZ80AFI (vease CP/M Boot Process mas arriba) — el disco se detecta automaticamente por su tamano de sector de 128 bytes y se monta como una unidad CP/M (normalmente C:/D:), de modo que para el uso cotidiano en hardware real o en la picoZ80 ya no es necesario convertir primero los discos.
  # List files (adjust diskdef name to match your MZ-80K diskdef entry)
  cpmls -f mz80k <MZ80K DISK NAME>.RAW

  # Extract all files
  cpmcp -f mz80k <MZ80K DISK NAME>.RAW 0:*.* /output/directory/

Extraer discos CP/M del MZ80B

El Sharp MZ-80B, al igual que el MZ-80A, almacena los datos del disquete en formato invertido — cada byte del disco es el complemento a nivel de bits de los datos reales. El sector de arranque del MZ-80B se identifica por los bytes marcadores 03h seguidos de IPLPRO al principio del primer sector, distinguiendolo de las variantes del MZ-80A (01h) y del MZ-80K (01h).

El MZ-80B tiene una capacidad de disco ligeramente superior a la del MZ-80A, usando 40 cilindros, 2 cabezas, 18 sectores por pista, 256 bytes por sector (aproximadamente 368KB). La mayoria de las imagenes de disco disponibles estan en formato EDSK.

Use samdisk para convertir la imagen EDSK en una imagen RAW plana:

  samdisk copy <MZ80B DISK NAME>.DSK <MZ80B DISK NAME>.RAW --cyls=40 --head=2 --sectors=18 --size=256

Aplique la misma inversion de bytes que para el MZ-80A para convertir los datos invertidos a formato estandar:

  python3 -c "import sys; sys.stdout.buffer.write(bytes(~b & 0xFF for b in open('<MZ80B DISK NAME>.RAW','rb').read()))" > <MZ80B DISK NAME>_normal.RAW
Use CPMTools con un diskdef adecuado para el MZ-80B para listar y extraer ficheros de la imagen RAW procesada. Una vez extraidos, copie los programas a una imagen de disco en formato MZ-80A soportado para usar con RFS como se describe en la seccion Creacion de un disco CP/M.
  # List files (adjust diskdef name to match your MZ-80B diskdef entry)
  cpmls -f mz80b <MZ80B DISK NAME>_normal.RAW

  # Extract all files
  cpmcp -f mz80b <MZ80B DISK NAME>_normal.RAW 0:*.* /output/directory/

Extraer discos CP/M del MZ800

Los ordenadores de la serie MZ800 usan un disco de formato mixto con las pistas de arranque usando datos invertidos y las pistas de CP/M usando datos estandar. Para empeorarlo, el orden de las pistas es tal que situan la cabeza 0 como pista 0-39 y la cabeza 1 como pista 40-79. Para usar estos discos, lo mejor es extraer los datos y copiarlos a uno de los formatos que he creado, ya que no veo ningun proposito en anadir codigo adicional para dar cabida a este formato extrano.

Use samdisk para convertir el EDSK (formato Extended DSK creado para la maquina Amstrad CPC; la mayoria de los discos MZ800 parecen estar en este formato) en una imagen RAW.

  samdisk copy <MZ800 DISK NAME>.DSK <MZ800 DISK NAME>.RAW --cyls=40 --head=2 --sectors=8 --size=256

Ejecute los siguientes comandos bash para convertir el disco en formato RAW obtenido arriba en algo que pueda ser leido por CPMTools.

   mv <MZ800 DISK NAME>.RAW workingfile.raw
   > total
   dd if=workingfile.raw of=total count=8192 bs=1
   for i in $(seq 8192 8192 327680); do 
     dd if=workingfile.raw of=blob skip=$i bs=1 count=4096
     cat blob >> total
     echo $i
   done
   for i in $(seq 12288 8192 327680); do
     dd if=workingfile.raw of=blob skip=$i bs=1 count=4096
     cat blob >> total
     echo $i
   done
   mv total <MZ800 DISK NAME>.RAW

Necesitara la siguiente definicion diskdefs para leer los datos de la imagen RAW procesada.

   # Definition for the MZ800 CP/M Boot Disk. The reserved
   # track is in inverted data format but this is skipped in
   # CPM Tools.
   diskdef mz800-BOOT
     seclen 256
     tracks 80
     sectrk 16
     blocksize 2048
     maxdir 64
     skew 0
     boottrk 1
     os 2.2
   end

   # Definition for the MZ800 CP/M Data disk. No reserved tracks.
   diskdef mz800-DATA
     seclen 256
     tracks 80
     sectrk 16
     blocksize 2048
     maxdir 64
     skew 0
     boottrk 0
     os 2.2
   end

Archivos de CP/M

He retirado los archivos de CP/M de Gitea ya que no es el lugar para almacenar/archivar ficheros. Descargue el fichero zip si los necesita y descomprimalo en su directorio /software.

Los ficheros del archivo son programas seleccionados que proceden de diversos archivos CP/M y estan organizados en directorios con la convencion de nombres CPM[0-9[0-9]_. Tambien se incluye (y con el debido credito y (C) por su trabajo al ensamblar el archivo) material del ordenador MultiComp de Grant Searle, que es multiples ordenadores en uno (o multiples tipos de CPU) y uno de sus modos es ejecutar CP/M. El archivo de Grant es excelente y una base ideal para usar CP/M en el MZ80A.

Para construir los archivos en un conjunto de imagenes de disquete de 1.4MB adecuadas para usar en una unidad de 3.5” o en un emulador de disquete, ejecute el comando:

cd <software>
tools/make_cpmdisks.sh

Los discos se crearan en el directorio: <CPM>/1M44/DSK.

Este script tambien construye las imagenes de unidad de tarjeta SD de 16MB usando una combinacion de los archivos. La combinacion esta fijada con valores fijos dentro del script.

Manuales de CP/M

Manual Descripcion
User Manual Manual de usuario de CP/M v2.2.
SID Guia del usuario del depurador de instrucciones simbolicas (Symbolic Instruction Debugger).
ED Guia del usuario del editor (EDitor).
MAC Guia del usuario del ensamblador de macros (Macro Assembler).
ASM Guia del usuario del ensamblador Z80/8080.
DDT Guia del usuario de la herramienta de depuracion dinamica (Dynamic Debugging Tool).

Guia del desarrollador

Para los desarrolladores que quieran entender la arquitectura interna de CP/M en el Sharp MZ, modificar el CBIOS, anadir nuevos formatos de disco o construir desde el codigo fuente, esta disponible una completa Guia del desarrollador de CP/M. Cubre la estructura por capas CCP/BDOS/CBIOS, los mapas de memoria tanto para las plataformas RFS como TZFS, los bloques de parametros de disco (Disk Parameter Blocks), el emulador de terminal ANSI, los controladores de almacenamiento, el sistema de construccion y la cadena CI/CD.

Agradecimientos

Donde he utilizado o basado cualquier componente en el diseno de un tercero, he incluido el aviso de copyright del autor original en los encabezados o dado el credito correspondiente. Todo el software de terceros, segun mi conocimiento e investigacion, es de codigo abierto y de libre uso. Si se descubre que algun componente tiene restricciones de licencia, sera eliminado de este repositorio y se proporcionara un enlace/configuracion adecuada.

Licencias

Este diseno, hardware y software, esta licenciado bajo la GNU Public Licence v3.

La Licencia Publica General GNU v3

Los archivos fuente y binarios en este proyecto marcados como GPL v3 son software libre: puede redistribuirlos y/o modificarlos bajo los terminos de la Licencia Publica General GNU publicada por la Free Software Foundation, ya sea la version 3 de la Licencia, o (a su eleccion) cualquier version posterior.

Los archivos fuente se distribuyen con la esperanza de que sean utiles, pero SIN NINGUNA GARANTIA; sin siquiera la garantia implicita de COMERCIABILIDAD o IDONEIDAD PARA UN PROPOSITO PARTICULAR. Vea la Licencia Publica General GNU para mas detalles.

Deberia haber recibido una copia de la Licencia Publica General GNU junto con este programa. Si no, vea http://www.gnu.org/licenses/.