changed z80 emulator to the cycle-stepped one

pull/31/head
AlinTigaeru 2023-02-28 19:18:56 +00:00
rodzic 88ef857bca
commit a2553293f9
8 zmienionych plików z 5065 dodań i 216 usunięć

Wyświetl plik

@ -11,8 +11,10 @@ extern "C" {
#include "emuapi.h"
#include "platform_config.h"
}
#include "processor/Z80.h"
#include "processor/Tables.h"
#ifndef CHIPS_IMPL
#define CHIPS_IMPL
#endif
#include "z80.h"
#include "crtc.h"
#include "ga.h"
#include "roms/rom464.h"
@ -29,14 +31,58 @@ extern "C" {
uint8_t RAM[0x10000]; // 64k
unsigned char* bitstream = 0; // 16k video ram to be used by PIO.
unsigned char* bitstream_init_pos = 0;
static Z80 CPU;
static z80_t CPU;
uint64_t pins;
bool interrupt_generated = false;
int sline = 0;
int cycles_left = 0;
bool test_flag = false;
// Implementations of system-specific emuapi Init, Step etc. functions.
// Helper functions
char read_z80(uint16_t Addr)
{
if(Addr <= LOWER_ROM_END && ga_config.lower_rom_enable)
{
// printf("At program counter %x, Z80 read from address %x in OS ROM\n", CPU.PC.W, Addr);
return gb_rom_464_0[Addr];
}
else if(Addr >= UPPER_ROM_BEGIN && ga_config.upper_rom_enable)
{
// printf("At program counter %x, Z80 read from address %x in BASIC ROM\n", CPU.PC.W, Addr);
return gb_rom_464_1[Addr - 0xC000];
}
else
{
// printf("At program counter %x, Z80 read from address %x in RAM\n", CPU.PC.W, Addr);
return RAM[Addr];
}
}
void write_z80(uint16_t Addr, uint8_t Value)
{
RAM[Addr] = Value;
}
void out_z80(uint16_t Port, uint8_t Value)
{
if(!(Port & 0x8000)) write_gate_array(Value); // The Gate Array is selected when bit 15 is set to 0.
if(!(Port & 0x4000)) write_crt_controller(Port, Value); // The CRTC is selected when bit 14 is set to 0.
if(!(Port & 0x2000))
{
// upper rom bank number. ROM banking needs to be done regardless of CPC model
// The Upper ROM Bank Number (in range of 0x00..0xFF) to be mapped to memory at 0xC000..0xFFFF
// byte req_bank_number = Value & 15;
// if(ga_config.upper_rom_enable)
// {
// }
}
}
uint8_t in_z80(uint16_t Port)
{
if(!(Port & 0x4000)) return read_crt_controller(Port); // The CRTC is selected when bit 14 is set to 0.
return 0xFF;
}
/**
* Creates initial emulation state (i.e. sets up color palette, clears memory etc.)
@ -49,9 +95,8 @@ void cpc_Init(void)
emu_SetPaletteEntry(firmware_palette[i].R, firmware_palette[i].G, firmware_palette[i].B, i);
}
if (bitstream == 0) bitstream = (unsigned char *)emu_Malloc(WIDTH*HEIGHT); //*HEIGHT
bitstream_init_pos = bitstream;
ResetZ80(&CPU, CYCLES_PER_FRAME);
pins = z80_init(&CPU);
memset(RAM, 0, sizeof(RAM));
}
@ -60,12 +105,9 @@ void cpc_Init(void)
*/
void cpc_Start(char* filename)
{
CPU.PC.W = 0x0000;
//CPU.IFF = IFF_IM1;
ga_config.lower_rom_enable = true;
ga_config.upper_rom_enable = false;
ga_config.interrupt_counter = 0;
// write_gate_array(0xC0);
}
/**
@ -73,24 +115,77 @@ void cpc_Start(char* filename)
*/
void cpc_Step(void)
{
for(;!is_hsync_active();)
//for(;!is_hsync_active();)
//{
// if not (z80 wait and ga wait) then tick, otherwise stall.
// or rather the tick will be a stall if both waits are asserted, i think that's better.
bool interrupt_acknowledged = false;
if(!(pins&Z80_WAIT && ga_config.wait_signal))
{
cycles_left = ExecZ80(&CPU, 24); // execute for the duration of 6 NOPs (maximum instruction length)
for(int k = 0; k < (24 - cycles_left) / 4; k++)
pins = z80_tick(&CPU, pins);
if (pins & Z80_MREQ)
{
crtc_step();
interrupt_generated = ga_step();
if(interrupt_generated)
const uint16_t addr = Z80_GET_ADDR(pins);
if (pins & Z80_RD)
{
// printf("Interrupting!\n");
IntZ80(&CPU, INT_RST38);
ga_config.interrupt_counter &= 0x1f;
uint8_t data = read_z80(addr);
Z80_SET_DATA(pins, data);
}
else if (pins & Z80_WR)
{
uint8_t data = Z80_GET_DATA(pins);
write_z80(addr, data);
}
}
else if (pins & Z80_IORQ)
{
const uint16_t port = Z80_GET_ADDR(pins);
if (pins & Z80_M1)
{
// an interrupt acknowledge cycle, depending on the emulated system,
// put either an instruction byte, or an interrupt vector on the data bus
Z80_SET_DATA(pins, 0x0038);
interrupt_acknowledged = true;
}
else if (pins & Z80_RD)
{
// handle IO input request at port
in_z80(port);
}
else if (pins & Z80_WR)
{
// handle IO output request at port
uint8_t data = Z80_GET_DATA(pins);
out_z80(port, data);
}
}
}
emu_DrawLine8(bitstream, WIDTH, HEIGHT, sline);
sline = (sline + 1) % NBLINES;
crtc_step();
interrupt_generated = ga_step();
if(interrupt_generated)
{
// To request an interrupt, or inject a wait state just set the respective pin
// (Z80_INT, Z80_NMI, Z80_WAIT), don't forget to clear the pin again later (the
// details on when those pins are set and cleared depend heavily on the
// emulated system).
// request an interrupt from the CPU
// TODO how to set the Z80_INT pin?
}
if(interrupt_acknowledged)
{
ga_config.interrupt_counter &= 0x1f;
}
if(is_hsync_active())
{
sline = (sline + 1) % NBLINES;
emu_DrawLine8(bitstream, WIDTH, HEIGHT, sline);
}
if(is_vsync_active())
{
@ -108,70 +203,10 @@ void cpc_Step(void)
crtc_step();
ga_step();
}
}
/**
* Input handler.
*/
void cpc_Input(int bClick)
{
}
void draw_vsync()
{
emu_DrawVsync();
}
// System-specific implementations of the Z80 instructions required by the portable Z80 emulator.
void OutZ80(word Port, byte Value)
{
if(!(Port & 0x8000)) write_gate_array(Value); // The Gate Array is selected when bit 15 is set to 0.
if(!(Port & 0x4000)) write_crt_controller(Port, Value); // The CRTC is selected when bit 14 is set to 0.
if(!(Port & 0x2000))
{
// upper rom bank number. ROM banking needs to be done regardless of CPC model
// The Upper ROM Bank Number (in range of 0x00..0xFF) to be mapped to memory at 0xC000..0xFFFF
// byte req_bank_number = Value & 15;
// if(ga_config.upper_rom_enable)
// {
// }
}
}
byte InZ80(word Port)
{
if(!(Port & 0x4000)) return read_crt_controller(Port); // The CRTC is selected when bit 14 is set to 0.
return 0xFF;
}
void WrZ80(word Addr, byte Value)
{
RAM[Addr] = Value;
}
void PatchZ80(Z80 *R)
{
// do nothing
}
byte RdZ80(word Addr)
{
if(Addr <= LOWER_ROM_END && ga_config.lower_rom_enable)
{
// printf("At program counter %x, Z80 read from address %x in OS ROM\n", CPU.PC.W, Addr);
return gb_rom_464_0[Addr];
}
else if(Addr >= UPPER_ROM_BEGIN && ga_config.upper_rom_enable)
{
// printf("At program counter %x, Z80 read from address %x in BASIC ROM\n", CPU.PC.W, Addr);
return gb_rom_464_1[Addr - 0xC000];
}
else
{
// printf("At program counter %x, Z80 read from address %x in RAM\n", CPU.PC.W, Addr);
return RAM[Addr];
}
}

Wyświetl plik

@ -28,40 +28,44 @@ uint8_t char_line_count = 0;
uint8_t scanline_count = 0;
uint8_t vertical_adjust_count = 0;
uint16_t memory_start_addr = 0;
uint8_t microsec_count_crtc = 0;
void crtc_step()
{
horizontal_count++;
if(horizontal_count > registers[0])
if(microsec_count_crtc == 3)
{
// horizontal counter is equal to the Horizontal Total Register.
horizontal_count = 0;
scanline_count++;
}
if(scanline_count > registers[9])
{
// The counter for Maximum Raster Address is equal to it.
// The height of a character is 8 rasters, so when we reach 8 rasters we increment the char line count.
scanline_count = 0;
char_line_count++;
horizontal_count++;
}
if(horizontal_count > registers[0])
{
// horizontal counter is equal to the Horizontal Total Register.
horizontal_count = 0;
scanline_count++;
}
if(char_line_count > registers[4])
{
// The vertical counter reaches the Vertical Total register.
char_line_count = 0;
}
if(scanline_count > registers[9])
{
// The counter for Maximum Raster Address is equal to it.
// The height of a character is 8 rasters, so when we reach 8 rasters we increment the char line count.
scanline_count = 0;
char_line_count++;
}
if(char_line_count == 0 && horizontal_count == 0)
{
memory_start_addr = ((uint16_t) registers[12] << 8) | registers[13];
}
if(char_line_count > registers[4])
{
// The vertical counter reaches the Vertical Total register.
char_line_count = 0;
}
if(char_line_count == 0 && horizontal_count == 0)
{
memory_start_addr = ((uint16_t) registers[12] << 8) | registers[13];
}
}
microsec_count_crtc = (microsec_count_crtc + 1) % 4;
}
uint16_t crtc_generate_addr()
@ -98,7 +102,7 @@ bool is_vsync_active()
int8_t char_height = (int8_t) registers[9] + 1;
int8_t char_lines_counted = (int8_t) char_line_count - registers[7];
return char_height * char_lines_counted + (int8_t) scanline_count >= 0 &&
char_height * char_lines_counted + (int8_t) scanline_count <= 16*8;
char_height * char_lines_counted + (int8_t) scanline_count <= 16;
}

Wyświetl plik

@ -8,6 +8,7 @@
#include "cpc.h"
struct GAConfig ga_config;
uint8_t microsecond_count_ga = 0;
/**
* Some of the colours are duplicates, because select_pen_colour() uses the least significant
@ -87,7 +88,6 @@ bool update_interrupts()
ga_config.interrupt_counter++;
ga_config.vsync_delay_count++;
if(ga_config.interrupt_counter == 52)
{
//printf("Interrupt generated! \n");
@ -212,23 +212,29 @@ void address_to_pixels()
break;
}
free(pixels);
}
}
}
}
bool ga_step()
{
bool interrupt_generated = update_interrupts();
//if(is_within_display())
//{
address_to_pixels();
//}
ga_config.hsync_active = is_hsync_active();
ga_config.vsync_active = is_vsync_active();
ga_config.wait_signal = microsecond_count_ga == 2;
return interrupt_generated;
if(microsecond_count_ga == 3)
{
bool interrupt_generated = update_interrupts();
//if(is_within_display())
//{
address_to_pixels();
//}
ga_config.hsync_active = is_hsync_active();
ga_config.vsync_active = is_vsync_active();
microsecond_count_ga = (microsecond_count_ga + 1) % 4;
return interrupt_generated;
}
microsecond_count_ga = (microsecond_count_ga + 1) % 4;
return false;
}
void select_pen(uint8_t value)

Wyświetl plik

@ -30,6 +30,7 @@ struct GAConfig {
bool hsync_active = false;
bool vsync_active = false;
uint8_t ram_banking = 0; // unused in CPC 464
bool wait_signal = true;
};
extern struct RGB firmware_palette[27];

Wyświetl plik

@ -13,44 +13,44 @@
/** changes to this file. **/
/*************************************************************/
static const byte Cycles[256] =
{
4,12, 8, 8, 4, 4, 8, 4, 4,12, 8, 8, 4, 4, 8, 4,
8,12, 8, 8, 4, 4, 8, 4,12,12, 8, 8, 4, 4, 8, 4,
8,12,16, 8, 4, 4, 8, 4, 8,12,16, 8, 4, 4, 8, 4,
8,12,16, 8,12,12,12, 4, 8,12,16, 8, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
8,12,12,12,12,12, 8,12, 8,12,12, 0,12,20, 8,12,
8,12,12,12,12,12, 8,12, 8, 4,12,12,12, 0, 8,12,
8,12,12,20,12,12, 8,12, 8, 4,12, 4,12, 0, 8,12,
8,12,12, 4,12,12, 8,12, 8, 8,12, 4,12, 0, 8,12
};
static const byte Cycles[256] =
{
4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4,
8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4,
7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4,
7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11,
5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11,
5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11,
5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11
};
static const byte CyclesCB[256] =
{
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8
};
static const byte CyclesED[256] =
@ -59,10 +59,10 @@ static const byte CyclesED[256] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12,12,16,20, 8,16, 8, 12,12,12,16,20, 0,16, 0, 12,
12,12,16,20, 0, 0, 8, 12,12,12,16,20, 0, 0, 8, 12,
12,12,16,20, 0, 0, 0,20,12,12,16,20, 0, 0, 0,20,
12, 0,16,20, 0, 0, 0, 0,12,12,16,20, 0, 0, 0, 0,
12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9,
12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9,
12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18,
12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0,
@ -75,42 +75,42 @@ static const byte CyclesED[256] =
static const byte CyclesXX[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0,16, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,16, 0, 0, 0, 0, 0, 0,
0,16,20,12, 12, 12, 12, 0, 0,16,20,12, 12, 12, 12, 0,
0, 0, 0, 0,24,24,20, 0, 0,16, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
12, 12, 12, 12, 12, 12,20, 12, 12, 12, 12, 12, 12, 12,20, 12,
20,20,20,20,20,20,20,20, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 12, 12,20, 0, 0, 0, 0, 0, 12, 12,20, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0,
0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9,
19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,16, 0,24, 0,16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0
0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0
};
static const byte CyclesXXCB[256] =
{
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0,
0, 0, 0, 0, 0, 0,24, 0, 0, 0, 0, 0, 0, 0,24, 0
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0
};
static const byte ZSTable[256] =

Wyświetl plik

@ -495,6 +495,7 @@ void ResetZ80(Z80 *R, register int Cycles)
R->ICount = R->IPeriod;
R->IRequest = INT_NONE;
R->IBackup = 0;
R->wait = false;
JumpZ80(R->PC.W);
}
@ -507,48 +508,55 @@ void ResetZ80(Z80 *R, register int Cycles)
#ifdef EXECZ80
int ExecZ80(register Z80 *R, register int RunCycles) //
{
register byte I;
register pair J;
for(R->ICount=RunCycles;;)
if(!R->wait)
{
while(R->ICount>0)
register byte I;
register pair J;
for(R->ICount=RunCycles;;)
{
while(R->ICount>0)
{
#ifdef DEBUG
/* Turn tracing on when reached trap address */
if(R->PC.W==R->Trap) R->Trace=1;
/* Call single-step debugger, exit if requested */
if(R->Trace)
if(!DebugZ80(R)) return(R->ICount);
/* Turn tracing on when reached trap address */
if(R->PC.W==R->Trap) R->Trace=1;
/* Call single-step debugger, exit if requested */
if(R->Trace)
if(!DebugZ80(R)) return(R->ICount);
#endif
/* Read opcode and count cycles */
I=OpZ80(R->PC.W++);
/* Count cycles */
R->ICount-=Cycles[I];
/* Interpret opcode */
switch(I)
{
/* Read opcode and count cycles */
I=OpZ80(R->PC.W++);
/* Count cycles */
R->ICount-=Cycles[I];
/* Interpret opcode */
switch(I)
{
#include "Codes.h"
case PFX_CB: CodesCB(R);break;
case PFX_ED: CodesED(R);break;
case PFX_FD: CodesFD(R);break;
case PFX_DD: CodesDD(R);break;
case PFX_CB: CodesCB(R);break;
case PFX_ED: CodesED(R);break;
case PFX_FD: CodesFD(R);break;
case PFX_DD: CodesDD(R);break;
}
/* Unless we have come here after EI, exit */
if(!(R->IFF&IFF_EI)) return(R->ICount);
else
{
/* Done with AfterEI state */
R->IFF=(R->IFF&~IFF_EI)|IFF_1;
/* Restore the ICount */
R->ICount+=R->IBackup-1;
/* Interrupt CPU if needed */
if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest);
}
/* Unless we have come here after EI, exit */
if(!(R->IFF&IFF_EI)) return(R->ICount);
else
{
/* Done with AfterEI state */
R->IFF=(R->IFF&~IFF_EI)|IFF_1;
/* Restore the ICount */
R->ICount+=R->IBackup-1;
/* Interrupt CPU if needed */
if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest);
}
}
}
}
else
{
return RunCycles;
}
}
#endif /* EXECZ80 */

Wyświetl plik

@ -14,6 +14,7 @@
#define Z80_H
#include <stdint.h>
#include <stdbool.h>
#define EXECZ80 // run a few cycles
@ -101,6 +102,7 @@ typedef struct
word Trap; /* Set Trap to address to trace from */
byte Trace; /* Set Trace=1 to start tracing */
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
bool wait;
} Z80;
/** ResetZ80() ***********************************************/

Plik diff jest za duży Load Diff