From 1d5d33a61322480199852d738060c8d252e8d966 Mon Sep 17 00:00:00 2001 From: Luxdragon Date: Sat, 6 Jan 2024 20:33:56 +0100 Subject: [PATCH] disassembler + first emulated commands --- ROM/invaders | Bin 0 -> 8192 bytes ROM/invaders.e | Bin 0 -> 2048 bytes ROM/invaders.f | Bin 0 -> 2048 bytes ROM/invaders.g | Bin 0 -> 2048 bytes ROM/invaders.h | Bin 0 -> 2048 bytes disassembler.c | 353 +++++++++++++++++++++++++++++++++++++++++++++++ emulator_shell.c | 213 ++++++++++++++++++++++++++++ 7 files changed, 566 insertions(+) create mode 100644 ROM/invaders create mode 100644 ROM/invaders.e create mode 100644 ROM/invaders.f create mode 100644 ROM/invaders.g create mode 100644 ROM/invaders.h create mode 100644 disassembler.c create mode 100644 emulator_shell.c diff --git a/ROM/invaders b/ROM/invaders new file mode 100644 index 0000000000000000000000000000000000000000..606ec01945d665881793becbde201b7292947a9e GIT binary patch literal 8192 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 literal 0 HcmV?d00001 diff --git a/ROM/invaders.e b/ROM/invaders.e new file mode 100644 index 0000000000000000000000000000000000000000..66da886fa0242d32d972fd2bd4744d3b999a1239 GIT binary patch literal 2048 zcmY*ZeP|o!8Gr9X(&;3f?sQVPJDsfeB>AMI!BMm{b~H(m-6XcMHgzD&7#pqoL6fn# zVIee5&~$F;AA!LLERdw7B~XUf(y^@t6Id~}4%3|5qlQ42ef+VGO=E2+E$y~ogm2G# zme=-`?)|;L=Y8&X&-1(=*miapFXGO^S}2t7EG!2pdqXkAlJuG`q}(sK246XYsilm2 zQu))U;vQ1$lH&f3r#>K-yY9n^T~$_tqI)2@;;dHB;78qG@GB0#>5bk#%kZZd{&9x? z9<$&WUA!-U%>5%ZSzW`o)~+knF7C0r-pAd`id05w?p)m@QRQ0`Nd-K8WhUysS@DZ&y|EuLur}98S-yy|#E))!~ z3{CADDduz~C5u8V8VQF2o^~NG2f7u_*{Z~`{E;WlI;%mZojvu_?Abu~sMhWs{0~00 z0(C9yNBQ<l*k{x31qziypd}212420{$ShuHSwc;vp|Y z)avZU#%xvfXZ#KXsqa~|%5d$z1#XwnvE+zWQ!$yZj8}0L*&iQs@bSS#Dg>vYZP40Sqv9>=WPCdDp zxz0^ofgH@Nme#a%R?BD_q&YJ^H8s_2Hp$jW#1WLhdsdKxL z?g=A*%|u5&&hR5&X1I|Xx>p=Cqe?<%C8e0zE@)BT9>MZt3x^6>K&#bi?FVd(kB{dF z2W$-N;{-_%fG~e}l5mdWEI>4Fk!eIj9Xo&)m(2P8z+ulJ3oDrTSt7?0B>KKC=#_nb zc%n|`ryf4K7q9|xn1Icu)ocQG2D)vUqT9eNI!Y6rr;=RqDZm*qF3tcxbhvf=3BU#* z(MN_wK9BN;TP>nHG2Z(AGl0=#!6MZ^cl`MAV}L_DTdgC2&B>|h8NmI6I_zz=j@Ez= z(t$j4N&j938)-?>0CPzzN$Lg14)!xDY+Xx(Bc2#G%~E=+4LP_yQZ`Jt|zmhT_0sVT4EVaHn(0F`|3#I<|ES>zEAE zggQjQLlN45sHt9BkSz8xdeI!xu$^Jke2bs8yG6x_;34ZN1`kr2&`IBHv-u~?Ffec4 z`@Q#m@AsZ0?LNB->?-iuDj-hjQhn8GC063MD|Wy4zwt~4DfOG;D>|1Xgw$8Pie0h0 z?jfDmtxEqk=tu>X`mWv$eyej#_nfa` zo6@Vf#tpqBqvPccJM{g!fEbWwh7(UIV(V@EQhfgdmF+>j}Oj*y*_VjJ&Tr)h0Ph1KLlu zagIZshu{M;l}sk5r>D=pH_66focAng8#9EnUa0za2)$ksb#h+~5#0+@&K_VHaFW33 zU?B>KmpL!EK~&SN`V)q&_`ee#t!s5#zOMc|>OUmUxX2o^bQs6mB0ZS$4>|3egHW!~ z2^f?40ja}-5eT|7B7UNSaQBK& z^6VZq;|7htm7TLPy11Aw6x4l4t?%(2LmikBTYJQv%@ok;=%Jj2ChZ3(P{h*ityVgt1>tnzgdjLf~Tad+ZaOH!bH1MCt8f*=_eFL(RW# zmgJii&$$HjN35-`N3GW*%uf}p6fLW-*)UgRz7oT?omgg9aaTAn4*DRa_)oBaa}{vb U&FsPeHHw);B+;$3hhFF6e>6OT6#xJL literal 0 HcmV?d00001 diff --git a/ROM/invaders.g b/ROM/invaders.g new file mode 100644 index 0000000000000000000000000000000000000000..6b90e831e6cc379227aea043f5dfad44cd77df9c GIT binary patch literal 2048 zcmeHG-)kII6rP!^vv+3dPKMnyGt-TGZ#Qj7wk&m`s~M7^KDGXM5Fe_25XA@Mi&P7; zMbl|%P>Q}-f)IaDiZ6>4-Bv_JeMshF=_DN6utwL(gG9_yNg%8tAZgh3%%=69F!$kd z=G^bh`R;eWQ*~x3+!Wn$sz;{?q$T`-YXU4-GKDP@%)Ovmu+ak-6!$!>%&jYs>V=0D zs1rEU3n$dM$BCSXk#F?YWJs7iM+8AIzO!M2$kR)ru1BvDJ(^DPvq?|nA1A?v~s+WLwHD?~dcs(EW*4W)L7#KA%Z-*^AI73+elV4H6o{ z11krGlY@hU*6OlMYBC?mxC(8ZzBP1_p7|;mRG1)pqBBVg`!CWEjJ?ISA40cPDEO5d zau0SRbH^098%gE;Z|hK09`ZMtc%Z+3EO-v{#*0}P$uvjdJ-bs?61=waA(gxNmdP&n zwWNB!m8j=KtaqDu!>ZGyD?@+N)n$Kjp!`DKe|Mn#Y~Ihme3E~zya`__Z!K=>xEebA zs5CqKLU`Tg?T%vXA6jSIG-OhLNywjR z)jNFebz(OhRd=$X+e2IJ&|OE*OsL0Xf);t~G)yQy+n^<(P%e~2_7V*}2@P12-Fd{l zjofBwxM;`k<0W@~I~H70@vWxRkUdTLlahCY|EhZDa9if51a}sF`@O11ub6st1u>aI zO6ODRT}nZOsesCRxMNpqUA6n*ymbezsqPxBu-?O|L~vU(wz4p#8r43ysp1jznDBK6 z5Imt7AK37R3g=Yg>b{)-5k{E%FJ|8i%PJZVOJYsitP(u0!2)sG49?o9FDe!5WlLzH z&ZNZ?)zolQP^{Ors&jzGf=yzC$JqXYmD;bKu^ki?~QL7VlBJWU@8tk2b_I^5Van#+5$2CD$|@Xa13u7DzgEP)g}I Pe7kE`fn5durwaTF#wig=;w5TMC(vL*_)BZsBqd&}#s?D$Vyj!fhZ6?7`6Xie^*TzPPRUtPbf*!Ca-kN3Ia9WPZBFNYZS^=i$J*&tVWhjWx(J5 z?yqQJSaqJIf`NRMzJQ@l`CIBo60eFdU@~xdCz;|cFl_Gi+dlsZ{Y%?{;(TmmBJQ4~ zqvh&>(tPaci9z?Lw8N8>GsqHiZ->}AN;joo6IW*S zA;Wzv=(v~xs&sO;B^SPZ(VD?(4k_|ba&C37x~Sh!5)1BDMNY=ujKX7J`wyzV@69OY z@Y5Gc&bVS?W`C%d-!b*XN-sKDx%$i{o} zgM@sdrR=@jDQ|Y$Wv?$}y@wjbE)Tb(brF*7iY!Ksny;kOV?=&LSED)3$mMk*2026I zLH@RNR_IW?q7I0+KwfQ;$CK_|Eoi$UvPE(4D5xkt3Yd7i>|O|wbe38v7-?RDgCVO2 zqV<_jwEkMiErevHOVbc)2zfWiok=;8luyQUM682a(f`mZga$+kaB9)-M=K4@)fT&Y~p?B4QIS;*!H89CD|XA z&%_(%Hq*>x@Ru>O5gc<#d|(_So{tD*X<}>_moDPuxyFLk2d4^RE66wE)(eNn2WaN5`bH9Z5lyKYUTtr4 z&#P+#lRMO@+U4z)srj}-hqIm4co8yz4d)qd&aZDUO28)}lSyYXIVPsSeTkJTF1{)S z;&|#Tobl8QqGH@ejbo?rJ1x zpN#V}%~OpeSuEJ#!nhpk;*&kb8E`S?lPOdJ62A#eXDTJoP5AnL{nN+W!}8Mzel7=j zY)gCG`DR3aKZzsP=yKRQuCcdg#e0CSryqT4IU&X!Fz$ogl#uBJdK{;8QrrULCKyW~ w_b22nDsNM{5D^c!cwop6@Pq1e;Ty6-WjMi$JB<6>xNo50p_9pT5e$X=3yLDh>i_@% literal 0 HcmV?d00001 diff --git a/disassembler.c b/disassembler.c new file mode 100644 index 0000000..77b42fe --- /dev/null +++ b/disassembler.c @@ -0,0 +1,353 @@ +#include +#include + +// gcc disassembler.c -o disassembler + +typedef struct buffer { + unsigned char* buffer; + int length; +} buffer; + +buffer* read_file(char** argv) { + FILE* file = fopen(argv[1], "rb"); + if (file == NULL) { + printf("Issue opening the file.\n"); + return NULL; + } + + //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); + + buffer *b = malloc(sizeof(buffer)); + b->buffer=malloc(fsize); + b->length=fsize; + + fread(b->buffer, fsize, 1, file); + fclose(file); + + return b; +} + +void print_buffer(buffer* b) { + for (int i = 0; i < 40; i++) { + printf("%02x \n", b->buffer[i]); + } +} + +int disassemble8080(buffer* b, int pc) { + unsigned char *code = &(b->buffer[pc]); + int opbytes = 1; + printf("%04x ", pc); + 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; +} + +int main (int argc, char** argv) { + int pc = 0; //Program Counter + + buffer* buff = read_file(argv); + if (buff == NULL) { + printf("Fatal error.\n"); + return 1; + } + print_buffer(buff); + while (pc < 40) {//buff->length) { + pc += disassemble8080(buff, pc); + } + free(buff); + return 0; + +} \ No newline at end of file diff --git a/emulator_shell.c b/emulator_shell.c new file mode 100644 index 0000000..80b855c --- /dev/null +++ b/emulator_shell.c @@ -0,0 +1,213 @@ +#include +#include // for the uintx_t's + + +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; + struct ConditionCodes cc; + uint8_t int_enable; +} State8080; + +int unknownInstruction(State8080* state) { + printf("Error: Unknown instruction"); + return 1; +} + +int parity(int x, int size) +{ + int i; + int p = 0; + x = (x & ((1<> 1; + } + return (0 == (p & 0x1)); +} + +int emulate8080(State8080* state) { + unsigned char *opcode = &(state->memory[state->pc]); + + 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; + case 0x05: // DCR B + uint8_t res = state->b - 1; + state->b = res; + state->cc.z = (res == 0); + state->cc.s = ((res & 0x80) != 0); + state->cc.p = parity(res, 8); + break; + case 0x06: // MVI B, byte + state->b = opcode[1]; + state->pc += 1; + break; + case 0x09: // DAD B + uint32_t h1 = (state->h << 8) | state->l; + uint32_t bc = (state->b << 8) | state->c; + uint32_t res = h1 + bc; + state->h = (res & 0xff) >> 8; + state->l = res & 0xff; + state->cc.cy = ((res > 0xffff) > 0); + break; + case 0x0e: // MVI C, byte + state->c = opcode[1]; + state->pc += 1; + break; + case 0x11: // LXI D, word + state->d = opcode[2]; + state->e = opcode[1]; + state->pc += 2; + case 0x21: // LXI H, word + state->h = opcode[2]; + state->l = opcode[1]; + state->pc += 2; + case 0x26: // MVI H, byte + state->h = opcode[1]; + state->pc += 1; + break; + case 0x31: // LXI SP, word + state->sp = (opcode[2] << 8) | opcode[1]); + state->pc += 2; + case 0x36: // MVI M, byte + state->m = opcode[1]; + state->pc += 1; + break; + case 0x3e: // MVI A, byte + state->a = opcode[1]; + state->pc += 1; + 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; + case 0x80: // ADD B + 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); + state->a = answer & 0xff; + break; + + case 0x86: // ADD M + 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); + state->a = answer & 0xff; + break; + + 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 + if (0 = state-> cc.z) { + state->pc = (opcode[2] << 8) | opcode[1]; + } else { + state->pc += 2; + } + break; + + case 0xc3: // JMP adress + state->pc = (opcode[2] << 8) | opcode[1]; + break; + + 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 + uint16_t answer = (uint16_t) state->a + (uint16_t) opcode[1]; + state->cc.z = ((state->a & 0xff) == 0); + state->cc.s = ((state->a & 0x80) != 0); + state->cc.cy = (state->a > 0xff); + state->cc.p = parity(state->a & 0xff); + state->pc += 1; + break; + case 0xcd: // CALL adress + 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]; + break; + case 0xc9: // RET + state->sp += 2; + state->pc = (state->memory[state->sp+1] << 8) | state->memory[state->sp]; + break; + + case 0x2f: // CMA (NOT) + state->a = ~state->a; + break; + case 0xe6: // ANI byte + 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++; + break; + + case 0x0f: // RRC + uint8_t x = state->a; + state->a = ((x & 1) << 7) | (x >> 1); + state->cc.cy = (1 == (x & 1)); + break; + + case 0x1f: // RAR + uint8_t x = state->a; + state->a = (state->cc.cy << 7) | (x >> 1); + state->cc.cy = (1 == (x & 1)); + break; + + case 0xfe: // CPI byte + 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++; + break; + + default: unknownInstruction(state); break; + } + state->pc+1; +} \ No newline at end of file