Further updates
This commit is contained in:
parent
85bc469a9c
commit
b9f6acdd76
1 changed files with 102 additions and 42 deletions
140
emulator_shell.c
140
emulator_shell.c
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
// gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -o emulator
|
// 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)
|
static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
|
||||||
{
|
{
|
||||||
switch (event->keyval)
|
switch (event->keyval)
|
||||||
|
@ -40,6 +43,62 @@ static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer u
|
||||||
return FALSE;
|
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 disassemble8080(unsigned char* code) {
|
||||||
int opbytes = 1;
|
int opbytes = 1;
|
||||||
switch (*code) {
|
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) {
|
void unknownInstruction(State8080* state) {
|
||||||
printf("Error: Unknown instruction");
|
printf("Error: Unknown instruction");
|
||||||
return exit(1);
|
return exit(1);
|
||||||
|
@ -400,6 +426,12 @@ void printState(State8080* state) {
|
||||||
uint8_t machineIn(State8080* state, uint8_t port) {
|
uint8_t machineIn(State8080* state, uint8_t port) {
|
||||||
uint8_t a;
|
uint8_t a;
|
||||||
switch(port) {
|
switch(port) {
|
||||||
|
case 0:
|
||||||
|
a = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
a = 0;
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
uint16_t v = (state->shift1<<8) | (state->shift0);
|
uint16_t v = (state->shift1<<8) | (state->shift0);
|
||||||
|
@ -410,7 +442,7 @@ uint8_t machineIn(State8080* state, uint8_t port) {
|
||||||
return a;
|
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) {
|
switch(port) {
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
|
@ -536,6 +568,19 @@ int emulate8080(State8080* state) {
|
||||||
state->pc++;
|
state->pc++;
|
||||||
}
|
}
|
||||||
break;
|
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
|
case 0x29: // DAD H
|
||||||
{
|
{
|
||||||
uint32_t hl = (state->h << 8) | state->l;
|
uint32_t hl = (state->h << 8) | state->l;
|
||||||
|
@ -814,14 +859,17 @@ int emulate8080(State8080* state) {
|
||||||
printState(state);
|
printState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateInterrupt(State8080* state, int interrupt_num)
|
void generateInterrupt(State8080* state, int interrupt_num)
|
||||||
{
|
{
|
||||||
//perform "PUSH PC"
|
//perform "PUSH PC"
|
||||||
Push(state, (state->pc & 0xFF00) >> 8, (state->pc & 0xff));
|
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.
|
//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[]) {
|
int main (int argc, char *argv[]) {
|
||||||
|
|
||||||
|
// GTK INIT
|
||||||
gtk_init(&argc, &argv);
|
gtk_init(&argc, &argv);
|
||||||
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
g_print("Test\n");
|
g_print("Test\n");
|
||||||
|
@ -853,10 +903,9 @@ int main (int argc, char *argv[]) {
|
||||||
gtk_widget_show(window);
|
gtk_widget_show(window);
|
||||||
|
|
||||||
|
|
||||||
//Initializations
|
// EMULATOR INIT
|
||||||
|
|
||||||
State8080 *state = (State8080*) calloc(1, sizeof(State8080));
|
State8080 *state = (State8080*) calloc(1, sizeof(State8080)); //memset obsolte with calloc
|
||||||
//memset(state, 0, sizeof(State8080));
|
|
||||||
state->cc.z = 1;
|
state->cc.z = 1;
|
||||||
state->cc.s = 1;
|
state->cc.s = 1;
|
||||||
state->cc.p = 1;
|
state->cc.p = 1;
|
||||||
|
@ -877,6 +926,17 @@ int main (int argc, char *argv[]) {
|
||||||
emulate8080(state);
|
emulate8080(state);
|
||||||
i++;
|
i++;
|
||||||
sleep(0.00001);
|
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();
|
gtk_main();
|
||||||
free(state->memory);
|
free(state->memory);
|
||||||
|
|
Loading…
Reference in a new issue