2024-01-06 19:33:56 +00:00
# include <stdio.h>
2024-01-07 12:32:22 +00:00
# include <stdlib.h>
2024-01-06 19:33:56 +00:00
# include <stdint.h> // for the uintx_t's
2024-01-07 12:32:22 +00:00
# include <unistd.h> // for sleep
2024-01-13 21:38:02 +00:00
# include <gtk/gtk.h>
2024-01-15 19:44:19 +00:00
# include <pthread.h>
2024-01-06 21:23:36 +00:00
2024-01-15 19:44:19 +00:00
// gcc emulator_shell.c `pkg-config --cflags --libs gtk+-3.0` -lpthread -o emulator
2024-01-13 21:38:02 +00:00
2024-01-14 20:19:34 +00:00
void keyDown ( uint8_t key ) ;
void keyUp ( uint8_t key ) ;
2024-01-14 12:26:06 +00:00
//===== GTK SETUP =====
2024-01-13 21:38:02 +00:00
static gboolean on_key_press ( GtkWidget * widget , GdkEventKey * event , gpointer user_data )
{
switch ( event - > keyval )
{
case GDK_KEY_Left :
// Code to be executed when the left arrow key is pressed down
g_print ( " Left arrow key pressed down \n " ) ;
2024-01-14 16:50:35 +00:00
keyDown ( 1 ) ;
2024-01-13 21:38:02 +00:00
break ;
case GDK_KEY_Right :
// Code to be executed when the right arrow key is pressed down
g_print ( " Right arrow key pressed down \n " ) ;
2024-01-14 16:50:35 +00:00
keyDown ( 2 ) ;
break ;
case GDK_KEY_space :
// Code to be executed when the space bar is pressed down
g_print ( " Space bar pressed down \n " ) ;
keyDown ( 3 ) ;
break ;
case GDK_KEY_c :
// Code to be executed when the 'c' key is pressed down
g_print ( " 'c' key pressed down \n " ) ;
keyDown ( 0 ) ;
break ;
case GDK_KEY_s :
// Code to be executed when the 's' key is pressed down
g_print ( " 's' key pressed down \n " ) ;
keyDown ( 4 ) ;
2024-01-13 21:38:02 +00:00
break ;
}
return FALSE ;
}
static gboolean on_key_release ( GtkWidget * widget , GdkEventKey * event , gpointer user_data )
{
switch ( event - > keyval )
{
case GDK_KEY_Left :
// Code to be executed when the left arrow key is released
g_print ( " Left arrow key released \n " ) ;
2024-01-14 16:50:35 +00:00
keyUp ( 1 ) ;
2024-01-13 21:38:02 +00:00
break ;
case GDK_KEY_Right :
// Code to be executed when the right arrow key is released
g_print ( " Right arrow key released \n " ) ;
2024-01-14 16:50:35 +00:00
keyUp ( 2 ) ;
break ;
case GDK_KEY_space :
// Code to be executed when the space bar is pressed down
g_print ( " Space bar released \n " ) ;
keyUp ( 3 ) ;
break ;
case GDK_KEY_c :
// Code to be executed when the 'c' key is pressed down
g_print ( " 'c' key released \n " ) ;
keyUp ( 0 ) ;
break ;
case GDK_KEY_s :
// Code to be executed when the 's' key is pressed down
g_print ( " 's' key released \n " ) ;
keyUp ( 4 ) ;
2024-01-13 21:38:02 +00:00
break ;
}
return FALSE ;
}
2024-01-06 21:23:36 +00:00
2024-01-14 12:26:06 +00:00
//===== EMULATOR SETUP =====
2024-01-15 13:06:04 +00:00
//GLOBAL VARIABLES
uint8_t in_port ;
char which_interrupt ;
2024-01-19 21:45:49 +00:00
uint8_t upscaleFactor = 2 ;
2024-01-20 11:31:11 +00:00
uint8_t lauteco = 90 ;
2024-01-14 21:35:01 +00:00
//GLOBAL GRAPHICS
2024-01-14 21:39:57 +00:00
uint8_t * bitmap = NULL ;
2024-01-15 13:06:04 +00:00
2024-01-14 16:50:35 +00:00
2024-01-14 12:26:06 +00:00
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 =====
2024-01-08 17:07:28 +00:00
int disassemble8080 ( unsigned char * code ) {
2024-01-07 12:32:22 +00:00
int opbytes = 1 ;
switch ( * code ) {
case 0x00 : printf ( " NOP " ) ; break ;
case 0x01 : printf ( " LXI B,#$%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x02 : printf ( " STAX B " ) ; break ;
case 0x03 : printf ( " INX B " ) ; break ;
case 0x04 : printf ( " INR B " ) ; break ;
case 0x05 : printf ( " DCR B " ) ; break ;
case 0x06 : printf ( " MVI B,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x07 : printf ( " RLC " ) ; break ;
case 0x08 : printf ( " NOP " ) ; break ;
case 0x09 : printf ( " DAD B " ) ; break ;
case 0x0a : printf ( " LDAX B " ) ; break ;
case 0x0b : printf ( " DCX B " ) ; break ;
case 0x0c : printf ( " INR C " ) ; break ;
case 0x0d : printf ( " DCR C " ) ; break ;
case 0x0e : printf ( " MVI C,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x0f : printf ( " RRC " ) ; break ;
case 0x10 : printf ( " NOP " ) ; break ;
case 0x11 : printf ( " LXI D,#$%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x12 : printf ( " STAX D " ) ; break ;
case 0x13 : printf ( " INX D " ) ; break ;
case 0x14 : printf ( " INR D " ) ; break ;
case 0x15 : printf ( " DCR D " ) ; break ;
case 0x16 : printf ( " MVI D,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x17 : printf ( " RAL " ) ; break ;
case 0x18 : printf ( " NOP " ) ; break ;
case 0x19 : printf ( " DAD D " ) ; break ;
case 0x1a : printf ( " LDAX D " ) ; break ;
case 0x1b : printf ( " DCX D " ) ; break ;
case 0x1c : printf ( " INR E " ) ; break ;
case 0x1d : printf ( " DCR E " ) ; break ;
case 0x1e : printf ( " MVI E,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x1f : printf ( " RAR " ) ; break ;
case 0x20 : printf ( " NOP " ) ; break ;
case 0x21 : printf ( " LXI H,#$%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x22 : printf ( " SHLD $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x23 : printf ( " INX H " ) ; break ;
case 0x24 : printf ( " INR H " ) ; break ;
case 0x25 : printf ( " DCR H " ) ; break ;
case 0x26 : printf ( " MVI H,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x27 : printf ( " DAA " ) ; break ;
case 0x28 : printf ( " NOP " ) ; break ;
case 0x29 : printf ( " DAD H " ) ; break ;
case 0x2a : printf ( " LHLD $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x2b : printf ( " DCX H " ) ; break ;
case 0x2c : printf ( " INR L " ) ; break ;
case 0x2d : printf ( " DCR L " ) ; break ;
case 0x2e : printf ( " MVI L,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x2f : printf ( " CMA " ) ; break ;
case 0x30 : printf ( " NOP " ) ; break ;
case 0x31 : printf ( " LXI SP,#$%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x32 : printf ( " STA $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x33 : printf ( " INX SP " ) ; break ;
case 0x34 : printf ( " INR M " ) ; break ;
case 0x35 : printf ( " DCR M " ) ; break ;
case 0x36 : printf ( " MVI M,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x37 : printf ( " STC " ) ; break ;
case 0x38 : printf ( " NOP " ) ; break ;
case 0x39 : printf ( " DAD SP " ) ; break ;
case 0x3a : printf ( " LDA $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0x3b : printf ( " DCX SP " ) ; break ;
case 0x3c : printf ( " INR A " ) ; break ;
case 0x3d : printf ( " DCR A " ) ; break ;
case 0x3e : printf ( " MVI A,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0x3f : printf ( " CMC " ) ; break ;
case 0x40 : printf ( " MOV B,B " ) ; break ;
case 0x41 : printf ( " MOV B,C " ) ; break ;
case 0x42 : printf ( " MOV B,D " ) ; break ;
case 0x43 : printf ( " MOV B,E " ) ; break ;
case 0x44 : printf ( " MOV B,H " ) ; break ;
case 0x45 : printf ( " MOV B,L " ) ; break ;
case 0x46 : printf ( " MOV B,M " ) ; break ;
case 0x47 : printf ( " MOV B,A " ) ; break ;
case 0x48 : printf ( " MOV C,B " ) ; break ;
case 0x49 : printf ( " MOV C,C " ) ; break ;
case 0x4a : printf ( " MOV C,D " ) ; break ;
case 0x4b : printf ( " MOV C,E " ) ; break ;
case 0x4c : printf ( " MOV C,H " ) ; break ;
case 0x4d : printf ( " MOV C,L " ) ; break ;
case 0x4e : printf ( " MOV C,M " ) ; break ;
case 0x4f : printf ( " MOV C,A " ) ; break ;
case 0x50 : printf ( " MOV D,B " ) ; break ;
case 0x51 : printf ( " MOV D,C " ) ; break ;
case 0x52 : printf ( " MOV D,D " ) ; break ;
case 0x53 : printf ( " MOV D,E " ) ; break ;
case 0x54 : printf ( " MOV D,H " ) ; break ;
case 0x55 : printf ( " MOV D,L " ) ; break ;
case 0x56 : printf ( " MOV D,M " ) ; break ;
case 0x57 : printf ( " MOV D,A " ) ; break ;
case 0x58 : printf ( " MOV E,B " ) ; break ;
case 0x59 : printf ( " MOV E,C " ) ; break ;
case 0x5a : printf ( " MOV E,D " ) ; break ;
case 0x5b : printf ( " MOV E,E " ) ; break ;
case 0x5c : printf ( " MOV E,H " ) ; break ;
case 0x5d : printf ( " MOV E,L " ) ; break ;
case 0x5e : printf ( " MOV E,M " ) ; break ;
case 0x5f : printf ( " MOV E,A " ) ; break ;
case 0x60 : printf ( " MOV H,B " ) ; break ;
case 0x61 : printf ( " MOV H,C " ) ; break ;
case 0x62 : printf ( " MOV H,D " ) ; break ;
case 0x63 : printf ( " MOV H,E " ) ; break ;
case 0x64 : printf ( " MOV H,H " ) ; break ;
case 0x65 : printf ( " MOV H,L " ) ; break ;
case 0x66 : printf ( " MOV H,M " ) ; break ;
case 0x67 : printf ( " MOV H,A " ) ; break ;
case 0x68 : printf ( " MOV L,B " ) ; break ;
case 0x69 : printf ( " MOV L,C " ) ; break ;
case 0x6a : printf ( " MOV L,D " ) ; break ;
case 0x6b : printf ( " MOV L,E " ) ; break ;
case 0x6c : printf ( " MOV L,H " ) ; break ;
case 0x6d : printf ( " MOV L,L " ) ; break ;
case 0x6e : printf ( " MOV L,M " ) ; break ;
case 0x6f : printf ( " MOV L,A " ) ; break ;
case 0x70 : printf ( " MOV M,B " ) ; break ;
case 0x71 : printf ( " MOV M,C " ) ; break ;
case 0x72 : printf ( " MOV M,D " ) ; break ;
case 0x73 : printf ( " MOV M,E " ) ; break ;
case 0x74 : printf ( " MOV M,H " ) ; break ;
case 0x75 : printf ( " MOV M,L " ) ; break ;
case 0x76 : printf ( " HLT " ) ; break ;
case 0x77 : printf ( " MOV M,A " ) ; break ;
case 0x78 : printf ( " MOV A,B " ) ; break ;
case 0x79 : printf ( " MOV A,C " ) ; break ;
case 0x7a : printf ( " MOV A,D " ) ; break ;
case 0x7b : printf ( " MOV A,E " ) ; break ;
case 0x7c : printf ( " MOV A,H " ) ; break ;
case 0x7d : printf ( " MOV A,L " ) ; break ;
case 0x7e : printf ( " MOV A,M " ) ; break ;
case 0x7f : printf ( " MOV A,A " ) ; break ;
case 0x80 : printf ( " ADD B " ) ; break ;
case 0x81 : printf ( " ADD C " ) ; break ;
case 0x82 : printf ( " ADD D " ) ; break ;
case 0x83 : printf ( " ADD E " ) ; break ;
case 0x84 : printf ( " ADD H " ) ; break ;
case 0x85 : printf ( " ADD L " ) ; break ;
case 0x86 : printf ( " ADD M " ) ; break ;
case 0x87 : printf ( " ADD A " ) ; break ;
case 0x88 : printf ( " ADC B " ) ; break ;
case 0x89 : printf ( " ADC C " ) ; break ;
case 0x8a : printf ( " ADC D " ) ; break ;
case 0x8b : printf ( " ADC E " ) ; break ;
case 0x8c : printf ( " ADC H " ) ; break ;
case 0x8d : printf ( " ADC L " ) ; break ;
case 0x8e : printf ( " ADC M " ) ; break ;
case 0x8f : printf ( " ADC A " ) ; break ;
case 0x90 : printf ( " SUB B " ) ; break ;
case 0x91 : printf ( " SUB C " ) ; break ;
case 0x92 : printf ( " SUB D " ) ; break ;
case 0x93 : printf ( " SUB E " ) ; break ;
case 0x94 : printf ( " SUB H " ) ; break ;
case 0x95 : printf ( " SUB L " ) ; break ;
case 0x96 : printf ( " SUB M " ) ; break ;
case 0x97 : printf ( " SUB A " ) ; break ;
case 0x98 : printf ( " SBB B " ) ; break ;
case 0x99 : printf ( " SBB C " ) ; break ;
case 0x9a : printf ( " SBB D " ) ; break ;
case 0x9b : printf ( " SBB E " ) ; break ;
case 0x9c : printf ( " SBB H " ) ; break ;
case 0x9d : printf ( " SBB L " ) ; break ;
case 0x9e : printf ( " SBB M " ) ; break ;
case 0x9f : printf ( " SBB A " ) ; break ;
case 0xa0 : printf ( " ANA B " ) ; break ;
case 0xa1 : printf ( " ANA C " ) ; break ;
case 0xa2 : printf ( " ANA D " ) ; break ;
case 0xa3 : printf ( " ANA E " ) ; break ;
case 0xa4 : printf ( " ANA H " ) ; break ;
case 0xa5 : printf ( " ANA L " ) ; break ;
case 0xa6 : printf ( " ANA M " ) ; break ;
case 0xa7 : printf ( " ANA A " ) ; break ;
case 0xa8 : printf ( " XRA B " ) ; break ;
case 0xa9 : printf ( " XRA C " ) ; break ;
case 0xaa : printf ( " XRA D " ) ; break ;
case 0xab : printf ( " XRA E " ) ; break ;
case 0xac : printf ( " XRA H " ) ; break ;
case 0xad : printf ( " XRA L " ) ; break ;
case 0xae : printf ( " XRA M " ) ; break ;
case 0xaf : printf ( " XRA A " ) ; break ;
case 0xb0 : printf ( " ORA B " ) ; break ;
case 0xb1 : printf ( " ORA C " ) ; break ;
case 0xb2 : printf ( " ORA D " ) ; break ;
case 0xb3 : printf ( " ORA E " ) ; break ;
case 0xb4 : printf ( " ORA H " ) ; break ;
case 0xb5 : printf ( " ORA L " ) ; break ;
case 0xb6 : printf ( " ORA M " ) ; break ;
case 0xb7 : printf ( " ORA A " ) ; break ;
case 0xb8 : printf ( " CMP B " ) ; break ;
case 0xb9 : printf ( " CMP C " ) ; break ;
case 0xba : printf ( " CMP D " ) ; break ;
case 0xbb : printf ( " CMP E " ) ; break ;
case 0xbc : printf ( " CMP H " ) ; break ;
case 0xbd : printf ( " CMP L " ) ; break ;
case 0xbe : printf ( " CMP M " ) ; break ;
case 0xbf : printf ( " CMP A " ) ; break ;
case 0xc0 : printf ( " RNZ " ) ; break ;
case 0xc1 : printf ( " POP B " ) ; break ;
case 0xc2 : printf ( " JNZ $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xc3 : printf ( " JMP $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xc4 : printf ( " CNZ $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xc5 : printf ( " PUSH B " ) ; break ;
case 0xc6 : printf ( " ADI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xc7 : printf ( " RST 0 " ) ; break ;
case 0xc8 : printf ( " RZ " ) ; break ;
case 0xc9 : printf ( " RET " ) ; break ;
case 0xca : printf ( " JZ $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xcb : printf ( " NOP " ) ; break ;
case 0xcc : printf ( " CZ $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xcd : printf ( " CALL $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xce : printf ( " ACI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xcf : printf ( " RST 1 " ) ; break ;
case 0xd0 : printf ( " RNC " ) ; break ;
case 0xd1 : printf ( " POP D " ) ; break ;
case 0xd2 : printf ( " JNC $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xd3 : printf ( " OUT #$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xd4 : printf ( " CNC $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xd5 : printf ( " PUSH D " ) ; break ;
case 0xd6 : printf ( " SUI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xd7 : printf ( " RST 2 " ) ; break ;
case 0xd8 : printf ( " RC " ) ; break ;
case 0xd9 : printf ( " NOP " ) ; break ;
case 0xda : printf ( " JC $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xdb : printf ( " IN #$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xdc : printf ( " CC $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xdd : printf ( " NOP " ) ; break ;
case 0xde : printf ( " SBI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xdf : printf ( " RST 3 " ) ; break ;
case 0xe0 : printf ( " RPO " ) ; break ;
case 0xe1 : printf ( " POP H " ) ; break ;
case 0xe2 : printf ( " JPO $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xe3 : printf ( " XTHL " ) ; break ;
case 0xe4 : printf ( " CPO $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xe5 : printf ( " PUSH H " ) ; break ;
case 0xe6 : printf ( " ANI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xe7 : printf ( " RST 4 " ) ; break ;
case 0xe8 : printf ( " RPE " ) ; break ;
case 0xe9 : printf ( " PCHL " ) ; break ;
case 0xea : printf ( " JPE $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xeb : printf ( " XCHG " ) ; break ;
case 0xec : printf ( " CPE $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xed : printf ( " NOP " ) ; break ;
case 0xee : printf ( " XRI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xef : printf ( " RST 5 " ) ; break ;
case 0xf0 : printf ( " RP " ) ; break ;
case 0xf1 : printf ( " POP PSW " ) ; break ;
case 0xf2 : printf ( " JP $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xf3 : printf ( " DI " ) ; break ;
case 0xf4 : printf ( " CP $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xf5 : printf ( " PUSH PSW " ) ; break ;
case 0xf6 : printf ( " ORI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xf7 : printf ( " RST 6 " ) ; break ;
case 0xf8 : printf ( " RM " ) ; break ;
case 0xf9 : printf ( " SPHL " ) ; break ;
case 0xfa : printf ( " JM $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xfb : printf ( " EI " ) ; break ;
case 0xfc : printf ( " CM $%02x%02x " , code [ 2 ] , code [ 1 ] ) ; opbytes = 3 ; break ;
case 0xfd : printf ( " NOP " ) ; break ;
case 0xfe : printf ( " CPI,#$%02x " , code [ 1 ] ) ; opbytes = 2 ; break ;
case 0xff : printf ( " RST 7 " ) ; break ;
}
printf ( " \n " ) ;
return opbytes ;
}
void unknownInstruction ( State8080 * state ) {
2024-01-06 19:33:56 +00:00
printf ( " Error: Unknown instruction " ) ;
2024-01-07 12:32:22 +00:00
return exit ( 1 ) ;
2024-01-06 19:33:56 +00:00
}
int parity ( int x , int size )
{
int i ;
int p = 0 ;
x = ( x & ( ( 1 < < size ) - 1 ) ) ;
for ( i = 0 ; i < size ; i + + )
{
if ( x & 0x1 ) p + + ;
x = x > > 1 ;
}
return ( 0 = = ( p & 0x1 ) ) ;
}
2024-01-13 21:38:02 +00:00
void printState ( State8080 * state ) {
2024-01-15 23:20:20 +00:00
printf ( " \t C=%d,P=%d,S=%d,Z=%d,Enable=%d \n " , state - > cc . cy , state - > cc . p ,
state - > cc . s , state - > cc . z , state - > int_enable ) ;
2024-01-13 21:38:02 +00:00
printf ( " \t A $%02x B $%02x C $%02x D $%02x E $%02x H $%02x L $%02x SP %04x \n " ,
state - > a , state - > b , state - > c , state - > d ,
state - > e , state - > h , state - > l , state - > sp ) ;
}
2024-01-14 10:00:05 +00:00
uint8_t machineIn ( State8080 * state , uint8_t port ) {
uint8_t a ;
switch ( port ) {
2024-01-14 12:26:06 +00:00
case 0 :
a = 1 ;
break ;
case 2 :
2024-01-14 16:50:35 +00:00
a = in_port ;
2024-01-14 12:26:06 +00:00
break ;
2024-01-14 10:00:05 +00:00
case 3 :
{
uint16_t v = ( state - > shift1 < < 8 ) | ( state - > shift0 ) ;
a = ( ( v > > ( 8 - state - > shift_offset ) ) & 0xff ) ;
}
2024-01-14 16:50:35 +00:00
break ;
2024-01-14 10:00:05 +00:00
}
return a ;
}
2024-01-14 12:26:06 +00:00
void machineOut ( State8080 * state , uint8_t port , uint8_t value ) {
2024-01-14 10:00:05 +00:00
switch ( port ) {
case 2 :
{
state - > shift_offset = value & 0x7 ;
} break ;
case 4 :
{
state - > shift0 = state - > shift1 ;
state - > shift1 = value ;
break ;
}
}
}
2024-01-06 19:33:56 +00:00
int emulate8080 ( State8080 * state ) {
unsigned char * opcode = & ( state - > memory [ state - > pc ] ) ;
2024-01-08 17:07:28 +00:00
printf ( " %04x " , state - > pc ) ;
disassemble8080 ( opcode ) ;
state - > pc + + ;
2024-01-07 12:32:22 +00:00
2024-01-06 19:33:56 +00:00
switch ( * opcode ) {
case 0x00 : break ; // NOP does nothing
case 0x01 : // LXI B, word
state - > c = opcode [ 1 ] ;
state - > b = opcode [ 2 ] ;
state - > pc + = 2 ;
break ;
2024-01-15 23:20:20 +00:00
case 0x02 : // STAX B
{
uint16_t offset = ( state - > b < < 8 ) | state - > c ;
state - > memory [ offset ] = state - > a ;
}
break ;
case 0x03 : // INX B
{
state - > c + + ;
if ( state - > c = = 0 ) {
state - > b + + ;
}
state - > cc . z = ( state - > b = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > b & 0x80 ) ) ;
state - > cc . p = parity ( state - > b , 8 ) ;
}
break ;
case 0x04 : // INR B
{
state - > b + + ;
}
break ;
2024-01-06 19:33:56 +00:00
case 0x05 : // DCR B
2024-01-08 17:07:28 +00:00
{
2024-01-06 19:33:56 +00:00
uint8_t res = state - > b - 1 ;
state - > b = res ;
state - > cc . z = ( res = = 0 ) ;
2024-01-08 17:07:28 +00:00
state - > cc . s = ( 0x80 = = ( res & 0x80 ) ) ;
2024-01-06 19:33:56 +00:00
state - > cc . p = parity ( res , 8 ) ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
case 0x06 : // MVI B, byte
state - > b = opcode [ 1 ] ;
state - > pc + = 1 ;
break ;
2024-01-19 19:20:17 +00:00
case 0x07 : // RLC
{
uint8_t x = state - > a ;
state - > a = ( ( x & 0x80 ) > > 7 ) | ( x < < 1 ) ;
state - > cc . cy = ( 0x80 = = ( x & 0x80 ) ) ;
}
break ;
2024-01-06 19:33:56 +00:00
case 0x09 : // DAD B
2024-01-08 17:07:28 +00:00
{
2024-01-06 19:33:56 +00:00
uint32_t h1 = ( state - > h < < 8 ) | state - > l ;
uint32_t bc = ( state - > b < < 8 ) | state - > c ;
2024-01-07 12:32:22 +00:00
uint32_t result = h1 + bc ;
2024-01-08 17:07:28 +00:00
state - > h = ( result & 0xff00 ) > > 8 ;
2024-01-07 12:32:22 +00:00
state - > l = result & 0xff ;
2024-01-08 17:07:28 +00:00
state - > cc . cy = ( ( result & 0xffff0000 ) ! = 0 ) ;
}
2024-01-06 21:23:36 +00:00
break ;
2024-01-15 23:20:20 +00:00
case 0x0a : // LDAX B
{
uint16_t address = ( state - > b < < 8 ) | state - > c ;
state - > a = state - > memory [ address ] ;
}
break ;
2024-01-06 21:23:36 +00:00
case 0x0d : // DCR C
2024-01-08 17:07:28 +00:00
{
2024-01-06 21:23:36 +00:00
uint8_t res = state - > c - 1 ;
state - > c = res ;
state - > cc . z = ( res = = 0 ) ;
2024-01-08 17:07:28 +00:00
state - > cc . s = ( ( res & 0x80 ) = = 0x80 ) ;
2024-01-06 21:23:36 +00:00
state - > cc . p = parity ( res , 8 ) ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
case 0x0e : // MVI C, byte
state - > c = opcode [ 1 ] ;
2024-01-08 17:07:28 +00:00
state - > pc + + ;
2024-01-06 19:33:56 +00:00
break ;
2024-01-06 21:23:36 +00:00
case 0x0f : // RRC
2024-01-08 17:07:28 +00:00
{
2024-01-06 21:23:36 +00:00
uint8_t x = state - > a ;
state - > a = ( ( x & 1 ) < < 7 ) | ( x > > 1 ) ;
state - > cc . cy = ( 1 = = ( x & 1 ) ) ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 21:23:36 +00:00
break ;
2024-01-06 19:33:56 +00:00
case 0x11 : // LXI D, word
2024-01-09 09:58:58 +00:00
{
2024-01-06 19:33:56 +00:00
state - > d = opcode [ 2 ] ;
state - > e = opcode [ 1 ] ;
state - > pc + = 2 ;
2024-01-09 09:58:58 +00:00
}
2024-01-08 17:07:28 +00:00
break ;
2024-01-06 21:23:36 +00:00
case 0x13 : // INX D
2024-01-09 09:58:58 +00:00
{
2024-01-06 21:23:36 +00:00
state - > e + + ;
if ( state - > e = = 0 ) {
state - > d + + ;
2024-01-09 09:58:58 +00:00
} }
2024-01-06 21:23:36 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x16 : // MVI D, byte
state - > d = opcode [ 1 ] ;
state - > pc + + ;
break ;
2024-01-06 21:23:36 +00:00
case 0x19 : // DAD D
2024-01-08 17:07:28 +00:00
{
2024-01-06 21:23:36 +00:00
uint32_t h1 = ( state - > h < < 8 ) | state - > l ;
uint32_t de = ( state - > d < < 8 ) | state - > e ;
2024-01-07 12:32:22 +00:00
uint32_t result = h1 + de ;
2024-01-08 17:07:28 +00:00
state - > h = ( result & 0xff00 ) > > 8 ;
2024-01-07 12:32:22 +00:00
state - > l = result & 0xff ;
state - > cc . cy = ( ( result & 0xffff0000 ) ! = 0 ) ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 21:23:36 +00:00
break ;
case 0x1a : // LDAX D
2024-01-08 17:07:28 +00:00
{
2024-01-06 21:23:36 +00:00
uint16_t de = ( state - > d < < 8 ) | state - > e ;
state - > a = state - > memory [ de ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 21:23:36 +00:00
break ;
2024-01-06 19:33:56 +00:00
case 0x21 : // LXI H, word
2024-01-09 09:58:58 +00:00
{
2024-01-19 19:20:17 +00:00
state - > h = opcode [ 2 ] ;
state - > l = opcode [ 1 ] ;
state - > pc + = 2 ;
}
2024-01-08 17:07:28 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x22 : // SHLD
{
uint16_t address = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
state - > memory [ address ] = state - > l ;
state - > memory [ address + 1 ] = state - > h ;
state - > pc + = 2 ;
2024-01-09 09:58:58 +00:00
}
2024-01-19 19:20:17 +00:00
break ;
2024-01-06 21:23:36 +00:00
case 0x23 : // INX H
2024-01-09 09:58:58 +00:00
{
2024-01-19 19:20:17 +00:00
state - > l + + ;
if ( state - > l = = 0 ) {
state - > h + + ;
}
}
2024-01-06 21:23:36 +00:00
break ;
2024-01-06 19:33:56 +00:00
case 0x26 : // MVI H, byte
2024-01-09 09:58:58 +00:00
{
2024-01-19 19:20:17 +00:00
state - > h = opcode [ 1 ] ;
state - > pc + + ;
2024-01-09 09:58:58 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-14 12:26:06 +00:00
case 0x27 : // DAA
{
2024-01-15 23:20:20 +00:00
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 ) ;
}
2024-01-14 12:26:06 +00:00
}
2024-01-15 23:20:20 +00:00
break ;
2024-01-06 21:47:44 +00:00
case 0x29 : // DAD H
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint32_t hl = ( state - > h < < 8 ) | state - > l ;
uint32_t result = hl + hl ;
state - > h = ( result & 0xff00 ) > > 8 ;
state - > l = result & 0xff ;
state - > cc . cy = ( ( result & 0xffff0000 ) ! = 0 ) ;
}
break ;
case 0x2a : // LHLD adress
{
uint16_t adress = ( opcode [ 2 ] < < 8 ) | ( opcode [ 1 ] ) ;
state - > h = state - > memory [ adress ] ;
state - > l = state - > memory [ adress + 1 ] ;
state - > pc + = 2 ;
}
break ;
case 0x2b : // DCX H
{
state - > l - - ;
if ( state - > l = = 0xff ) {
state - > h - - ;
}
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x2c : // INR L
{
state - > l + + ;
state - > cc . z = ( state - > l = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > l & 0x80 ) ) ;
state - > cc . p = parity ( state - > l , 8 ) ;
}
break ;
case 0x2d : // DCR L
{
state - > l - - ;
state - > cc . z = ( state - > l = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > l & 0x80 ) ) ;
state - > cc . p = parity ( state - > l , 8 ) ;
}
break ;
case 0x2e : // MVI L, Adress
state - > l = opcode [ 1 ] ;
state - > pc + + ;
break ;
case 0x2f : // CMA (NOT)
state - > a = ~ state - > a ;
break ;
2024-01-06 19:33:56 +00:00
case 0x31 : // LXI SP, word
2024-01-07 12:32:22 +00:00
state - > sp = ( ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ) ;
state - > pc + = 2 ;
2024-01-08 17:07:28 +00:00
break ;
2024-01-07 12:32:22 +00:00
case 0x32 : // STA adress
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( opcode [ 2 ] < < 8 ) | ( opcode [ 1 ] ) ;
state - > memory [ adress ] = state - > a ;
state - > pc + = 2 ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-15 23:20:20 +00:00
case 0x34 : // ICR M
{
uint16_t offset = ( state - > h < < 8 ) | state - > l ;
uint8_t res = state - > memory [ offset ] + 1 ;
state - > cc . z = ( res = = 0 ) ;
state - > cc . s = ( 0x80 = = ( res & 0x80 ) ) ;
state - > cc . p = parity ( res , 8 ) ;
state - > memory [ offset ] = res ;
}
break ;
case 0x35 : // DCR M
{
uint16_t offset = ( state - > h < < 8 ) | state - > l ;
uint8_t res = state - > memory [ offset ] - 1 ;
state - > cc . z = ( res = = 0 ) ;
state - > cc . s = ( 0x80 = = ( res & 0x80 ) ) ;
state - > cc . p = parity ( res , 8 ) ;
state - > memory [ offset ] = res ;
}
break ;
2024-01-06 19:33:56 +00:00
case 0x36 : // MVI M, byte
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > memory [ adress ] = opcode [ 1 ] ;
state - > pc + + ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-07 12:32:22 +00:00
2024-01-15 23:20:20 +00:00
case 0x37 : // STC
state - > cc . cy = 1 ;
break ;
2024-01-07 12:32:22 +00:00
case 0x3a : // LDA adress
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( opcode [ 2 ] < < 8 ) | ( opcode [ 1 ] ) ;
state - > a = state - > memory [ adress ] ;
state - > pc + = 2 ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0x3b : // DCX SP
{
state - > sp - - ;
}
break ;
case 0x3c : // INR A
{
state - > a + + ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
}
break ;
2024-01-15 23:20:20 +00:00
case 0x3d : // DCR A
{
state - > a - - ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
}
break ;
2024-01-20 11:31:11 +00:00
2024-01-06 19:33:56 +00:00
case 0x3e : // MVI A, byte
state - > a = opcode [ 1 ] ;
2024-01-08 17:07:28 +00:00
state - > pc + + ;
break ;
2024-01-20 11:31:11 +00:00
case 0x3f : // CMC
state - > cc . cy = 0 ;
break ;
2024-01-06 19:33:56 +00:00
case 0x41 : // MOV B, C
state - > b = state - > c ;
break ;
case 0x42 : // MOV B, D
state - > b = state - > d ;
break ;
case 0x43 : // MOV B, E
state - > b = state - > e ;
break ;
2024-01-19 19:20:17 +00:00
case 0x44 : // MOV B, H
state - > b = state - > h ;
break ;
case 0x45 : // MOV B, L
state - > b = state - > l ;
break ;
case 0x46 : // MOV B, M
{
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > b = state - > memory [ adress ] ;
}
case 0x47 : // MOV B, A
state - > b = state - > a ;
break ;
case 0x48 : // MOV C, B
state - > c = state - > b ;
break ;
case 0x49 : // MOV C, C
break ;
case 0x4a : // MOV C, D
state - > c = state - > d ;
break ;
case 0x4b : // MOV C, E
state - > c = state - > e ;
break ;
case 0x4c : // MOV C, H
state - > c = state - > h ;
break ;
case 0x4d : // MOV C, L
state - > c = state - > l ;
break ;
case 0x4e : // MOV C, M
{
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > c = state - > memory [ adress ] ;
}
break ;
case 0x4f : // MOV C, A
state - > c = state - > a ;
break ;
case 0x50 : // MOV D, B
state - > d = state - > b ;
break ;
case 0x51 : // MOV D, C
state - > d = state - > c ;
break ;
case 0x52 : // MOV D, D
break ;
case 0x53 : // MOV D, E
state - > d = state - > e ;
break ;
case 0x54 : // MOV D, H
state - > d = state - > h ;
break ;
case 0x55 : // MOV D, L
state - > d = state - > l ;
break ;
2024-01-07 12:32:22 +00:00
case 0x56 : // MOV D, M
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > d = state - > memory [ adress ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x57 : // MOV D, A
state - > d = state - > a ;
break ;
case 0x58 : // MOV E, B
state - > e = state - > b ;
break ;
case 0x59 : // MOV E, C
state - > e = state - > c ;
break ;
case 0x5a : // MOV E, D
state - > e = state - > d ;
break ;
case 0x5b : // MOV E, E
break ;
case 0x5c : // MOV E, H
state - > e = state - > h ;
break ;
case 0x5d : // MOV E, L
state - > e = state - > l ;
break ;
2024-01-07 12:32:22 +00:00
case 0x5e : // MOV E, M
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > e = state - > memory [ adress ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x5f : // MOV E, A
state - > e = state - > a ;
break ;
case 0x60 : // MOV H, B
state - > h = state - > b ;
break ;
case 0x61 : // MOV H, C
state - > h = state - > c ;
break ;
case 0x62 : // MOV H, D
state - > h = state - > d ;
break ;
case 0x63 : // MOV H, E
state - > h = state - > e ;
break ;
case 0x64 : // MOV H, H
break ;
case 0x65 : // MOV H, L
state - > h = state - > l ;
break ;
2024-01-07 12:32:22 +00:00
case 0x66 : // MOV H, M
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > h = state - > memory [ adress ] ;
}
break ;
case 0x67 : // MOV H, A
{
state - > h = state - > a ;
}
break ;
case 0x68 : // MOV L, B
state - > l = state - > b ;
break ;
case 0x69 : // MOV L, C
state - > l = state - > c ;
break ;
case 0x6a : // MOV L, D
state - > l = state - > d ;
break ;
case 0x6b : // MOV L, E
state - > l = state - > e ;
break ;
case 0x6c : // MOV L, H
state - > l = state - > h ;
break ;
case 0x6d : // MOV L, L
break ;
case 0x6e : // MOV L, M
{
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > l = state - > memory [ adress ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
case 0x6f : // MOV L, A
state - > l = state - > a ;
break ;
case 0x77 : // MOV M, A
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > memory [ adress ] = state - > a ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
case 0x7a : // MOV A, D
state - > a = state - > d ;
break ;
2024-01-19 19:20:17 +00:00
case 0x78 : // MOV A, B
state - > a = state - > b ;
break ;
case 0x79 : // MOV A, C
state - > a = state - > c ;
break ;
2024-01-07 12:32:22 +00:00
case 0x7b : // MOV A, E
state - > a = state - > e ;
break ;
case 0x7c : // MOV A, H
state - > a = state - > h ;
break ;
2024-01-19 19:20:17 +00:00
case 0x7d : // MOV A, L
state - > a = state - > l ;
break ;
2024-01-07 12:32:22 +00:00
case 0x7e : // MOV A, M
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t adress = ( state - > h < < 8 ) | ( state - > l ) ;
state - > a = state - > memory [ adress ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0x7f : // MOV A, A
break ;
2024-01-06 19:33:56 +00:00
case 0x80 : // ADD B
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t answer = ( uint16_t ) state - > a + ( uint16_t ) state - > b ;
state - > cc . z = ( ( answer & 0xff ) = = 0 ) ;
state - > cc . s = ( ( answer & 0x80 ) ! = 0 ) ;
state - > cc . cy = ( answer > 0xff ) ;
state - > cc . p = parity ( answer & 0xff , 8 ) ;
state - > a = answer & 0xff ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
case 0x86 : // ADD M
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t offset = ( state - > h < < 8 ) | ( state - > l ) ;
uint16_t answer = ( uint16_t ) state - > a + state - > memory [ offset ] ;
state - > cc . z = ( ( answer & 0xff ) = = 0 ) ;
state - > cc . s = ( ( answer & 0x80 ) ! = 0 ) ;
state - > cc . cy = ( answer > 0xff ) ;
state - > cc . p = parity ( answer & 0xff , 8 ) ;
state - > a = answer & 0xff ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-07 12:32:22 +00:00
case 0x1f : // RAR
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t x = state - > a ;
state - > a = ( state - > cc . cy < < 7 ) | ( x > > 1 ) ;
state - > cc . cy = ( 1 = = ( x & 1 ) ) ;
2024-01-08 17:07:28 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xa0 : // ANA B
state - > a = state - > a & state - > b ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa1 : // ANA C
state - > a = state - > a & state - > c ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa2 : // ANA D
state - > a = state - > a & state - > d ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa3 : // ANA E
state - > a = state - > a & state - > e ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa4 : // ANA H
state - > a = state - > a & state - > h ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa5 : // ANA L
state - > a = state - > a & state - > l ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xa6 : // ANA HL
{
uint16_t adress = ( state - > h < < 8 ) | state - > l ;
state - > a = state - > a & state - > memory [ adress ] ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
}
break ;
2024-01-07 12:32:22 +00:00
case 0xa7 : // ANA A
state - > a & = state - > a ;
state - > cc . z = ( state - > a = = 0 ) ;
2024-01-08 17:07:28 +00:00
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
2024-01-07 12:32:22 +00:00
state - > cc . p = parity ( state - > a , 8 ) ;
2024-01-20 11:31:11 +00:00
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xa8 : // XRA B
state - > a ^ = state - > b ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xa9 : // XRA C
state - > a ^ = state - > c ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xaa : // XRA D
state - > a ^ = state - > d ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xab : // XRA E
state - > a ^ = state - > e ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xac : // XRA H
state - > a ^ = state - > h ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xad : // XRA L
state - > a ^ = state - > d ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
state - > cc . cy = state - > cc . ac = 0 ;
break ;
case 0xae : // XRA HL
{
uint16_t adress = ( state - > h < < 8 ) | state - > l ;
state - > a ^ = state - > memory [ adress ] ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
}
2024-01-07 12:32:22 +00:00
break ;
case 0xaf : // XRA A
state - > a ^ = state - > a ;
state - > cc . z = ( state - > a = = 0 ) ;
2024-01-08 17:07:28 +00:00
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
2024-01-07 12:32:22 +00:00
state - > cc . p = parity ( state - > a , 8 ) ;
2024-01-20 11:31:11 +00:00
state - > cc . cy = state - > cc . ac = 0 ;
2024-01-07 12:32:22 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0xb0 : // ORA B
state - > a | = state - > b ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
2024-01-20 11:31:11 +00:00
case 0xb1 : // ORA C
state - > a | = state - > c ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xb2 : // ORA D
state - > a | = state - > d ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xb3 : // ORA E
state - > a | = state - > e ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xb4 : // ORA H
state - > a | = state - > h ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
case 0xb5 : // ORA L
state - > a | = state - > l ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
2024-01-19 19:20:17 +00:00
case 0xb6 : // ORA M
{
uint16_t offset = ( state - > h < < 8 ) | ( state - > l ) ;
state - > a | = state - > memory [ offset ] ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
}
break ;
2024-01-20 11:31:11 +00:00
case 0xb7 : // ORA A
state - > a | = state - > a ;
state - > cc . cy = state - > cc . ac = 0 ;
state - > cc . z = ( state - > a = = 0 ) ;
state - > cc . s = ( 0x80 = = ( state - > a & 0x80 ) ) ;
state - > cc . p = parity ( state - > a , 8 ) ;
break ;
2024-01-15 23:20:20 +00:00
case 0xc0 : // RNZ
{
if ( state - > cc . z = = 0 ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
}
break ;
2024-01-06 19:33:56 +00:00
case 0xc1 : // POP B
state - > c = state - > memory [ state - > sp ] ;
state - > b = state - > memory [ state - > sp + 1 ] ;
state - > sp + = 2 ;
break ;
case 0xc2 : // JNZ adress
2024-01-08 17:07:28 +00:00
if ( 0 = = state - > cc . z ) {
2024-01-06 19:33:56 +00:00
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
break ;
case 0xc3 : // JMP adress
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
break ;
2024-01-19 19:20:17 +00:00
case 0xc4 : // CNZ adress
{
if ( 0 = = state - > cc . z ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ret & 0xff ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-06 19:33:56 +00:00
case 0xc5 : // PUSH B
state - > memory [ state - > sp - 1 ] = state - > b ;
state - > memory [ state - > sp - 2 ] = state - > c ;
state - > sp - = 2 ;
break ;
case 0xc6 : // ADI byte
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t answer = ( uint16_t ) state - > a + ( uint16_t ) opcode [ 1 ] ;
state - > cc . z = ( ( state - > a & 0xff ) = = 0 ) ;
state - > cc . s = ( ( state - > a & 0x80 ) = = 0x80 ) ;
state - > cc . cy = ( state - > a > 0xff ) ;
state - > cc . p = parity ( state - > a & 0xff , 8 ) ;
state - > pc + + ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-15 23:20:20 +00:00
case 0xc8 : // RZ
{
if ( state - > cc . z ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
}
break ;
2024-01-07 12:32:22 +00:00
case 0xc9 : // RET
state - > pc = ( state - > memory [ state - > sp + 1 ] < < 8 ) | state - > memory [ state - > sp ] ;
2024-01-09 09:58:58 +00:00
state - > sp + = 2 ;
2024-01-07 12:32:22 +00:00
break ;
2024-01-15 23:20:20 +00:00
case 0xca : // JZ adress
{
if ( state - > cc . z ) {
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-20 11:31:11 +00:00
case 0xcc : // CZ adress
{
if ( state - > cc . z = = 1 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ret & 0xff ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-15 23:20:20 +00:00
2024-01-06 19:33:56 +00:00
case 0xcd : // CALL adress
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xce : // ACI byte
{
uint16_t answer = ( uint16_t ) state - > a + ( uint16_t ) opcode [ 1 ] + state - > cc . cy ;
state - > cc . z = ( ( answer & 0xff ) = = 0 ) ;
state - > cc . s = ( ( ( answer & 0xff ) & 0x80 ) = = 0x80 ) ;
state - > cc . p = parity ( answer & 0xff , 8 ) ;
state - > cc . cy = ( answer > 0xff ) ;
state - > a = answer & 0xff ;
state - > pc + + ;
}
break ;
case 0xcf : // RST 1
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x08 ;
}
break ;
case 0xd0 : // RNC
if ( state - > cc . cy = = 0 ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
break ;
2024-01-07 12:32:22 +00:00
case 0xd1 : // POP D
state - > e = state - > memory [ state - > sp ] ;
state - > d = state - > memory [ state - > sp + 1 ] ;
2024-01-06 19:33:56 +00:00
state - > sp + = 2 ;
2024-01-07 12:32:22 +00:00
break ;
2024-01-15 23:20:20 +00:00
case 0xd2 : // JNC adress
{
if ( 0 = = state - > cc . cy ) {
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-07 12:32:22 +00:00
case 0xd3 : // OUT byte
2024-01-14 20:19:34 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t port = opcode [ 1 ] ;
machineOut ( state , port , 0x00 ) ; // PROBLEM: We need to pass a value to machineOUT
state - > pc + + ;
2024-01-14 20:19:34 +00:00
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xd4 : // CNC Adress
{
if ( state - > cc . cy = = 0 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ( ret > > 8 ) & 0xff ) ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-07 12:32:22 +00:00
case 0xd5 : // PUSH D
state - > memory [ state - > sp - 1 ] = state - > d ;
state - > memory [ state - > sp - 2 ] = state - > e ;
state - > sp - = 2 ;
2024-01-06 19:33:56 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xd6 : // SUI Byte
{
uint8_t x = state - > a - opcode [ 1 ] ;
state - > cc . z = ( x & 0xff = = 0 ) ;
state - > cc . s = ( 0x80 = = ( ( x & 0xff ) & 0x80 ) ) ;
state - > cc . p = parity ( x & 0xff , 8 ) ;
state - > cc . cy = ( state - > a < opcode [ 1 ] ) ;
state - > a = x ;
state - > pc + + ;
}
break ;
case 0xd7 : // RST 2
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ( ret > > 8 ) & 0xff ) ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x10 ;
}
break ;
2024-01-19 19:20:17 +00:00
case 0xd8 : // RC
{
if ( state - > cc . cy ! = 0 ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
}
break ;
2024-01-15 23:20:20 +00:00
case 0xda : // JC adress
{
if ( state - > cc . cy ! = 0 ) {
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-13 21:38:02 +00:00
case 0xdb : // IN byte
2024-01-14 20:19:34 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t port = opcode [ 1 ] ;
state - > a = machineIn ( state , port ) ;
state - > pc + + ;
2024-01-14 20:19:34 +00:00
}
2024-01-13 21:38:02 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xdc : // CC Adress
{
if ( state - > cc . cy ! = 0 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ( ret > > 8 ) & 0xff ) ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
case 0xde : // SBI byte
{
uint16_t x = state - > a - opcode [ 1 ] - state - > cc . cy ;
state - > cc . z = ( x & 0xff = = 0 ) ;
state - > cc . s = ( 0x80 = = ( ( x & 0xff ) & 0x80 ) ) ;
state - > cc . p = parity ( x & 0xff , 8 ) ;
state - > cc . cy = ( x > 0xff ) ;
state - > a = x & 0xff ;
state - > pc + + ;
}
break ;
case 0xdf : // RST 3
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ( ret > > 8 ) & 0xff ) ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x18 ;
}
break ;
case 0xe0 : // RPO
if ( state - > cc . p = = 0 )
{
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
break ;
2024-01-07 12:32:22 +00:00
case 0xe1 : // POP H
state - > l = state - > memory [ state - > sp ] ;
state - > h = state - > memory [ state - > sp + 1 ] ;
state - > sp + = 2 ;
break ;
2024-01-19 19:20:17 +00:00
case 0xe2 : // JPO adress
{
if ( 0 = = state - > cc . p ) {
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
case 0xe3 : // XTHL
{
uint8_t tmp = state - > l ;
state - > l = state - > memory [ state - > sp ] ;
state - > memory [ state - > sp ] = tmp ;
tmp = state - > h ;
state - > h = state - > memory [ state - > sp + 1 ] ;
state - > memory [ state - > sp + 1 ] = tmp ;
}
break ;
case 0xe4 : // CPO adress
{
if ( 0 = = state - > cc . p ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-07 12:32:22 +00:00
case 0xe5 : // PUSH H
state - > memory [ state - > sp - 1 ] = state - > h ;
state - > memory [ state - > sp - 2 ] = state - > l ;
state - > sp - = 2 ;
break ;
2024-01-06 19:33:56 +00:00
case 0xe6 : // ANI byte
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t x = state - > a & opcode [ 1 ] ;
state - > cc . z = ( x = = 0 ) ;
state - > cc . s = ( 0x80 = = ( x & 0x80 ) ) ;
state - > cc . cy = 0 ;
state - > cc . p = parity ( x , 8 ) ;
state - > pc + + ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-19 19:20:17 +00:00
case 0xe7 : // RST 4
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x20 ;
}
break ;
case 0xe8 : // RPE
{
if ( 0 ! = state - > cc . p ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
}
break ;
case 0xe9 : // PCHL
state - > pc = ( state - > h < < 8 ) | state - > l ;
break ;
case 0xea : // JPE
if ( state - > cc . p ! = 0 )
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
else
state - > pc + = 2 ;
break ;
2024-01-07 12:32:22 +00:00
case 0xeb : // XCHG
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t tmp = state - > h ;
state - > h = state - > d ;
state - > d = tmp ;
tmp = state - > l ;
state - > l = state - > e ;
state - > e = tmp ;
}
break ;
case 0xec : // CPE Adress
{
if ( state - > cc . p ! = 0 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
case 0xee : // XRI Data
{
uint8_t x = state - > a ^ opcode [ 1 ] ;
state - > cc . z = ( x = = 0 ) ;
state - > cc . s = ( 0x80 = = ( x & 0x80 ) ) ;
state - > cc . p = parity ( x , 8 ) ;
state - > cc . cy = 0 ;
state - > a = x ;
state - > pc + + ;
}
break ;
case 0xef : // RST 5
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x28 ;
}
break ;
case 0xf0 : // RP
{
if ( state - > cc . s = = 0 ) {
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > pc + = 2 ;
}
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-06 21:23:36 +00:00
case 0xf1 : // POP PSW
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
state - > a = state - > memory [ state - > sp + 1 ] ;
uint8_t psw = state - > memory [ state - > sp ] ;
state - > cc . z = ( 0x01 = = ( psw & 0x01 ) ) ;
state - > cc . s = ( 0x02 = = ( psw & 0x02 ) ) ;
state - > cc . p = ( 0x04 = = ( psw & 0x04 ) ) ;
state - > cc . cy = ( 0x08 = = ( psw & 0x08 ) ) ;
state - > cc . ac = ( 0x10 = = ( psw & 0x10 ) ) ;
state - > sp + = 2 ;
}
break ;
case 0xf2 : // JP Adress
{
if ( state - > cc . s = = 0 ) {
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
case 0xf3 : // DI
state - > int_enable = 0 ;
break ;
case 0xf4 : // CP
{
if ( state - > cc . s = = 0 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
2024-01-08 17:07:28 +00:00
}
2024-01-06 21:23:36 +00:00
break ;
case 0xf5 : // PUSH PSW
state - > memory [ state - > sp - 1 ] = state - > a ;
state - > memory [ state - > sp - 2 ] = ( state - > cc . z | ( state - > cc . s < < 1 ) | ( state - > cc . p < < 2 ) | ( state - > cc . cy < < 3 ) | ( state - > cc . ac < < 4 ) ) ;
state - > sp - = 2 ;
break ;
2024-01-20 11:31:11 +00:00
case 0xf6 : // ORI
{
uint8_t x = state - > a | opcode [ 1 ] ;
state - > cc . z = ( x = = 0 ) ;
state - > cc . s = ( 0x80 = = ( x & 0x80 ) ) ;
state - > cc . p = parity ( x , 8 ) ;
2024-01-06 21:23:36 +00:00
2024-01-20 11:31:11 +00:00
state - > cc . cy = 0 ;
state - > a = x ;
state - > pc + + ;
}
2024-01-07 12:32:22 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xf7 : // RST 6
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x30 ;
}
break ;
case 0xf8 : //RM
if ( state - > cc . s ! = 0 )
{
state - > pc = state - > memory [ state - > sp ] | ( state - > memory [ state - > sp + 1 ] < < 8 ) ;
state - > sp + = 2 ;
}
break ;
case 0xf9 : // SPHL
state - > sp = state - > l | ( state - > h < < 8 ) ;
break ;
case 0xfa : // JM
if ( state - > cc . s ! = 0 )
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
else
state - > pc + = 2 ;
break ;
case 0xfb : // EI
state - > int_enable = 1 ;
break ;
case 0xfc : // CM
{
if ( state - > cc . s ! = 0 ) {
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = ( opcode [ 2 ] < < 8 ) | opcode [ 1 ] ;
} else {
state - > pc + = 2 ;
}
}
break ;
2024-01-06 19:33:56 +00:00
case 0xfe : // CPI byte
2024-01-08 17:07:28 +00:00
{
2024-01-19 19:20:17 +00:00
uint8_t x = state - > a - opcode [ 1 ] ;
state - > cc . z = ( x = = 0 ) ;
state - > cc . s = ( 0x80 = = ( x & 0x80 ) ) ;
state - > cc . cy = ( state - > a < opcode [ 1 ] ) ;
state - > cc . p = parity ( x , 8 ) ;
state - > pc + + ;
2024-01-08 17:07:28 +00:00
}
2024-01-06 19:33:56 +00:00
break ;
2024-01-20 11:31:11 +00:00
case 0xff : // RST 7
{
uint16_t ret = state - > pc + 2 ;
state - > memory [ state - > sp - 1 ] = ( ret > > 8 ) & 0xff ;
state - > memory [ state - > sp - 2 ] = ( ret & 0xff ) ;
state - > sp - = 2 ;
state - > pc = 0x38 ;
}
break ;
2024-01-06 19:33:56 +00:00
default : unknownInstruction ( state ) ; break ;
}
2024-01-13 21:38:02 +00:00
printState ( state ) ;
2024-01-14 16:50:35 +00:00
return cycles8080 [ * opcode ] ;
2024-01-07 12:32:22 +00:00
}
2024-01-14 12:26:06 +00:00
void generateInterrupt ( State8080 * state , int interrupt_num )
2024-01-14 10:00:05 +00:00
{
2024-01-14 12:26:06 +00:00
//perform "PUSH PC"
state - > memory [ state - > sp - 1 ] = ( ( state - > pc & 0xFF00 ) > > 8 ) ;
state - > memory [ state - > sp - 2 ] = ( state - > pc & 0xff ) ;
state - > sp - = 2 ;
2024-01-14 10:00:05 +00:00
//Set the PC to the low memory vector.
2024-01-14 12:26:06 +00:00
state - > pc = 8 * interrupt_num ;
state - > int_enable = 0 ;
2024-01-14 10:00:05 +00:00
}
2024-01-08 17:07:28 +00:00
void read_Space_Invaders_ROM ( State8080 * state , const char * filename , int offset ) {
//Works exclusively with the memory system of Space Invaders
FILE * file = fopen ( filename , " rb " ) ;
if ( file = = NULL ) {
printf ( " Issue opening the file. \n " ) ;
exit ( 1 ) ;
2024-01-07 12:32:22 +00:00
}
2024-01-08 17:07:28 +00:00
//Get the file size and read it into a memory buffer
fseek ( file , 0L , SEEK_END ) ;
int fsize = ftell ( file ) ;
fseek ( file , 0L , SEEK_SET ) ;
uint8_t * buffer = & state - > memory [ offset ] ;
fread ( buffer , fsize , 1 , file ) ;
fclose ( file ) ;
2024-01-13 21:38:02 +00:00
}
2024-01-08 17:07:28 +00:00
2024-01-14 16:50:35 +00:00
void keyDown ( uint8_t key )
{
switch ( key ) {
case 0 : // COIN
in_port | = 0x1 ;
break ;
case 1 : // LEFT
in_port | = 0x20 ;
break ;
case 2 : // RIGHT
in_port | = 0x40 ;
break ;
case 3 : // FIRE
in_port | = 0x10 ;
break ;
case 4 : // START
in_port | = 0x04 ;
break ;
}
}
void keyUp ( uint8_t key )
{
switch ( key ) {
case 0 : // COIN
in_port & = ~ 0x1 ;
break ;
case 1 : // LEFT
in_port & = ~ 0x20 ;
break ;
case 2 : // RIGHT
in_port & = ~ 0x40 ;
break ;
case 3 : // FIRE
in_port & = ~ 0x10 ;
break ;
case 4 : // START
in_port & = ~ 0x04 ;
break ;
}
}
2024-01-15 13:06:04 +00:00
typedef struct cpu_data {
char done ;
int total_cycles_count ;
GtkWidget * drawing_area ;
State8080 * state ;
2024-01-14 21:35:01 +00:00
2024-01-15 13:06:04 +00:00
} cpu_data ;
2024-01-14 21:35:01 +00:00
2024-01-19 21:45:49 +00:00
void * cpu ( void * arg ) {
cpu_data * cpu = ( cpu_data * ) arg ;
char done = cpu - > done ;
State8080 * state = cpu - > state ;
int counter ;
2024-01-14 21:35:01 +00:00
2024-01-19 21:45:49 +00:00
while ( ! done ) {
counter = emulate8080 ( cpu - > state ) ;
cpu - > total_cycles_count + = counter ;
printf ( " Total cycles: %d \n " , cpu - > total_cycles_count ) ;
//usleep(counter / 2); // EMULATION OF THE PROCESSOR ŠPEED
if ( ( cpu - > total_cycles_count > 16000 ) & & ( state - > int_enable ) ) //1/60 second has elapsed
{
//redraw screen() will be handeled by the gtk_main() function
if ( which_interrupt = = 2 ) {
generateInterrupt ( state , 2 ) ; //interrupt 2
cpu - > total_cycles_count = 0 ;
which_interrupt = 1 ;
} else {
generateInterrupt ( state , 1 ) ; //interrupt 1
cpu - > total_cycles_count = 0 ;
which_interrupt = 2 ;
}
}
}
}
2024-01-19 19:20:17 +00:00
2024-01-19 21:45:49 +00:00
// ===== GTK GRAPHICS =====
2024-01-19 19:20:17 +00:00
static void draw_callback ( GtkWidget * widget , cairo_t * cr , gpointer user_data ) {
uint8_t * video = malloc ( sizeof ( uint8_t ) * 256 * 256 ) ; // Adjusted size
2024-01-20 11:31:11 +00:00
// Clear the drawing area if you want
//cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
//cairo_paint(cr);
2024-01-19 19:20:17 +00:00
// Copying the bitmap to video output
for ( int i = 0 ; i < 224 ; i + + ) {
for ( int j = 0 ; j < 32 ; j + + ) {
uint8_t byte = bitmap [ i * 32 + j ] ;
for ( int p = 0 ; p < 8 ; p + + ) {
int pixel = ( byte > > p ) & 1 ; // flip the bit order within each byte
int x = i ; // swap x and y
int y = 255 - ( j * 8 + p ) ; // flip the y-coordinate
if ( x > = 0 & & x < 256 & & y > = 0 & & y < 256 ) { // Check bounds
video [ y * 256 + x ] = pixel ;
}
2024-01-15 20:15:53 +00:00
}
}
}
2024-01-19 19:20:17 +00:00
// Rendering the graphics
2024-01-20 11:31:11 +00:00
for ( int x = 0 ; x < 224 ; x + + ) {
2024-01-19 19:20:17 +00:00
for ( int y = 0 ; y < 256 ; y + + ) {
if ( video [ y * 256 + x ] ) {
2024-01-15 19:44:19 +00:00
cairo_set_source_rgb ( cr , 1.0 , 1.0 , 1.0 ) ; // Set color to white
} else {
cairo_set_source_rgb ( cr , 0.0 , 0.0 , 0.0 ) ; // Set color to black
2024-01-14 21:35:01 +00:00
}
2024-01-15 19:44:19 +00:00
cairo_rectangle ( cr , x * upscaleFactor , y * upscaleFactor , upscaleFactor , upscaleFactor ) ;
cairo_fill ( cr ) ;
2024-01-14 21:35:01 +00:00
}
}
2024-01-19 19:20:17 +00:00
2024-01-15 20:15:53 +00:00
free ( video ) ;
2024-01-15 13:06:04 +00:00
}
2024-01-14 21:35:01 +00:00
2024-01-19 21:45:49 +00:00
void on_about_clicked ( GtkToolButton * toolbutton , gpointer user_data ) {
GtkWidget * dialog = gtk_about_dialog_new ( ) ;
2024-01-20 11:31:11 +00:00
gtk_about_dialog_set_program_name ( GTK_ABOUT_DIALOG ( dialog ) , " Lux8080-Emulator " ) ;
gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG ( dialog ) , " This is a simple Intel 8080-Emulator for Space Invaders using C and GTK. Following the guide of @realemulator101 " ) ;
gtk_about_dialog_set_logo_icon_name ( GTK_ABOUT_DIALOG ( dialog ) , " your logo " ) ;
2024-01-19 21:45:49 +00:00
gtk_dialog_run ( GTK_DIALOG ( dialog ) ) ;
gtk_widget_destroy ( dialog ) ;
2024-01-14 21:35:01 +00:00
}
2024-01-19 19:20:17 +00:00
gboolean update_ui ( gpointer data ) {
// Seems like GTK is not thread safe
// we fix it with update_ui using gtk_main_iteration_do(FALSE)
GtkWidget * drawing_area = ( GtkWidget * ) data ;
gtk_widget_queue_draw ( drawing_area ) ;
while ( gtk_events_pending ( ) )
gtk_main_iteration_do ( FALSE ) ;
return TRUE ;
}
2024-01-19 21:45:49 +00:00
void on_size_changed ( GtkComboBox * combo_box , gpointer user_data ) {
gchar * text = gtk_combo_box_text_get_active_text ( GTK_COMBO_BOX_TEXT ( combo_box ) ) ;
if ( g_strcmp0 ( text , " 1x " ) = = 0 ) {
upscaleFactor = 1 ;
} else if ( g_strcmp0 ( text , " 2x " ) = = 0 ) {
upscaleFactor = 2 ;
} else if ( g_strcmp0 ( text , " 3x " ) = = 0 ) {
upscaleFactor = 3 ;
}
g_free ( text ) ;
}
2024-01-14 19:45:36 +00:00
int main ( int argc , char * argv [ ] ) {
2024-01-19 19:20:17 +00:00
// Emulator init
2024-01-07 12:32:22 +00:00
2024-01-14 12:26:06 +00:00
State8080 * state = ( State8080 * ) calloc ( 1 , sizeof ( State8080 ) ) ; //memset obsolte with calloc
2024-01-08 17:07:28 +00:00
state - > cc . z = 1 ;
state - > cc . s = 1 ;
state - > cc . p = 1 ;
state - > cc . cy = 0 ;
2024-01-15 23:20:20 +00:00
state - > cc . ac = 1 ;
state - > int_enable = 1 ;
2024-01-07 12:32:22 +00:00
state - > pc = 0 ;
2024-01-19 19:20:17 +00:00
state - > memory = calloc ( 0x10000 , 1 ) ;
2024-01-08 17:07:28 +00:00
read_Space_Invaders_ROM ( state , " ROM/invaders.h " , 0 ) ;
read_Space_Invaders_ROM ( state , " ROM/invaders.g " , 0x800 ) ;
read_Space_Invaders_ROM ( state , " ROM/invaders.f " , 0x1000 ) ;
read_Space_Invaders_ROM ( state , " ROM/invaders.e " , 0x1800 ) ;
2024-01-14 21:35:01 +00:00
2024-01-19 19:20:17 +00:00
// GTK init
2024-01-15 13:06:04 +00:00
gtk_init ( & argc , & argv ) ;
GtkWidget * window = gtk_window_new ( GTK_WINDOW_TOPLEVEL ) ;
2024-01-20 11:31:11 +00:00
gtk_window_set_default_size ( GTK_WINDOW ( window ) , 448 , 550 ) ;
gtk_window_set_title ( GTK_WINDOW ( window ) , " Lux8080-Emulator " ) ;
2024-01-15 13:06:04 +00:00
g_signal_connect ( window , " key-press-event " , G_CALLBACK ( on_key_press ) , NULL ) ;
g_signal_connect ( window , " key-release-event " , G_CALLBACK ( on_key_release ) , NULL ) ;
g_signal_connect ( window , " destroy " , G_CALLBACK ( gtk_main_quit ) , NULL ) ;
2024-01-14 21:35:01 +00:00
2024-01-19 21:45:49 +00:00
// Toolbar init
GtkWidget * toolbar = gtk_toolbar_new ( ) ;
GtkCssProvider * provider = gtk_css_provider_new ( ) ;
gtk_css_provider_load_from_data ( provider , " * { -GtkWidget-toolbar-style: both-horiz; } " , - 1 , NULL ) ;
gtk_style_context_add_provider ( gtk_widget_get_style_context ( toolbar ) , GTK_STYLE_PROVIDER ( provider ) , GTK_STYLE_PROVIDER_PRIORITY_USER ) ;
// Size option in the toolbar
GtkToolItem * size = gtk_tool_item_new ( ) ;
GtkWidget * combo_box = gtk_combo_box_text_new ( ) ;
gtk_combo_box_text_append_text ( GTK_COMBO_BOX_TEXT ( combo_box ) , " 1x " ) ;
gtk_combo_box_text_append_text ( GTK_COMBO_BOX_TEXT ( combo_box ) , " 2x " ) ;
gtk_combo_box_text_append_text ( GTK_COMBO_BOX_TEXT ( combo_box ) , " 3x " ) ;
gtk_container_add ( GTK_CONTAINER ( size ) , combo_box ) ;
gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ) , size , - 1 ) ;
g_signal_connect ( combo_box , " changed " , G_CALLBACK ( on_size_changed ) , NULL ) ;
// About option in the toolbar
GtkToolItem * about = gtk_tool_button_new ( NULL , " About " ) ;
gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ) , about , - 1 ) ;
g_signal_connect ( about , " clicked " , G_CALLBACK ( on_about_clicked ) , NULL ) ;
2024-01-19 19:20:17 +00:00
// Drawing area init
2024-01-14 21:39:57 +00:00
bitmap = & ( state - > memory [ 0x2400 ] ) ;
2024-01-14 21:35:01 +00:00
GtkWidget * drawing_area = gtk_drawing_area_new ( ) ;
2024-01-15 19:44:19 +00:00
gtk_widget_set_app_paintable ( drawing_area , TRUE ) ;
2024-01-14 21:39:57 +00:00
g_signal_connect ( drawing_area , " draw " , G_CALLBACK ( draw_callback ) , NULL ) ;
2024-01-19 21:45:49 +00:00
// VBox to hold toolbar and drawing area
GtkWidget * vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , toolbar , FALSE , FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , drawing_area , TRUE , TRUE , 0 ) ;
gtk_container_add ( GTK_CONTAINER ( window ) , vbox ) ;
2024-01-14 21:35:01 +00:00
gtk_widget_show_all ( window ) ;
2024-01-19 19:20:17 +00:00
// CPU-init
2024-01-15 13:06:04 +00:00
cpu_data * cpu_eco = malloc ( sizeof ( cpu_data ) ) ;
cpu_eco - > state = state ;
cpu_eco - > drawing_area = drawing_area ;
cpu_eco - > done = 0 ;
cpu_eco - > total_cycles_count = 0 ;
2024-01-14 21:35:01 +00:00
2024-01-19 19:20:17 +00:00
// Pthread
2024-01-15 19:44:19 +00:00
pthread_t pid ;
pthread_create ( & pid , NULL , cpu , ( void * ) cpu_eco ) ;
2024-01-19 19:20:17 +00:00
// Main GTK Loop
g_timeout_add ( 200 , update_ui , drawing_area ) ;
2024-01-14 21:35:01 +00:00
gtk_main ( ) ;
2024-01-15 19:44:19 +00:00
pthread_join ( pid , NULL ) ;
2024-01-08 17:07:28 +00:00
free ( state - > memory ) ;
free ( state ) ;
2024-01-15 13:06:04 +00:00
free ( cpu_eco ) ;
2024-01-07 12:32:22 +00:00
return 0 ;
2024-01-06 19:33:56 +00:00
}