mirror of
https://github.com/mlaux/gb6.git
synced 2024-06-13 15:29:27 +00:00
unify old and new source
This commit is contained in:
parent
f064ee3934
commit
1a6a95cc87
|
@ -1,6 +1,10 @@
|
|||
add_application(Emulator
|
||||
src/old/emulator.c
|
||||
src/old/mem_model.c
|
||||
src/old/z80.c
|
||||
src/bootstrap.c
|
||||
src/cpu.c
|
||||
src/dmg.c
|
||||
src/emulator.c
|
||||
src/instructions.c
|
||||
src/lcd.c
|
||||
src/rom.c
|
||||
resources.r
|
||||
)
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include <Devices.h>
|
||||
#include <Memory.h>
|
||||
|
||||
#include "gb_types.h"
|
||||
#include "z80.h"
|
||||
#include "emulator.h"
|
||||
|
||||
WindowPtr g_wp;
|
||||
|
@ -59,9 +57,7 @@ void StartEmulation(void)
|
|||
noGrowDocProc, (WindowPtr) -1, true, 0);
|
||||
SetPort(g_wp);
|
||||
|
||||
theState.cpu = z80_create();
|
||||
theState.cpu->regs->pc = 0x100;
|
||||
z80_run(theState.cpu);
|
||||
|
||||
}
|
||||
|
||||
bool LoadRom(StrFileName fileName, short vRefNum)
|
|
@ -7,6 +7,9 @@
|
|||
#ifndef EMULATOR_H
|
||||
#define EMULATOR_H
|
||||
|
||||
#include "types.h"
|
||||
#include "dmg.h"
|
||||
|
||||
#define WINDOW_TITLE "\pEmulator"
|
||||
|
||||
#define WINDOW_X 100
|
||||
|
@ -40,7 +43,7 @@ typedef unsigned char bool;
|
|||
#define false 0
|
||||
|
||||
typedef struct _emu_state {
|
||||
z80_state *cpu;
|
||||
struct dmg *cpu;
|
||||
u8 *rom;
|
||||
unsigned long int romLength;
|
||||
} emu_state;
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef GB_TYPES_H
|
||||
#define GB_TYPES_H
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
|
||||
#endif
|
|
@ -1,27 +0,0 @@
|
|||
#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)
|
||||
{
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#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
303
src/old/z80.c
|
@ -1,303 +0,0 @@
|
|||
/* 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 *) malloc(sizeof(z80_state));
|
||||
|
||||
state->regs = (z80_regs *) malloc(sizeof(z80_regs));
|
||||
state->ram = (u8 *) malloc(GB_RAM_SIZE);
|
||||
state->regs->pc = 0;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void z80_destroy(z80_state *state)
|
||||
{
|
||||
free((char *) state->regs);
|
||||
free((char *) state->ram);
|
||||
free((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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* 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