Primeros pasos para pogramar un emulador

Foro dedicado a la emulación de sistemas clásicos en el PC o en otros sistemas.
Avatar de Usuario
chernandezba
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 221
Registrado: 11 Mar 2015, 10:42
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: ZX81
consola_favorita: NeoGeo
Primera consola: Atari 2600
Gracias dadas: 10 veces
Gracias recibidas: 60 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor chernandezba » 12 Sep 2018, 13:32

Bubu escribió:Namek, el poblema es que FreeBASIC no implementa disparadores (triggers), y sin ellos nu sé cómo vas a hacer que el Z80 ejecute cosas y la ULA muestre los pantallazos, ni sé cómo vas a controlar los timings.


Si con triggers te refieres a algo que "salte" a intervalos regulares de tiempo, como un timer... no te hace falta.
En ZEsarUX tengo dos modos de compilar: con pthreads o sin pthreads. Con threads, hay un timer que salta 50 veces por segundo
Sin pthreads, lo único que hago es obtener la fecha del reloj del sistema (minutos, segundos y nanosegundos) al principio del frame de video. Cuando acabo de ejecutar los 69888 t-estados del frame de video, obtengo de nuevo la fecha para ver si han transcurrido 20 milisegundos (restando del reloj inicial del frame). Si no, me quedo en un bucle de espera hasta que la diferencia del reloj actual respecto al inicial sea mayor o igual que 20 milisegundos. Cuando eso sucede, sé que han pasado 20 ms y me sirve de timer simulado.
De hecho, la versión que genero binaria de Mac por defecto no usa timers y por tanto leo el reloj del sistema, y no se nota diferencia aparente de la que usa threads+timer ;)

Tema diferente será que ese Basic del que estáis hablando soporte obtener el reloj con precisión de nanosegundos (o al menos de milisegundos)
----

ZEsarUX
ZX Second-Emulator And Released for UniX
https://github.com/chernandezba/zesarux

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 13 Sep 2018, 16:04

Pillad esto, a ver qué os sale, porfi

screen.rar
(337.2 KiB) Descargado 16 veces


Es trata de una pantalla del Spectrum tal y como lo voy a emular. Sale una pantalla con su border, en blanco, y una línea negra diagonal ocupando toda la pantalla. Pulsad ALT + ENTER para ponerla a pantalla completa.


EDITO: Me está encantando sobremanera el QBasic 64. Léase:
https://qb64.org/wiki/FULLSCREEN
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 13 Sep 2018, 21:57

Bueno, el EXE tiene 4 descargas. ¿Alguno lo ha catado y me puede decir si se pone en pantalla completa?

Y ahora otra historia: el tema del borde. ¿Cuántas líneas debe tener el borde por arriba y por abajo? Y entiendo que en los laterales debe tener 192 líneas, tantas como píxeles en vertical la pantalla, ¿nor? La verdad es que en esto estoy un poco pegaíto, jiji.
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 14 Sep 2018, 00:53

Dejaremos la pantalla pa otro momento.

Estoy emulando el Z80, y he llegado a la instrucción "CP VALOR", que es comparar con el registro A. Realmente hace una resta "SUB" pero sin afestar al registro A: A = A - VALOR
Lo que tengo es una liada con el flag que no veas. Resulta que el flag lo forman las siguientes 8 banderas:

S - Z - F5 - H - F3 - V - N - C

S = bit 7 del resultado (lo que viene siendo el signo)
Z = 1 si el resultado = 0
F5 = bit 5 del operando
H = 1 si ha habido acarreo del bit 3 al 4
F3 = bit 3 del operando
V = 1 si el complemento a 2 del resultado no cabe en el registro (la virgen)
C = 1 si el resultado no cabía en el registro

A ver, los flags H, V y C ¿los entiende alguien?

Creo que C se astiva cuando el valor es mayor estricto que el registro A, ¿nor? ¿y los otros, H y V?
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
explorer
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 252
Registrado: 11 May 2014, 17:10
Sistema Favorito: Atari ST
primer_sistema: Atari 800XL/600XL
consola_favorita: Atari 2600
Primera consola: Atari 2600
Ubicación: Valladolid, España
Gracias recibidas: 50 veces
Contactar:

Re: Primeros pasos para pogramar un emulador

Mensajepor explorer » 14 Sep 2018, 02:50

A partir de http://z80.info/zip/z80cpu_um.pdf sección Z80 Status Indicator Flags

Indicador de Acarreo

El indicador de Acarreo (C) se activa o limpia dependiendo de la operación realizada. Para instrucciones ADD que generan Acarreo, e instrucciones SUB que generan Préstamo, se activa el indicador de Acarreo. El indicador de Acarreo se limpia por una instrucción ADD que no genere Acarreo, y una instrucción SUB que no genere un préstamo. Este almacenamiento del Acarreo ayuda a las rutinas con una precisión aritmética extendida. También, la instrucción DAA establece el indicador de Acarreo si se cumplen las condiciones para realizar un ajuste decimal.

Para las instrucciones RLA, RRA, RLS y RRS, el bit de Acarreo se usa como un enlace entre el byte menos significativo (LSB) y el byte más significativo (MSB) para cualquier registro o posición de memoria. Durante las instrucciones RLCA, RLC y SLA, el Acarreo contiene el último valor desplazado del bit 7 de cualquier registro o posición de memoria. Durante las instrucciones RRCA, RRC, SRA y SRL, el Acarreo contiene el último valor desplazado del bit 0 de cualquier registro o posición de memoria.

Para las operaciones lógicas AND, OR y XOR, el Acarreo se limpia.

El indicador de Acarreo también se activa con la instrucción Establecer Indicador de Acarreo (SCF) y su complementada por la (CCF).

Indicador de Paridad/Rebose (P/V)

Este indicador se establece a un estado específico dependiendo de la operación realizada.

Para operaciones aritméticas, este indicador muestra una condición de Rebose cuando el resultado del Acumulador es mayor que el número máximo posible (+127) o es menor que el número mínimo posible (–128). Esta condición de Rebose se determina examinando los bits de signo de los operandos.

Para la suma, los operandos con signos diferentes nunca provocan Rebose. Cuando se suman operandos con el mismo signo y el resultado tiene un signo diferente, se activa el indicador de Rebose, por ejemplo:

+120 = 0111 1000 SUMANDO
+105 = 0110 1001 SUMADOR
------ --------------------
+225 = 1110 0001 (-95) SUMA


Los dos números sumados resultan en un número que excede +127 y
los dos operandos positivos han resultado en un número negativo (-95), que es incorrecto. Por lo tanto,
el indicador de Rebose se activa.

Para la resta, el Rebose puede ocurrir para operandos con signos distintos. Operandos con signos iguales nunca causan
Rebose. Por ejemplo:
+127 0111 1111 MINUENDO
(-) -64 1100 0000 SUSTRAYENDO
----------- ----------- -------------
+191 1011 1111 DIFERENCIA

El signo del minuendo ha cambiado de positivo a negativo, dando una diferencia incorrecta. El Rebose se activa.

Otro método para identificar un Rebose es observar el cambio de acarreo del bit de signo. Si hay un acarreo y cambia no acarreo, o si no hay acarreo y cambio a acarreo, se produjo un Rebose.

Este indicador también se usa con operaciones lógicas e instrucciones de rotación para indicar si el resultado de
la paridad es Par. Se cuentan el número de bits 1 en un byte. Si el total es Impar se señaliza paridad Impar (P=0).
Si el total es Par, se indica paridad Par (P=1).

Durante las instrucciones de búsqueda (CPI, CPIR, CPD, CPDR) y las instrucciones de transferencia de bloques
(LDI, LDIR, LDD, LDDR), el indicador P/V monitoriza el estado del Registro Contador de Bytes (BC). Cuando se decrementa,
si el contador de bytes llega a 0, el indicador se pone a 0. Sino, el indicador se pone a 1.

Durante las instrucciones LD A,I y LD A,R, el indicador P/V se activa con el valor del activador flip-flop de interrupciones
(IFF2) como salvaguarda y comprobación.

Cuando entra un byte desde un dispositivo de E/S con una instrucción IN r, (C), el indicador P/V se ajusta para indicar
paridad de datos.

Indicador de Medio Acarreo

El indicador de Medio Acarreo (H) se activa (1) o limpia (0) dependiendo del estado de acarreo y préstamo entre
los bits 3 y 4 de una operación aritmética 8 bits.

Este indicador se usa por la instrucción Ajuste Decimal del Acumulador (DAA) para corregir el resultado de una operación
de suma o resta empaqueta BCD. El indicador H se activa (1) o limpia (0) de acuerdo a la siguiente tabla:

Indicador H Suma Resta
1 Acarreo entre bits 3 y 4 Préstamo del bit 4
0 No acarreo No préstamo

Avatar de Usuario
Namek
Atari 1040 STf
Atari 1040 STf
Mensajes: 650
Registrado: 11 Jul 2011, 13:13
Gracias dadas: 12 veces
Gracias recibidas: 32 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Namek » 14 Sep 2018, 08:27

Resumiendo:

En suma de 8 bits si el resultado es mayor de 255 o mayor de 65535 en 16 bits ponemos C=1 si no C=0.
En resta si el resultado es menor de 0 ponemos C=1 si no C=0.
En suma si la suma de los 2 nibbles inferiores >15 ponemos H=1 si no H=0.
En resta si la resta de los 2 nibbles inferiores <0 ponemos H=1 si no H=0.
Si el resultado es 0 tanto para suma como resta ponemos Z=1 si no Z=0.
El flag P es el mas facil, ya que suele tomar el valor del bit 7 del resultado.

Ten en cuenta que no todas las instrucciones afectan a todos los flags y que algunas los afectan de forma distinta, por ejemplo las instrucciones de incremento y decremento de 8 bits solo afectan al flag Z y las de 16bits no afectan a ninguno.

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 14 Sep 2018, 16:00

OK, muchísimas gracias, torpedos, me queda bastante más claro. Uséase, en una instrucción como "CP B", tenemos que:

- C=1 si B>A. En otro caso, C=0
- H=1 si (nib)B>nib(A). En otro caso, H=0
- V=???

El flag de oVerflow (V) es el que no veo tan claro. Me refiero a concretamente la instrucción de comparación CP, o a la de resta SUB, que es lo pispo. A ver si lo entiendo en el caso "CP B":

Si A es positivo, y B es positivo, V=1 si B>A
Si A es positivo, y B es negativo, como A-B = |A|+|B|, V=S
Si A es negativo, y B es positivo, debe salir negativo, por tanto V=S
Si A es negativo, y B es negativo, V=1 si A>B

No sé yo... Por favor, si me podéis revisar esto, es que estoy bloqueado totalmente en este punto, en el flag V con la instrucción CP.
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Namek
Atari 1040 STf
Atari 1040 STf
Mensajes: 650
Registrado: 11 Jul 2011, 13:13
Gracias dadas: 12 veces
Gracias recibidas: 32 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Namek » 15 Sep 2018, 01:19

Para emular V en CP B yo hacia esto:

IF (A AND 127)-(B AND 127)<0 THEN V=1 ELSE V=0

Creo que es lo correcto, que alguien me corrija si no... :roll:

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 15 Sep 2018, 01:50

Uséase, que la fórmula sería aquesta:

Código: Seleccionar todo

FLAG_V =  (A AND 127)-(B AND 127) < 0


Yo lo que veo raro ahí es que si el V se dedica a detestar situaciones con el signo, como el signo es el bit 7, uséase, valor 128, ¿por qué usas 127 y no 128?
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Bubu
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 631
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 14 veces
Gracias recibidas: 19 veces

Re: Primeros pasos para pogramar un emulador

Mensajepor Bubu » 15 Sep 2018, 02:09

Y otra cosita, para detestar el bit de paridad, ¿lo harías sumando bits y viendo que es impar? Uséase, algo tal que así:

Código: Seleccionar todo

bits1 = (A and 128) + (A and 64) + ... + (A and 2) + (A and 1)
flag_p = 2 * [(bits1 / 2) - INT(bits1 / 2)]



Vaya paranoia...


EDITO: Veo que este lenguaje admite la instrucción MOD para el resto, así que:

Código: Seleccionar todo

flag_p = [(A and 128) + (A and 64) + ... + (A and 2) + (A and 1)] MOD 2
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!


Volver a “Emuladores”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados