Skip to content

Latest commit

 

History

History
283 lines (247 loc) · 11.2 KB

readmeSpanish.md

File metadata and controls

283 lines (247 loc) · 11.2 KB

Core Z80 en C

He realizado una conversión rápida del core del Z80 de José Luis Sánchez a C (no POSIX) en normativa STD(C89). El proyecto original en C++ es de Jose Luis Sánchez. Yo tan sólo he realizado una conversión a C, para que sirva de plantilla en otras plataformas y compiladores de recursos más reducidos.
Esta versión modificada sólo permite usar un único core de Z80, en lugar de múltiples, característica que si tenía el proyecto original:

  • Windows (mingw32)
  • ESP32 (Arduino IDE)
  • ANDROID (C4droid y CppDroid)
  • RP2040, W801, W806



Proyecto original

z80cpp



Archivos

Todo se puede dejar simplificado en 2 archivos (z80.c y z80.h), pero para realizar simulaciones, se ha dejado la siguiente estructura:
  • z80.h
  • z80.c
  • sim.c (para simulación)
  • zxallbin.h (el binario de test zxall)
  • gbGlobal (variables globales de Z80 y de simulación)



Entorno

Está preparado para mingw32 (devcpp) de Windows, pero puede usarse gcc con Linux, así como sistemas embebidos.



Plantilla

Tan sólo tenemos que definir el comportamiento de:
unsigned char fetchOpcode(unsigned short int address)
{
}

unsigned char peek8(unsigned short int address)
{
}

void poke8(unsigned short int address, unsigned char value)
{
}

unsigned short int peek16(unsigned short int address)
{   
}

void poke16(unsigned short int address, RegisterPair word)
{
}

void addressOnBus(unsigned short int address, int wstates)
{
}

unsigned char inPort(unsigned short int port)
{    
}

void outPort(unsigned short int port, unsigned char value)
{    
}

void interruptHandlingTime(int wstates)
{
}

unsigned char isActiveINT(void)
{
}

Debemos tener en cuenta la sección de Inicio simulador del fichero gbGlobal.h, porque ahi es donde definimos los recursos del Z80 a emular, es decir, RAM y puertos.



Test

Si lanzamos la simulación que simula la salida de consola de CPM, nos saldrá los tiempos de ejecución del test zxall:

Cuando termine, si todo va bien, saldrá algo como lo siguiente:



Opciones

Se permiten varias opciones de ajustes en el fichero gbConfig.h:
  • cfg_use_big_endian: Soporte de Big endian
  • WITH_BREAKPOINT_SUPPORT: Permite depuración
  • cfg_use_time_show: Muestra los tiempos
  • cfg_use_time_per_line: Muestra el tiempo en cada linea de ejecución.
  • cfg_use_tstates_64bits: Declara la variable de temporización de 64 bits.
  • cfg_use_direct_RegA: Modo de acceso rápido a un registro del Z80.
  • --
  • cfg_use_direct_PendingEI: Modo de acceso rápido a PendingEI.
  • cfg_use_finish_fast: Variable de ejecución declarada en modo rápido (ESP32).
  • cfg_use_z80RAM_fast: El array de RAM en modo rápido (ESP32)
  • cfg_use_z80Ports_fast: El array de puertos en modo rápido (ESP32)
  • cfg_use_time_fast: El acceso al timer en modo rápido (ESP32)



ESP32

He dejado un proyecto para ESP32 (sourceESP32) preparado para el IDE de Arduino (1.8.11), para realizar un test rápido.
La memoria de puertos se ha dejado en 8192 bytes, que nos vale para los tests.
La salida se realiza por el puerto serie, por donde podemos monitorizar.
15:50:13.123 -> BEGIN Test
15:50:13.123 ->  (00:00:00) Z80all instruction exerciser
15:50:13.123 ->  hl,....  OK
15:54:23.087 -> add hl,..........  OK
15:56:27.501 -> add ix,..........  OK
15:58:31.963 -> add iy,..........  OK
16:00:36.416 -> aluop a,nn....................  OK
16:01:39.342 -> aluop a,..  OK
16:38:21.948 -> aluop a,.....  OK
16:57:04.702 -> aluop a,(+1)...........  OK
17:06:31.325 -> bit n,(+1).............  OK
17:06:35.739 -> bit n,....  OK
17:08:57.614 -> cpd........................  OK
17:09:25.270 -> cpi........................  OK
17:09:52.965 -> .............  OK
17:11:54.128 ->  a...................  OK
17:12:00.667 ->  b...................  OK
17:12:07.207 ->  bc..................  OK
17:12:10.582 ->  c...................  OK
17:12:17.121 ->  d...................  OK
17:12:23.682 ->  de..................  OK
17:12:27.041 ->  e...................  OK
17:12:33.574 ->  h...................  OK
17:12:40.136 ->  hl..................  OK
17:12:43.496 ->  ix..................  OK
17:12:46.894 ->  iy..................  OK
17:12:50.253 ->  l...................  OK
17:12:56.777 ->  (hl)................  OK
17:13:03.339 ->  sp..................  OK
17:13:06.699 ->  (+1).........  OK
17:13:20.410 ->  ixh.................  OK
17:13:26.972 ->  ixl.................  OK
17:13:33.496 ->  iyh.................  OK
17:13:40.058 ->  iyl.................  OK
17:13:46.621 -> ld ,(nnnn).............  OK
17:13:46.660 -> ld hl,(nnnn)..................  OK
17:13:46.699 -> ld sp,(nnnn)..................  OK
17:13:46.738 -> ld ,(nnnn).............  OK
17:13:46.816 -> ld (nnnn),.............  OK
17:13:46.933 -> ld (nnnn),hl..................  OK
17:13:46.972 -> ld (nnnn),sp..................  OK
17:13:47.011 -> ld (nnnn),.............  OK
17:13:47.167 -> ld ,nnnn.........  OK
17:13:47.285 -> ld ,nnnn...............  OK
17:13:47.363 -> ld a,<(bc),(de)>..............  OK
17:13:47.441 -> ld ,nn....  OK
17:13:47.558 -> ld (+1),nn.............  OK
17:13:47.636 -> ld ,(+1)......  OK
17:13:48.808 -> ld ,(+1)..........  OK
17:13:49.394 -> ld a,(+1)..............  OK
17:13:49.667 -> ld ,nn.......  OK
17:13:49.707 -> ld ,........  OK
17:13:59.707 -> ld ,........  OK
17:14:20.292 -> ld a,(nnnn) / ld (nnnn),a.....  OK
17:14:20.371 -> ldd (1)....................  OK
17:14:20.488 -> ldd (2)....................  OK
17:14:20.566 -> ldi (1)....................  OK
17:14:20.683 -> ldi (2)....................  OK
17:14:20.761 -> neg...........................  OK
17:14:49.316 -> .....................  OK
17:15:04.824 -> ...........  OK
17:15:17.988 -> shf/rot (+1)...........  OK
17:15:18.886 -> shf/rot ..  OK
17:15:39.121 ->  n,.....  OK
17:15:59.277 ->  n,(+1).......  OK
17:16:00.214 -> ld (+1),......  OK
17:16:02.871 -> ld (+1),..........  OK
17:16:03.457 -> ld (+1),a..............  OK
17:16:03.574 -> ld (),a................  OK
17:16:03.808 -> Tests completeZ80 reset after 3785304271 t-states
17:16:03.808 ->  (01:25:46) END Test
Se puede ver la velocidad en un ESP32, de 1 hora y 25 minutos de ejecución con las opciones por defecto.
Si se seleccionan varias opciones de optimización, nos queda en (01:24:58).



ESP32 fps

Si activamos el pragma cfg_use_test_fps_48k en el gbConfig.h podremos medir los fps (cuadros por segundo), así como el tiempo en milisegundos cur (actual), min (mínimo) y max (máximo) para completar un frame en el ZX Spectrum 48K (69887 t-states).
16:35:48.682 -> fps(135) - ms cur(7) min(7) max(7)
16:35:49.698 -> fps(135) - ms cur(7) min(7) max(7)
16:35:50.713 -> fps(135) - ms cur(7) min(7) max(7)
16:35:51.690 -> fps(135) - ms cur(8) min(8) max(8)
16:35:52.706 -> fps(135) - ms cur(8) min(8) max(8)
16:35:53.721 -> fps(135) - ms cur(8) min(8) max(8)
16:35:54.698 -> fps(135) - ms cur(8) min(8) max(8)
16:35:55.713 -> fps(135) - ms cur(7) min(7) max(7)



RP2040 fps

Se han realizado pruebas en la placa rp2040 adjunta:

Si activamos el pragma cfg_use_test_fps_48k en el gbConfig.h y desactivamos el cfg_use_time_show, en la placa RP2040, nos dará unos tiempos:
fps(64) - ms cur(15) min(15) max(15)
fps(64) - ms cur(15) min(15) max(15)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(16) min(16) max(16)
fps(64) - ms cur(15) min(15) max(15)
fps(64) - ms cur(15) min(15) max(15) 

Dependiendo de la versión de framework, es posible que se tengan que sustituir los printf por print.



W806 fps

Se han realizado pruebas en la placa Winner Micro W806 adjunta:

Si activamos el pragma cfg_use_test_fps_48k en el gbConfig.h y desactivamos el cfg_use_time_show, nos dará unos tiempos:
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(16) min(16) max(16)



W801 fps

Se han realizado pruebas en la placa Winner Micro W801 adjunta:

Si activamos el pragma cfg_use_test_fps_48k en el gbConfig.h y desactivamos el cfg_use_time_show, nos dará unos tiempos:
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(17) min(17) max(17)



ANDROID

He realizado una conversión rápida en un sólo archivo compatible con C4droid y CppDroid, con salida simple a consola, de manera, que sólo tenemos que darle a compilar el archivo main.c.