mirror of
https://github.com/mlaux/gb6.git
synced 2024-09-27 09:56:08 +00:00
add old GUI and resources
This commit is contained in:
parent
d0b89bf258
commit
9675e55db8
111
resources.r
Normal file
111
resources.r
Normal file
@ -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" /* .<2E>........ÿÿÿ÷.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" /* ...€.<2E>.‚ */
|
||||||
|
};
|
||||||
|
|
||||||
|
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" /* cÂVersion 1.0ÂCo */
|
||||||
|
$"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.<EFBFBD>DD0. */
|
||||||
|
};
|
||||||
|
|
||||||
|
data 'ALRT' (129) {
|
||||||
|
$"0028 0028 0082 0154 0082 5555 300A" /* .(.(.‚.T.‚UU0. */
|
||||||
|
};
|
||||||
|
|
205
src/old/emulator.c
Normal file
205
src/old/emulator.c
Normal file
@ -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 <stdio.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Quickdraw.h>
|
||||||
|
#include <StandardFile.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
50
src/old/emulator.h
Normal file
50
src/old/emulator.h
Normal file
@ -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
|
7
src/old/gb_types.h
Normal file
7
src/old/gb_types.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef GB_TYPES_H
|
||||||
|
#define GB_TYPES_H
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
|
||||||
|
#endif
|
27
src/old/mem_model.c
Normal file
27
src/old/mem_model.c
Normal file
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
9
src/old/mem_model.h
Normal file
9
src/old/mem_model.h
Normal file
@ -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
|
303
src/old/z80.c
Normal file
303
src/old/z80.c
Normal file
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
src/old/z80.h
Normal file
66
src/old/z80.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user