mirror of
https://github.com/mlaux/gb6.git
synced 2025-01-02 16:29:34 +00:00
start on mbc1
This commit is contained in:
parent
0f43ebf4cc
commit
03ef4d1116
@ -20,6 +20,7 @@ add_executable(gb6
|
||||
../src/instructions.c
|
||||
../src/lcd.c
|
||||
../src/rom.c
|
||||
../src/mbc.c
|
||||
emulator.c
|
||||
lcd_imgui.c
|
||||
imgui/imgui_demo.cpp
|
||||
|
35
src/cpu.c
35
src/cpu.c
@ -453,6 +453,34 @@ static void conditional_jump(struct cpu *cpu, u8 opc, u8 neg_op, int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
static void daa(struct cpu *cpu)
|
||||
{
|
||||
// https://forums.nesdev.org/viewtopic.php?t=15944
|
||||
if (!flag_isset(cpu, FLAG_SIGN)) {
|
||||
if (flag_isset(cpu, FLAG_CARRY) || cpu->a > 0x99) {
|
||||
cpu->a += 0x60;
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
if (flag_isset(cpu, FLAG_HALF_CARRY) || (cpu->a & 0x0f) > 0x09) {
|
||||
cpu->a += 0x6;
|
||||
}
|
||||
} else {
|
||||
if (flag_isset(cpu, FLAG_CARRY)) {
|
||||
cpu->a -= 0x60;
|
||||
}
|
||||
if (flag_isset(cpu, FLAG_HALF_CARRY)) {
|
||||
cpu->a -= 0x6;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->a) {
|
||||
set_flag(cpu, FLAG_ZERO);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
}
|
||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
}
|
||||
|
||||
static u16 handlers[] = { 0x40, 0x48, 0x50, 0x58, 0x60 };
|
||||
|
||||
static u16 check_interrupts(struct cpu *cpu)
|
||||
@ -480,6 +508,9 @@ static u16 check_interrupts(struct cpu *cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
void cpu_step(struct cpu *cpu)
|
||||
{
|
||||
u8 temp;
|
||||
@ -512,6 +543,9 @@ void cpu_step(struct cpu *cpu)
|
||||
case 0x0f: // RRCA
|
||||
cpu->a = rrc(cpu, cpu->a);
|
||||
break;
|
||||
case 0x10: // STOP
|
||||
cpu->pc++;
|
||||
break;
|
||||
case 0x11: // LD DE,d16
|
||||
write_de(cpu, read16(cpu, cpu->pc));
|
||||
cpu->pc += 2;
|
||||
@ -892,6 +926,7 @@ void cpu_step(struct cpu *cpu)
|
||||
case 0xff: push(cpu, cpu->pc); cpu->pc = 0x38; break;
|
||||
|
||||
case 0x27: // DAA
|
||||
daa(cpu);
|
||||
break;
|
||||
|
||||
case 0x76: // HALT
|
||||
|
12
src/dmg.c
12
src/dmg.c
@ -5,6 +5,7 @@
|
||||
#include "rom.h"
|
||||
#include "lcd.h"
|
||||
#include "dmg.h"
|
||||
#include "mbc.h"
|
||||
#include "types.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
@ -54,6 +55,12 @@ static int counter;
|
||||
u8 dmg_read(void *_dmg, u16 address)
|
||||
{
|
||||
struct dmg *dmg = (struct dmg *) _dmg;
|
||||
u8 mbc_data;
|
||||
|
||||
if (mbc_read(dmg->rom->mbc, dmg, address, &mbc_data)) {
|
||||
return mbc_data;
|
||||
}
|
||||
|
||||
// if (address < 0x100) {
|
||||
// return dmg_boot_rom[address];
|
||||
// } else if (address < 0x4000) {
|
||||
@ -93,6 +100,11 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||
void dmg_write(void *_dmg, u16 address, u8 data)
|
||||
{
|
||||
struct dmg *dmg = (struct dmg *) _dmg;
|
||||
|
||||
if (mbc_write(dmg->rom->mbc, dmg, address, data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (address < 0x4000) {
|
||||
printf("warning: writing 0x%04x in rom\n", address);
|
||||
} else if (address < 0x8000) {
|
||||
|
@ -1,9 +1,7 @@
|
||||
#ifndef _DMG_H
|
||||
#define _DMG_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "rom.h"
|
||||
#include "lcd.h"
|
||||
#include "types.h"
|
||||
|
||||
#define FIELD_JOY 1
|
||||
#define FIELD_ACTION 2
|
||||
@ -17,6 +15,10 @@
|
||||
#define BUTTON_SELECT (1 << 2)
|
||||
#define BUTTON_START (1 << 3)
|
||||
|
||||
struct cpu;
|
||||
struct rom;
|
||||
struct lcd;
|
||||
|
||||
struct dmg {
|
||||
struct cpu *cpu;
|
||||
struct rom *rom;
|
||||
|
91
src/mbc.c
Normal file
91
src/mbc.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "mbc.h"
|
||||
#include "dmg.h"
|
||||
#include "rom.h"
|
||||
|
||||
static int mbc_noop_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbc_noop_write(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbc1_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data)
|
||||
{
|
||||
if (addr >= 0x4000 && addr <= 0x7fff) {
|
||||
int use_bank = mbc->rom_bank || 1;
|
||||
*out_data = dmg->rom->data[0x4000 * use_bank + (addr & 0x3fff)];
|
||||
return 1;
|
||||
} else if (addr >= 0xa000 && addr <= 0xbfff) {
|
||||
if (mbc->ram_enabled) {
|
||||
*out_data = mbc->ram[0x2000 * mbc->ram_bank + (addr & 0x1fff)];
|
||||
} else {
|
||||
*out_data = 0xff;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbc1_write(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 data)
|
||||
{
|
||||
if (addr >= 0 && addr <= 0x1fff) {
|
||||
mbc->ram_enabled = (data & 0xf) == 0xa;
|
||||
return 1;
|
||||
} else if (addr >= 0x2000 && addr <= 0x3fff) {
|
||||
mbc->rom_bank = data & 0x1f;
|
||||
return 1;
|
||||
} else if (addr >= 0x4000 && addr <= 0x5fff) {
|
||||
mbc->ram_bank = data & 0x03;
|
||||
return 1;
|
||||
} else if (addr >= 0x6000 && addr <= 0x7fff) {
|
||||
//printf("sel %d\n", data);
|
||||
return 1;
|
||||
} else if (addr >= 0xa000 && addr <= 0xbfff) {
|
||||
if (mbc->ram_enabled) {
|
||||
mbc->ram[0x2000 * mbc->ram_bank + (addr & 0x1fff)] = data;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mbc mbc_noop = {
|
||||
mbc_noop_read,
|
||||
mbc_noop_write,
|
||||
};
|
||||
|
||||
struct mbc mbc1 = {
|
||||
mbc1_read,
|
||||
mbc1_write,
|
||||
};
|
||||
|
||||
struct mbc *mbc_new(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case 0:
|
||||
return &mbc_noop;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return &mbc1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mbc_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data)
|
||||
{
|
||||
return mbc->read_fn(mbc, dmg, addr, out_data);
|
||||
}
|
||||
|
||||
int mbc_write(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 data)
|
||||
{
|
||||
return mbc->write_fn(mbc, dmg, addr, data);
|
||||
}
|
22
src/mbc.h
Normal file
22
src/mbc.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef _MBC_H
|
||||
#define _MBC_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct dmg;
|
||||
|
||||
struct mbc {
|
||||
int (*read_fn)(struct mbc *, struct dmg *, u16, u8 *);
|
||||
int (*write_fn)(struct mbc *, struct dmg *, u16, u8);
|
||||
int type;
|
||||
int rom_bank;
|
||||
int ram_bank;
|
||||
int ram_enabled;
|
||||
u8 ram[0x8000];
|
||||
};
|
||||
|
||||
struct mbc *mbc_new(int type);
|
||||
int mbc_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data);
|
||||
int mbc_write(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 data);
|
||||
|
||||
#endif
|
@ -17,12 +17,15 @@ int rom_load(struct rom *rom, const char *filename)
|
||||
len = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
rom->type = 0; // TODO read type from cart
|
||||
rom->data = malloc(len);
|
||||
rom->length = len;
|
||||
if (fread(rom->data, 1, len, fp) < len) {
|
||||
return 0;
|
||||
}
|
||||
rom->mbc = mbc_new(rom->data[0x147]);
|
||||
if (!rom->mbc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user