diff --git a/resources.r b/resources.r new file mode 100644 index 0000000..ad58545 --- /dev/null +++ b/resources.r @@ -0,0 +1,111 @@ +data 'MENU' (128) { + $"0080 0000 0000 0000 0000 FFFF FFFF 0114" /* ........... */ + $"0841 626F 7574 2E2E 2E00 0000 0000" /* .About........ */ +}; + +data 'MENU' (129) { + $"0081 0000 0000 0000 0000 FFFF FFF7 0446" /* ..........F */ + $"696C 6507 4F70 656E 2E2E 2E00 4F00 000F" /* ile.Open....O... */ + $"5361 7665 2053 6372 6565 6E73 686F 7400" /* Save Screenshot. */ + $"5300 0001 2D00 0000 0004 4578 6974 0051" /* S...-.....Exit.Q */ + $"0000 00" /* ... */ +}; + +data 'MENU' (130) { + $"0082 0000 0000 0000 0000 FFFF FFFB 0945" /* .........E */ + $"6D75 6C61 7469 6F6E 0550 6175 7365 0050" /* mulation.Pause.P */ + $"0000 012D 0000 0000 0E50 7265 6665 7265" /* ...-.....Prefere */ + $"6E63 6573 2E2E 2E00 2C00 000F 4B65 7920" /* nces....,...Key */ + $"4D61 7070 696E 6773 2E2E 2E00 4B00 0000" /* Mappings....K... */ +}; + +data 'MBAR' (128) { + $"0003 0080 0081 0082" /* ..... */ +}; + +data 'DLOG' (128) { + $"0034 007E 008E 01A0 0003 0100 0100 0000" /* .4.~.......... */ + $"0000 0080 0000 300A" /* .....0. */ +}; + +data 'DITL' (128) { + $"0002 0000 0000 003C 00DC 0050 0116 0405" /* .......<..P.... */ + $"436C 6F73 6558 0000 0000 0014 000A 0034" /* CloseX.........4 */ + $"002A A002 0080 0000 0000 000A 0032 003A" /* .*.........2.: */ + $"010C 8842 4761 6D65 2042 6F79 2045 6D75" /* ..BGame Boy Emu */ + $"6C61 746F 7220 666F 7220 3638 6B20 4D61" /* lator for 68k Ma */ + $"630D 5665 7273 696F 6E20 312E 300D 436F" /* cVersion 1.0Co */ + $"7079 7269 6768 7420 3230 3133 204D 6174" /* pyright 2013 Mat */ + $"7420 4C61 7578" /* t Laux */ +}; + +data 'DITL' (129) { + $"0002 0000 0000 001E 00DC 0032 0116 0403" /* ..........2.... */ + $"4372 79BD 0000 0000 000A 000A 002A 002A" /* Cry.........*.* */ + $"A002 0000 0000 0000 000A 0032 001B 0117" /* ..........2.... */ + $"881E 4E6F 7420 656E 6F75 6768 206D 656D" /* .Not enough mem */ + $"6F72 7920 746F 206F 7065 6E20 524F 4D2E" /* ory to open ROM. */ +}; + +data 'DITL' (130) { + $"0005 0000 0000 0046 00F0 005A 012A 0402" /* .......F..Z.*.. */ + $"4F4B 0000 0000 000A 000A 002A 002A A002" /* OK.........*.*. */ + $"0001 0000 0000 000A 0032 0019 012C 8802" /* .........2...,. */ + $"5E30 0000 0000 0019 0032 0028 012C 8802" /* ^0.......2.(.,. */ + $"5E31 0000 0000 0028 0032 0037 012C 8802" /* ^1.....(.2.7.,. */ + $"5E32 0000 0000 0037 0032 0046 012C 8802" /* ^2.....7.2.F.,. */ + $"5E33" /* ^3 */ +}; + +data 'ICON' (128) { + $"0FFF FFF0 0FFF FFF0 0A00 0050 0A1F FF50" /* .....P..P */ + $"0AD0 0150 0AD2 0950 0A12 0950 0A10 0150" /* ..P.P..P...P */ + $"0A10 0150 0A12 0950 0A11 F150 0A10 0150" /* ...P..P..P...P */ + $"0A1F FF50 0A00 0050 0BFF FFD0 0800 0010" /* ..P...P..... */ + $"0870 0010 0870 0010 0870 0010 0BFE 01D0" /* .p...p...p.... */ + $"0BFE 01D0 0BFE 01D0 0870 1C10 0870 1C10" /* .....p...p.. */ + $"0870 1C10 0800 0010 0800 0010 0800 0010" /* .p.............. */ + $"080E 7020 081C E020 0800 00C0 0FFF FF00" /* ..p .. ..... */ +}; + +data 'ICN#' (128) { + $"0FFF FFF0 0FFF FFF0 0A00 0050 0A1F FF50" /* .....P..P */ + $"0AD0 0150 0AD2 0950 0A12 0950 0A10 0150" /* ..P.P..P...P */ + $"0A10 0150 0A12 0950 0A11 F150 0A10 0150" /* ...P..P..P...P */ + $"0A1F FF50 0A00 0050 0BFF FFD0 0800 0010" /* ..P...P..... */ + $"0870 0010 0870 0010 0870 0010 0BFE 01D0" /* .p...p...p.... */ + $"0BFE 01D0 0BFE 01D0 0870 1C10 0870 1C10" /* .....p...p.. */ + $"0870 1C10 0800 0010 0800 0010 0800 0010" /* .p.............. */ + $"080E 7020 081C E020 0800 00C0 0FFF FF00" /* ..p .. ..... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0" /* .... */ + $"0FFF FFE0 0FFF FFE0 0FFF FFC0 0FFF FF00" /* ..... */ +}; + +data 'BNDL' (128) { + $"4D47 4245 0000 0001 4652 4546 0000 0000" /* MGBE....FREF.... */ + $"0080 4943 4E23 0000 0000 0080" /* .ICN#..... */ +}; + +data 'FREF' (128) { + $"4150 504C 0000 00" /* APPL... */ +}; + +data 'MGBE' (0, "Owner resource") { + $"10A9 2032 3031 3320 4D61 7474 204C 6175" /* . 2013 Matt Lau */ + $"78" /* x */ +}; + +data 'ALRT' (128) { + $"004E 0048 008A 016A 0081 4444 300A" /* .N.H..j.DD0. */ +}; + +data 'ALRT' (129) { + $"0028 0028 0082 0154 0082 5555 300A" /* .(.(..T.UU0. */ +}; + diff --git a/src/old/emulator.c b/src/old/emulator.c new file mode 100644 index 0000000..3584dd3 --- /dev/null +++ b/src/old/emulator.c @@ -0,0 +1,205 @@ +/* Game Boy emulator for 68k Macs + Compiled with Symantec THINK C 5.0 + (c) 2013 Matt Laux + + emulator.c - entry point */ + +#include +#include +#include +#include + +#include "gb_types.h" +#include "z80.h" +#include "emulator.h" + +WindowPtr g_wp; +unsigned char g_running; + +static Point windowPt = { WINDOW_Y, WINDOW_X }; + +static Rect windowBounds = { WINDOW_Y, WINDOW_X, WINDOW_Y + WINDOW_HEIGHT, WINDOW_X + WINDOW_WIDTH }; + +emu_state theState; + +void InitEverything(void) +{ + Handle mbar; + + InitGraf(&qd.thePort); + InitFonts(); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(0L); + InitCursor(); + + mbar = GetNewMBar(MBAR_DEFAULT); + SetMenuBar(mbar); + DrawMenuBar(); + + g_running = 1; +} + +void Render(void) +{ + MoveTo(10, 10); + DrawString("\pTest 123"); +} + +void StartEmulation(void) +{ + g_wp = NewWindow(0, &windowBounds, WINDOW_TITLE, true, + noGrowDocProc, (WindowPtr) -1, true, 0); + SetPort(g_wp); + + theState.cpu = z80_create(); + theState.cpu->regs->pc = 0x100; + z80_run(theState.cpu); +} + +bool LoadRom(FSSpec *fp) +{ + int err; + short fileNo; + long amtRead; + + if(theState.rom != NULL) { + // unload existing ROM + DisposPtr((char *) theState.rom); + theState.romLength = 0; + } + + err = FSpOpenDF(fp, fsRdWrPerm, &fileNo); + + if(err != noErr) { + return false; + } + + GetEOF(fileNo, (long *) &theState.romLength); + theState.rom = (unsigned char *) NewPtr(theState.romLength); + if(theState.rom == NULL) { + Alert(ALRT_NOT_ENOUGH_RAM, NULL); + return false; + } + + amtRead = theState.romLength; + + FSRead(fileNo, &amtRead, theState.rom); + return true; +} + +// -- DIALOG BOX FUNCTIONS -- + +bool ShowOpenBox(void) +{ + StandardFileReply reply; + Point pt = { 0, 0 }; + + StandardGetFile(NULL, -1, NULL, &reply); + + if(reply.sfGood) { + return LoadRom(&reply.sfFile); + } + + return false; +} + +void ShowAboutBox(void) +{ + DialogPtr dp; + EventRecord e; + + dp = GetNewDialog(DLOG_ABOUT, 0L, (WindowPtr) -1L); + + DrawDialog(dp); + + while(!GetNextEvent(mDownMask, &e)); + while(WaitMouseUp()); + + DisposDialog(dp); +} + +// -- EVENT FUNCTIONS -- + +void OnMenuAction(long action) +{ + short menu, item; + + if(action <= 0) + return; + + HiliteMenu(0); + + menu = HiWord(action); + item = LoWord(action); + + if(menu == MENU_APPLE) { + if(item == APPLE_ABOUT) { + ShowAboutBox(); + } + } + + else if(menu == MENU_FILE) { + if(item == FILE_OPEN) { + if(ShowOpenBox()) + StartEmulation(); + } + else if(item == FILE_QUIT) { + g_running = 0; + } + } +} + +void OnMouseDown(EventRecord *pEvt) +{ + short part; + WindowPtr clicked; + long action; + + part = FindWindow(pEvt->where, &clicked); + + switch(part) { + case inDrag: + DragWindow(clicked, pEvt->where, &qd.screenBits.bounds); + break; + case inGoAway: + if(TrackGoAway(clicked, pEvt->where)) + DisposeWindow(clicked); + break; + case inContent: + if(clicked != FrontWindow()) + SelectWindow(clicked); + break; + case inMenuBar: + action = MenuSelect(pEvt->where); + OnMenuAction(action); + break; + } +} + +// -- ENTRY POINT -- + +int main(int argc, char *argv[]) +{ + EventRecord evt; + + InitEverything(); + + while(g_running) { + if(WaitNextEvent(everyEvent, &evt, 10, 0) != nullEvent) { + switch(evt.what) { + case mouseDown: + OnMouseDown(&evt); + break; + case updateEvt: + BeginUpdate((WindowPtr) evt.message); + Render(); + EndUpdate((WindowPtr) evt.message); + break; + } + } + } + + return 0; +} \ No newline at end of file diff --git a/src/old/emulator.h b/src/old/emulator.h new file mode 100644 index 0000000..6daec26 --- /dev/null +++ b/src/old/emulator.h @@ -0,0 +1,50 @@ +/* Game Boy emulator for 68k Macs + Compiled with Symantec THINK C 5.0 + (c) 2013 Matt Laux + + emulator.h - declarations for emulator.c */ + +#ifndef EMULATOR_H +#define EMULATOR_H + +#define WINDOW_TITLE "\pEmulator" + +#define WINDOW_X 100 +#define WINDOW_Y 100 +#define WINDOW_WIDTH 256 +#define WINDOW_HEIGHT 256 + +#define ALRT_NOT_ENOUGH_RAM 128 +#define ALRT_4_LINE 129 + +#define DLOG_ABOUT 128 + +#define MBAR_DEFAULT 128 + +#define MENU_APPLE 128 +#define MENU_FILE 129 +#define MENU_EMULATION 130 + +#define APPLE_ABOUT 1 + +#define FILE_OPEN 1 +#define FILE_SCREENSHOT 2 +#define FILE_QUIT 4 + +#define EMULATION_PAUSE 1 +#define EMULATION_PREFERENCES 3 +#define EMULATION_KEY_MAPPINGS 4 + +typedef unsigned char bool; +#define true 1 +#define false 0 + +typedef struct _emu_state { + z80_state *cpu; + u8 *rom; + unsigned long int romLength; +} emu_state; + +extern emu_state theState; + +#endif \ No newline at end of file diff --git a/src/old/gb_types.h b/src/old/gb_types.h new file mode 100644 index 0000000..072a198 --- /dev/null +++ b/src/old/gb_types.h @@ -0,0 +1,7 @@ +#ifndef GB_TYPES_H +#define GB_TYPES_H + +typedef unsigned char u8; +typedef unsigned short u16; + +#endif \ No newline at end of file diff --git a/src/old/mem_model.c b/src/old/mem_model.c new file mode 100644 index 0000000..86ba0eb --- /dev/null +++ b/src/old/mem_model.c @@ -0,0 +1,27 @@ +#include "gb_types.h" +#include "z80.h" +#include "emulator.h" +#include "mem_model.h" + +u8 mem_read(u16 addr) +{ + if(addr >= 0x0000 && addr <= 0x7fff) + return theState.rom[addr]; + //else if(addr >= +} + +u16 mem_read_word(u16 addr) +{ + if(addr >= 0x0000 && addr <= 0x7fff) + return theState.rom[addr] | theState.rom[addr + 1] << 8; +} + +void mem_write(u16 addr, u8 value) +{ + +} + +void mem_write_word(u16 addr, u16 value) +{ + +} \ No newline at end of file diff --git a/src/old/mem_model.h b/src/old/mem_model.h new file mode 100644 index 0000000..a2547ff --- /dev/null +++ b/src/old/mem_model.h @@ -0,0 +1,9 @@ +#ifndef MEM_MODEL_H +#define MEM_MODEL_H + +u8 mem_read(u16 addr); +u16 mem_read_word(u16 addr); +void mem_write(u16 addr, u8 value); +void mem_write_word(u16 addr, u16 value); + +#endif \ No newline at end of file diff --git a/src/old/z80.c b/src/old/z80.c new file mode 100644 index 0000000..e9a83fe --- /dev/null +++ b/src/old/z80.c @@ -0,0 +1,303 @@ +/* Game Boy emulator for 68k Macs + Compiled with Symantec THINK C 5.0 + (c) 2013 Matt Laux + + z80.c - Game Boy CPU emulation */ + +#include + +#include "gb_types.h" +#include "mem_model.h" +#include "z80.h" + +static u8 insn_cycles[] = { 0 }; + +static void set(z80_regs *regs, int flag) { regs->af.ind.f |= flag; } +static void clear(z80_regs *regs, int flag) { regs->af.ind.f &= ~flag; } + +static void inc_with_carry(z80_regs *regs, u8 *reg) +{ + clear(regs, FLAG_SUBTRACT); + if(*reg == 0xff || *reg == 0x0f) + set(regs, FLAG_HALF_CARRY); + (*reg)++; + if(*reg == 0) + set(regs, FLAG_ZERO); +} + +static void dec_with_carry(z80_regs *regs, u8 *reg) +{ + set(regs, FLAG_SUBTRACT); + if(*reg == 0x00 || *reg == 0x10) + set(regs, FLAG_HALF_CARRY); + (*reg)--; + if(*reg == 0) + set(regs, FLAG_ZERO); +} + +static void rotate_left(z80_regs *regs, u8 *reg) +{ + // copy old leftmost bit to carry flag + regs->af.ind.f = (*reg & 0x80) >> 3 | (regs->af.ind.f & ~FLAG_CARRY); + // rotate + *reg <<= 1; + // restore leftmost (now rightmost) bit + *reg |= (regs->af.ind.f & FLAG_CARRY) >> 4; +} + +static void rotate_right(z80_regs *regs, u8 *reg) +{ + // copy old rightmost bit to carry flag + regs->af.ind.f = (*reg & 0x01) << 4 | (regs->af.ind.f & ~FLAG_CARRY); + // rotate + *reg >>= 1; + // restore rightmost bit to left + *reg |= (regs->af.ind.f & FLAG_CARRY) << 3; +} + +static void xor(z80_regs *regs, u8 value) +{ + regs->af.ind.a ^= value; + if(regs->af.ind.a == 0) + set(regs, FLAG_ZERO); + clear(regs, FLAG_SUBTRACT); + clear(regs, FLAG_HALF_CARRY); + clear(regs, FLAG_CARRY); +} + +z80_state *z80_create(void) +{ + z80_state *state; + + state = (z80_state *) NewPtr(sizeof(z80_state)); + + state->regs = (z80_regs *) NewPtr(sizeof(z80_regs)); + state->ram = (u8 *) NewPtr(GB_RAM_SIZE); + state->regs->pc = 0; + + return state; +} + +void z80_destroy(z80_state *state) +{ + DisposPtr((char *) state->regs); + DisposPtr((char *) state->ram); + DisposPtr((char *) state); +} + +void z80_dump_regs(z80_state *state) +{ + char line1[256], line2[256], line3[256], line4[256]; + sprintf(line1, " PC: %04x, Opcode: %02x", state->current_pc, state->current_op); + sprintf(line2, " A: %02x, F: %02x, B: %02x, C: %02x", state->regs->af.ind.a, + state->regs->af.ind.f, state->regs->bc.ind.b, state->regs->bc.ind.c); + sprintf(line3, " D: %02x, E: %02x, H: %02x, L: %02x", state->regs->de.ind.d, + state->regs->de.ind.e, state->regs->hl.ind.h, state->regs->hl.ind.l); + sprintf(line4, " SP: %04x, PC: %04x", state->regs->sp, state->regs->pc); + + line1[0] = strlen(line1); + line2[0] = strlen(line2); + line3[0] = strlen(line3); + line4[0] = strlen(line4); + + ParamText((void *) line1, (void *) line2, (void *) line3, (void *) line4); + Alert(129, NULL); +} + +#define load(dst, src) ((dst) = (src)) + +void z80_run(z80_state *state) +{ + z80_regs *regs = state->regs; + u16 old; + + for(;;) { + u8 op = mem_read(regs->pc); + + state->current_op = op; + state->current_pc = regs->pc; + + z80_dump_regs(state); + regs->pc++; + + switch(op) { + // 8-bit immediate loads + + case 0x06: load(regs->bc.ind.b, mem_read(regs->pc)); regs->pc++; break; + case 0x0e: load(regs->bc.ind.c, mem_read(regs->pc)); regs->pc++; break; + case 0x16: load(regs->de.ind.d, mem_read(regs->pc)); regs->pc++; break; + case 0x1e: load(regs->de.ind.e, mem_read(regs->pc)); regs->pc++; break; + case 0x26: load(regs->hl.ind.h, mem_read(regs->pc)); regs->pc++; break; + case 0x2e: load(regs->hl.ind.l, mem_read(regs->pc)); regs->pc++; break; + case 0x36: mem_write(regs->hl.val, mem_read(regs->pc)); regs->pc++; break; + case 0x3e: load(regs->af.ind.a, mem_read(regs->pc)); regs->pc++; break; + + // 8-bit register -> *register copies + + // src = A + case 0x02: mem_write(regs->bc.val, regs->af.ind.a); break; // *BC = A + case 0x12: mem_write(regs->de.val, regs->af.ind.a); break; // *DE = A + case 0x22: mem_write(regs->hl.val, regs->af.ind.a); regs->hl.val++; break; + case 0x32: mem_write(regs->hl.val, regs->af.ind.a); regs->hl.val--; break; + + // dest = A + case 0x0a: load(regs->af.ind.a, mem_read(regs->bc.val)); break; // A = *BC + case 0x1a: load(regs->af.ind.a, mem_read(regs->de.val)); break; // A = *DE + case 0x2a: load(regs->af.ind.a, mem_read(regs->hl.val)); regs->hl.val++; break; + case 0x3a: load(regs->af.ind.a, mem_read(regs->hl.val)); regs->hl.val--; break; + + // dest = *HL + case 0x70: mem_write(regs->hl.val, regs->bc.ind.b); break; + case 0x71: mem_write(regs->hl.val, regs->bc.ind.c); break; + case 0x72: mem_write(regs->hl.val, regs->de.ind.d); break; + case 0x73: mem_write(regs->hl.val, regs->de.ind.e); break; + case 0x74: mem_write(regs->hl.val, regs->hl.ind.h); break; + case 0x75: mem_write(regs->hl.val, regs->hl.ind.l); break; + // 0x76 is HALT + case 0x77: mem_write(regs->hl.val, regs->af.ind.a); break; + + // 8-bit register -> register copies + + // dest = A + case 0x78: load(regs->af.ind.a, regs->bc.ind.b); break; + case 0x79: load(regs->af.ind.a, regs->bc.ind.c); break; + case 0x7a: load(regs->af.ind.a, regs->de.ind.d); break; + case 0x7b: load(regs->af.ind.a, regs->de.ind.e); break; + case 0x7c: load(regs->af.ind.a, regs->hl.ind.h); break; + case 0x7d: load(regs->af.ind.a, regs->hl.ind.l); break; + case 0x7e: load(regs->af.ind.a, mem_read(regs->hl.val)); break; + case 0x7f: break; // copy A to A + + // dest = B + case 0x40: break; // copy B to B + case 0x41: load(regs->bc.ind.b, regs->bc.ind.c); break; + case 0x42: load(regs->bc.ind.b, regs->de.ind.d); break; + case 0x43: load(regs->bc.ind.b, regs->de.ind.e); break; + case 0x44: load(regs->bc.ind.b, regs->hl.ind.h); break; + case 0x45: load(regs->bc.ind.b, regs->hl.ind.l); break; + case 0x46: load(regs->bc.ind.b, mem_read(regs->hl.val)); break; + case 0x47: load(regs->bc.ind.b, regs->af.ind.a); break; + + // dest = C + case 0x48: load(regs->bc.ind.c, regs->bc.ind.b); break; + case 0x49: break; // copy C to C + case 0x4a: load(regs->bc.ind.c, regs->de.ind.d); break; + case 0x4b: load(regs->bc.ind.c, regs->de.ind.e); break; + case 0x4c: load(regs->bc.ind.c, regs->hl.ind.h); break; + case 0x4d: load(regs->bc.ind.c, regs->hl.ind.l); break; + case 0x4e: load(regs->bc.ind.c, mem_read(regs->hl.val)); break; + case 0x4f: load(regs->bc.ind.c, regs->af.ind.a); break; + + // dest = D + case 0x50: load(regs->de.ind.d, regs->bc.ind.b); break; + case 0x51: load(regs->de.ind.d, regs->bc.ind.c); break; + case 0x52: break; // copy D to D + case 0x53: load(regs->de.ind.d, regs->de.ind.e); break; + case 0x54: load(regs->de.ind.d, regs->hl.ind.h); break; + case 0x55: load(regs->de.ind.d, regs->hl.ind.l); break; + case 0x56: load(regs->de.ind.d, mem_read(regs->hl.val)); break; + case 0x57: load(regs->de.ind.d, regs->af.ind.a); break; + + // dest = E + case 0x58: load(regs->de.ind.e, regs->bc.ind.b); break; + case 0x59: load(regs->de.ind.e, regs->bc.ind.c); break; + case 0x5a: load(regs->de.ind.e, regs->de.ind.d); break; + case 0x5b: break; // copy E to E + case 0x5c: load(regs->de.ind.e, regs->hl.ind.h); break; + case 0x5d: load(regs->de.ind.e, regs->hl.ind.l); break; + case 0x5e: load(regs->de.ind.e, mem_read(regs->hl.val)); break; + case 0x5f: load(regs->de.ind.e, regs->af.ind.a); break; + + // dest = H + case 0x60: load(regs->hl.ind.h, regs->bc.ind.b); break; + case 0x61: load(regs->hl.ind.h, regs->bc.ind.c); break; + case 0x62: load(regs->hl.ind.h, regs->de.ind.d); break; + case 0x63: load(regs->hl.ind.h, regs->de.ind.e); break; + case 0x64: break; // copy H to H + case 0x65: load(regs->hl.ind.h, regs->hl.ind.l); break; + case 0x66: load(regs->hl.ind.h, mem_read(regs->hl.val)); break; + case 0x67: load(regs->hl.ind.h, regs->af.ind.a); break; + + // dest = L + case 0x68: load(regs->hl.ind.l, regs->bc.ind.b); break; + case 0x69: load(regs->hl.ind.l, regs->bc.ind.c); break; + case 0x6a: load(regs->hl.ind.l, regs->de.ind.d); break; + case 0x6b: load(regs->hl.ind.l, regs->de.ind.e); break; + case 0x6c: load(regs->hl.ind.l, regs->hl.ind.h); break; + case 0x6d: break; // copy L to L + case 0x6e: load(regs->hl.ind.l, mem_read(regs->hl.val)); break; + case 0x6f: load(regs->hl.ind.l, regs->af.ind.a); break; + + case 0x00: break; // NOP + case 0x01: // LD BC, 0xNNNN + regs->bc.val = mem_read_word(regs->pc); + regs->pc += 2; + break; + case 0x03: // INC BC + regs->bc.val++; + break; + case 0x04: // INC B + inc_with_carry(regs, ®s->bc.ind.b); + break; + case 0x05: // DEC B + dec_with_carry(regs, ®s->bc.ind.b); + break; + case 0x07: // RLCA + rotate_left(regs, ®s->af.ind.a); + break; + case 0x08: // LD (0xNNNN), SP + mem_write_word(regs->pc, regs->sp); + regs->pc += 2; + break; + case 0x09: // ADD HL, BC + clear(regs, FLAG_SUBTRACT); + old = regs->hl.val; + regs->hl.val += regs->bc.val; + if(regs->hl.val < old) // overflow occured + set(regs, FLAG_CARRY); + if(regs->hl.val >= 0x1000) // half carry on high byte + set(regs, FLAG_HALF_CARRY); + break; + case 0x0b: // DEC BC + regs->bc.val--; + break; + case 0x0c: // INC C + inc_with_carry(regs, ®s->bc.ind.c); + break; + case 0x0d: // DEC C + dec_with_carry(regs, ®s->bc.ind.c); + break; + case 0x0f: // RRCA + rotate_right(regs, ®s->af.ind.a); + break; + case 0x10: // STOP + // 2 bytes long for some reason + regs->pc++; + return; + break; + case 0x11: // LD DE, 0xNNNN + regs->de.val = mem_read_word(regs->pc); + regs->pc += 2; + break; + + case 0xc3: + regs->pc = mem_read_word(regs->pc); + break; + + // XOR + case 0xaf: xor(regs, regs->af.ind.a); break; + case 0xa8: xor(regs, regs->bc.ind.b); break; + case 0xa9: xor(regs, regs->bc.ind.c); break; + case 0xaa: xor(regs, regs->de.ind.d); break; + case 0xab: xor(regs, regs->de.ind.e); break; + case 0xac: xor(regs, regs->hl.ind.h); break; + case 0xad: xor(regs, regs->hl.ind.l); break; + case 0xae: xor(regs, mem_read(regs->hl.val)); break; + case 0xee: xor(regs, mem_read(regs->pc)); regs->pc++; break; + + default: + break; + + } + } +} \ No newline at end of file diff --git a/src/old/z80.h b/src/old/z80.h new file mode 100644 index 0000000..89def42 --- /dev/null +++ b/src/old/z80.h @@ -0,0 +1,66 @@ +/* Game Boy emulator for 68k Macs + Compiled with Symantec THINK C 5.0 + (c) 2013 Matt Laux + + z80.h - definitions and prototypes for z80.c */ + +#ifndef Z80_H +#define Z80_H + +#define GB_RAM_SIZE 0x2000 + +#define FLAG_ZERO 0x80 +#define FLAG_SUBTRACT 0x40 +#define FLAG_HALF_CARRY 0x20 +#define FLAG_CARRY 0x10 + +typedef struct _z80_regs { + union { + struct { + u8 f; + u8 a; + } ind; + u16 val; + } af; + + union { + struct { + u8 c; + u8 b; + } ind; + u16 val; + } bc; + + union { + struct { + u8 e; + u8 d; + } ind; + u16 val; + } de; + + union { + struct { + u8 l; + u8 h; + } ind; + u16 val; + } hl; + + u16 sp; + u16 pc; +} z80_regs; + +typedef struct _z80_state { + z80_regs *regs; + u8 current_op; + u16 current_pc; + u8 *ram; +} z80_state; + +z80_state *z80_create(void); +void z80_destroy(z80_state *state); +void z80_dump_regs(z80_state *state); +void z80_run(z80_state *state); + +#endif \ No newline at end of file