Further updates

This commit is contained in:
Luxdragon 2024-01-14 13:26:06 +01:00
parent 85bc469a9c
commit b9f6acdd76

View file

@ -6,6 +6,9 @@
// gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -o emulator
//===== GTK SETUP =====
static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
switch (event->keyval)
@ -40,6 +43,62 @@ static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer u
return FALSE;
}
//===== EMULATOR SETUP =====
typedef struct ConditionCodes {
//bitfields for condition codes
//the number following the variables sets the number of bits
uint8_t z:1;
uint8_t s:1;
uint8_t p:1;
uint8_t cy:1;
uint8_t ac:1;
uint8_t pad:3;
} ConditionCodes;
typedef struct State8080 {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t h;
uint8_t l;
uint16_t sp;
uint16_t pc;
uint8_t *memory;
ConditionCodes cc;
uint8_t int_enable;
uint8_t shift_offset;
uint8_t shift0;
uint8_t shift1;
} State8080;
unsigned char cycles8080[] = {
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, //0x00..0x0f
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, //0x10..0x1f
4, 10, 16, 5, 5, 5, 7, 4, 4, 10, 16, 5, 5, 5, 7, 4, //etc
4, 10, 13, 5, 10, 10, 10, 4, 4, 10, 13, 5, 5, 5, 7, 4,
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, //0x40..0x4f
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5,
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, //0x80..8x4f
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,
11, 10, 10, 10, 17, 11, 7, 11, 11, 10, 10, 10, 10, 17, 7, 11, //0xc0..0xcf
11, 10, 10, 10, 17, 11, 7, 11, 11, 10, 10, 10, 10, 17, 7, 11,
11, 10, 10, 18, 17, 11, 7, 11, 11, 5, 10, 5, 17, 17, 7, 11,
11, 10, 10, 4, 17, 11, 7, 11, 11, 5, 10, 4, 17, 17, 7, 11,
};
//===== EMULATOR FUNCTIONS =====
int disassemble8080(unsigned char* code) {
int opbytes = 1;
switch (*code) {
@ -338,39 +397,6 @@ int disassemble8080(unsigned char* code) {
}
// ================= EMULATOR CODE ======================
typedef struct ConditionCodes {
//bitfields for condition codes
//the number following the variables sets the number of bits
uint8_t z:1;
uint8_t s:1;
uint8_t p:1;
uint8_t cy:1;
uint8_t ac:1;
uint8_t pad:3;
} ConditionCodes;
typedef struct State8080 {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t h;
uint8_t l;
uint16_t sp;
uint16_t pc;
uint8_t *memory;
ConditionCodes cc;
uint8_t int_enable;
uint8_t shift_offset;
uint8_t shift0;
uint8_t shift1;
} State8080;
void unknownInstruction(State8080* state) {
printf("Error: Unknown instruction");
return exit(1);
@ -400,6 +426,12 @@ void printState(State8080* state) {
uint8_t machineIn(State8080* state, uint8_t port) {
uint8_t a;
switch(port) {
case 0:
a = 1;
break;
case 2:
a = 0;
break;
case 3:
{
uint16_t v = (state->shift1<<8) | (state->shift0);
@ -410,7 +442,7 @@ uint8_t machineIn(State8080* state, uint8_t port) {
return a;
}
uint8_t machineOut(State8080* state, uint8_t port, uint8_t value) {
void machineOut(State8080* state, uint8_t port, uint8_t value) {
switch(port) {
case 2:
{
@ -536,6 +568,19 @@ int emulate8080(State8080* state) {
state->pc++;
}
break;
case 0x27: // DAA
{
if ((state->a & 0x0f) > 9) {
state->a += 6;
} else if ((state->a & 0xf0) > 0x90) {
uint16_t res = (uint16_t) state->a + 0x60;
state->a = res & 0xff;
state->cc.cy = (res > 0xff);
state->cc.z = ((res & 0xff) == 0);
state->cc.s = (0x80 == (res & 0x80));
state->cc.p = parity((res & 0xff), 8);
}
}
case 0x29: // DAD H
{
uint32_t hl = (state->h << 8) | state->l;
@ -814,14 +859,17 @@ int emulate8080(State8080* state) {
printState(state);
}
void GenerateInterrupt(State8080* state, int interrupt_num)
void generateInterrupt(State8080* state, int interrupt_num)
{
//perform "PUSH PC"
Push(state, (state->pc & 0xFF00) >> 8, (state->pc & 0xff));
//perform "PUSH PC"
state->memory[state->sp-1] = ((state->pc & 0xFF00) >> 8);
state->memory[state->sp-2] = (state->pc & 0xff);
state->sp -= 2;
//Set the PC to the low memory vector.
//This is identical to an "RST interrupt_num" instruction.
state->pc = 8 * interrupt_num;
state->pc = 8 * interrupt_num;
state->int_enable = 0;
}
@ -845,6 +893,8 @@ void read_Space_Invaders_ROM(State8080* state, const char* filename, int offset)
int main (int argc, char *argv[]) {
// GTK INIT
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_print("Test\n");
@ -853,10 +903,9 @@ int main (int argc, char *argv[]) {
gtk_widget_show(window);
//Initializations
// EMULATOR INIT
State8080 *state = (State8080*) calloc(1, sizeof(State8080));
//memset(state, 0, sizeof(State8080));
State8080 *state = (State8080*) calloc(1, sizeof(State8080)); //memset obsolte with calloc
state->cc.z = 1;
state->cc.s = 1;
state->cc.p = 1;
@ -877,6 +926,17 @@ int main (int argc, char *argv[]) {
emulate8080(state);
i++;
sleep(0.00001);
if ( time() - lastInterrupt > 1.0/60.0) //1/60 second has elapsed
{
//only do an interrupt if they are enabled
if (state->int_enable)
{
GenerateInterrupt(state, 2); //interrupt 2
//Save the time we did this
lastInterrupt = time();
}
}
}
gtk_main();
free(state->memory);