mirror of
https://github.com/mlaux/gb6.git
synced 2024-06-20 00:29:27 +00:00
Compare commits
3 Commits
8d87ee1f26
...
0351226479
Author | SHA1 | Date | |
---|---|---|---|
|
0351226479 | ||
|
950a759abb | ||
|
b23d52737e |
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Matthew Laux
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -54,8 +54,8 @@ GLuint make_output_texture() {
|
||||||
glGenTextures(1, &image_texture);
|
glGenTextures(1, &image_texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, image_texture);
|
glBindTexture(GL_TEXTURE_2D, image_texture);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
return image_texture;
|
return image_texture;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,8 @@ void convert_output(struct lcd *lcd) {
|
||||||
for (y = 0; y < 256; y++) {
|
for (y = 0; y < 256; y++) {
|
||||||
for (x = 0; x < 256; x++) {
|
for (x = 0; x < 256; x++) {
|
||||||
int val = lcd->buf[y * 256 + x];
|
int val = lcd->buf[y * 256 + x];
|
||||||
int fill = val ? 255 : 0;
|
int fill = 255 - val * 85;
|
||||||
|
//int fill = val ? 255 : 0;
|
||||||
output_image[out_index++] = fill;
|
output_image[out_index++] = fill;
|
||||||
output_image[out_index++] = fill;
|
output_image[out_index++] = fill;
|
||||||
output_image[out_index++] = fill;
|
output_image[out_index++] = fill;
|
||||||
|
|
17
src/cpu.c
17
src/cpu.c
|
@ -174,7 +174,16 @@ static u8 shift_right(struct cpu *cpu, u8 value)
|
||||||
|
|
||||||
static u8 swap(struct cpu *cpu, u8 value)
|
static u8 swap(struct cpu *cpu, u8 value)
|
||||||
{
|
{
|
||||||
return ((value & 0xf0) >> 4) | ((value & 0x0f) << 4);
|
u8 ret = ((value & 0xf0) >> 4) | ((value & 0x0f) << 4);
|
||||||
|
if(ret == 0) {
|
||||||
|
set_flag(cpu, FLAG_ZERO);
|
||||||
|
} else {
|
||||||
|
clear_flag(cpu, FLAG_ZERO);
|
||||||
|
}
|
||||||
|
clear_flag(cpu, FLAG_SIGN);
|
||||||
|
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||||
|
clear_flag(cpu, FLAG_CARRY);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xor(struct cpu *regs, u8 value)
|
static void xor(struct cpu *regs, u8 value)
|
||||||
|
@ -634,6 +643,8 @@ void cpu_step(struct cpu *cpu)
|
||||||
break;
|
break;
|
||||||
case 0x2f: // CPL
|
case 0x2f: // CPL
|
||||||
cpu->a = ~cpu->a;
|
cpu->a = ~cpu->a;
|
||||||
|
set_flag(cpu, FLAG_SIGN);
|
||||||
|
set_flag(cpu, FLAG_HALF_CARRY);
|
||||||
break;
|
break;
|
||||||
case 0x31: // LD SP,d16
|
case 0x31: // LD SP,d16
|
||||||
cpu->sp = read16(cpu, cpu->pc);
|
cpu->sp = read16(cpu, cpu->pc);
|
||||||
|
@ -756,6 +767,10 @@ void cpu_step(struct cpu *cpu)
|
||||||
case 0xb5: or(cpu, cpu->l); break;
|
case 0xb5: or(cpu, cpu->l); break;
|
||||||
case 0xb6: or(cpu, read8(cpu, read_hl(cpu))); break;
|
case 0xb6: or(cpu, read8(cpu, read_hl(cpu))); break;
|
||||||
case 0xb7: or(cpu, cpu->a); break;
|
case 0xb7: or(cpu, cpu->a); break;
|
||||||
|
case 0xf6:
|
||||||
|
or(cpu, read8(cpu, cpu->pc));
|
||||||
|
cpu->pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
// CP
|
// CP
|
||||||
case 0xb8: subtract(cpu, cpu->b, 0, 1); break;
|
case 0xb8: subtract(cpu, cpu->b, 0, 1); break;
|
||||||
|
|
40
src/dmg.c
40
src/dmg.c
|
@ -39,9 +39,18 @@ void dmg_set_button(struct dmg *dmg, int field, int button, int pressed)
|
||||||
|
|
||||||
static u8 get_button_state(struct dmg *dmg)
|
static u8 get_button_state(struct dmg *dmg)
|
||||||
{
|
{
|
||||||
return dmg->action_selected ? dmg->action_buttons : dmg->joypad;
|
u8 ret = 0;
|
||||||
|
if (dmg->action_selected) {
|
||||||
|
ret |= dmg->action_buttons;
|
||||||
|
}
|
||||||
|
if (dmg->joypad_selected) {
|
||||||
|
ret |= dmg->joypad;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int counter;
|
||||||
|
|
||||||
u8 dmg_read(void *_dmg, u16 address)
|
u8 dmg_read(void *_dmg, u16 address)
|
||||||
{
|
{
|
||||||
struct dmg *dmg = (struct dmg *) _dmg;
|
struct dmg *dmg = (struct dmg *) _dmg;
|
||||||
|
@ -66,6 +75,9 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||||
return dmg->zero_page[address - 0xff80];
|
return dmg->zero_page[address - 0xff80];
|
||||||
} else if (address == 0xff00) {
|
} else if (address == 0xff00) {
|
||||||
return get_button_state(dmg);
|
return get_button_state(dmg);
|
||||||
|
} else if (address == 0xff04) {
|
||||||
|
counter++;
|
||||||
|
return counter;
|
||||||
} else if (address == 0xff0f) {
|
} else if (address == 0xff0f) {
|
||||||
return dmg->interrupt_requested;
|
return dmg->interrupt_requested;
|
||||||
} else if (address == 0xffff) {
|
} else if (address == 0xffff) {
|
||||||
|
@ -93,12 +105,21 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
||||||
} else if (address < 0xc000) {
|
} else if (address < 0xc000) {
|
||||||
// TODO switchable ram bank
|
// TODO switchable ram bank
|
||||||
} else if (address < 0xe000) {
|
} else if (address < 0xe000) {
|
||||||
|
// printf("write ram %04x %02x\n", address, data);
|
||||||
dmg->main_ram[address - 0xc000] = data;
|
dmg->main_ram[address - 0xc000] = data;
|
||||||
|
} else if (address == 0xFF46) {
|
||||||
|
u16 src = data << 8;
|
||||||
|
int k = 0;
|
||||||
|
// printf("oam dma %04x\n", src);
|
||||||
|
for (u16 addr = src; addr < src + 0xa0; addr++) {
|
||||||
|
dmg->lcd->oam[k++] = dmg_read(dmg, addr);
|
||||||
|
}
|
||||||
} else if (lcd_is_valid_addr(address)) {
|
} else if (lcd_is_valid_addr(address)) {
|
||||||
lcd_write(dmg->lcd, address, data);
|
lcd_write(dmg->lcd, address, data);
|
||||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
dmg->zero_page[address - 0xff80] = data;
|
dmg->zero_page[address - 0xff80] = data;
|
||||||
} else if (address == 0xff00) {
|
} else if (address == 0xff00) {
|
||||||
|
dmg->joypad_selected = data & (1 << 4);
|
||||||
dmg->action_selected = data & (1 << 5);
|
dmg->action_selected = data & (1 << 5);
|
||||||
} else if (address == 0xff0f) {
|
} else if (address == 0xff0f) {
|
||||||
dmg->interrupt_requested = data;
|
dmg->interrupt_requested = data;
|
||||||
|
@ -126,9 +147,19 @@ void dmg_step(void *_dmg)
|
||||||
if (dmg->cpu->cycle_count - dmg->last_lcd_update >= 456) {
|
if (dmg->cpu->cycle_count - dmg->last_lcd_update >= 456) {
|
||||||
dmg->last_lcd_update = dmg->cpu->cycle_count;
|
dmg->last_lcd_update = dmg->cpu->cycle_count;
|
||||||
int next_scanline = lcd_step(dmg->lcd);
|
int next_scanline = lcd_step(dmg->lcd);
|
||||||
|
|
||||||
|
// update LYC
|
||||||
|
if (next_scanline == lcd_read(dmg->lcd, REG_LYC)) {
|
||||||
|
lcd_set_bit(dmg->lcd, REG_STAT, STAT_FLAG_MATCH);
|
||||||
|
dmg_request_interrupt(dmg, INT_LCDSTAT);
|
||||||
|
} else {
|
||||||
|
lcd_clear_bit(dmg->lcd, REG_STAT, STAT_FLAG_MATCH);
|
||||||
|
}
|
||||||
|
|
||||||
if (next_scanline == 144) {
|
if (next_scanline == 144) {
|
||||||
// vblank has started, draw all the stuff from ram into the lcd
|
// vblank has started, draw all the stuff from ram into the lcd
|
||||||
dmg_request_interrupt(dmg, INT_VBLANK);
|
dmg_request_interrupt(dmg, INT_VBLANK);
|
||||||
|
dmg_request_interrupt(dmg, INT_SERIAL);
|
||||||
|
|
||||||
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
||||||
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
|
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
|
||||||
|
@ -136,7 +167,7 @@ void dmg_step(void *_dmg)
|
||||||
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
|
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
|
||||||
int tilebase = use_unsigned ? 0x8000 : 0x9000;
|
int tilebase = use_unsigned ? 0x8000 : 0x9000;
|
||||||
|
|
||||||
printf("%04x %04x %04x\n", bg_base, window_base, tilebase);
|
//printf("%04x %04x %04x\n", bg_base, window_base, tilebase);
|
||||||
|
|
||||||
int k = 0, off = 0;
|
int k = 0, off = 0;
|
||||||
int tile_y = 0, tile_x = 0;
|
int tile_y = 0, tile_x = 0;
|
||||||
|
@ -155,9 +186,8 @@ void dmg_step(void *_dmg)
|
||||||
int data1 = dmg_read(dmg, eff_addr + b);
|
int data1 = dmg_read(dmg, eff_addr + b);
|
||||||
int data2 = dmg_read(dmg, eff_addr + b + 1);
|
int data2 = dmg_read(dmg, eff_addr + b + 1);
|
||||||
for (i = 7; i >= 0; i--) {
|
for (i = 7; i >= 0; i--) {
|
||||||
// monochrome for now
|
dmg->lcd->buf[off] = ((data1 & (1 << i)) ? 1 : 0);// << 1;
|
||||||
dmg->lcd->buf[off] = (data1 & (1 << i)) ? 1 : 0;
|
//dmg->lcd->buf[off] |= (data1 & (1 << i)) ? 1 : 0;
|
||||||
//dmg->lcd->buf[off] |= (data2 & (1 << i)) ? 1 : 0;
|
|
||||||
off++;
|
off++;
|
||||||
}
|
}
|
||||||
off += 248;
|
off += 248;
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct dmg {
|
||||||
u8 video_ram[0x2000];
|
u8 video_ram[0x2000];
|
||||||
u8 zero_page[0x80];
|
u8 zero_page[0x80];
|
||||||
u32 last_lcd_update;
|
u32 last_lcd_update;
|
||||||
|
int joypad_selected;
|
||||||
int action_selected; // non-0 if A/B/start/select selected, 0 for directions
|
int action_selected; // non-0 if A/B/start/select selected, 0 for directions
|
||||||
u8 interrupt_enabled;
|
u8 interrupt_enabled;
|
||||||
u8 interrupt_requested;
|
u8 interrupt_requested;
|
||||||
|
|
15
src/lcd.c
15
src/lcd.c
|
@ -5,12 +5,12 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
||||||
static void set_bit(struct lcd *lcd, u16 addr, u8 bit)
|
void lcd_set_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||||
{
|
{
|
||||||
lcd_write(lcd, addr, lcd_read(lcd, addr) | (1 << bit));
|
lcd_write(lcd, addr, lcd_read(lcd, addr) | (1 << bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_bit(struct lcd *lcd, u16 addr, u8 bit)
|
void lcd_clear_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||||
{
|
{
|
||||||
lcd_write(lcd, addr, lcd_read(lcd, addr) & ~(1 << bit));
|
lcd_write(lcd, addr, lcd_read(lcd, addr) & ~(1 << bit));
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ static void clear_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||||
void lcd_new(struct lcd *lcd)
|
void lcd_new(struct lcd *lcd)
|
||||||
{
|
{
|
||||||
lcd->buf = malloc(256 * 256);
|
lcd->buf = malloc(256 * 256);
|
||||||
|
memset(lcd->buf, 0, 256 * 256);
|
||||||
// todo < 8 bpp
|
// todo < 8 bpp
|
||||||
lcd->pixels = malloc(LCD_WIDTH * LCD_HEIGHT);
|
lcd->pixels = malloc(LCD_WIDTH * LCD_HEIGHT);
|
||||||
}
|
}
|
||||||
|
@ -41,9 +42,6 @@ void lcd_write(struct lcd *lcd, u16 addr, u8 value)
|
||||||
lcd->oam[addr - 0xfe00] = value;
|
lcd->oam[addr - 0xfe00] = value;
|
||||||
} else {
|
} else {
|
||||||
lcd->regs[addr - REG_LCD_BASE] = value;
|
lcd->regs[addr - REG_LCD_BASE] = value;
|
||||||
if (addr == 0xFF46) {
|
|
||||||
// OAM DMA
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +62,6 @@ void lcd_copy(struct lcd *lcd)
|
||||||
|
|
||||||
int lcd_step(struct lcd *lcd)
|
int lcd_step(struct lcd *lcd)
|
||||||
{
|
{
|
||||||
// update LYC
|
|
||||||
if (lcd_read(lcd, REG_LY) == lcd_read(lcd, REG_LYC)) {
|
|
||||||
set_bit(lcd, REG_STAT, STAT_FLAG_MATCH);
|
|
||||||
} else {
|
|
||||||
clear_bit(lcd, REG_STAT, STAT_FLAG_MATCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
// step to next scanline 0-153
|
// step to next scanline 0-153
|
||||||
u8 next_scanline = (lcd_read(lcd, REG_LY) + 1) % 154;
|
u8 next_scanline = (lcd_read(lcd, REG_LY) + 1) % 154;
|
||||||
lcd_write(lcd, REG_LY, next_scanline);
|
lcd_write(lcd, REG_LY, next_scanline);
|
||||||
|
|
|
@ -48,6 +48,9 @@ void lcd_write(struct lcd *lcd, u16 addr, u8 value);
|
||||||
|
|
||||||
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value);
|
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value);
|
||||||
|
|
||||||
|
void lcd_set_bit(struct lcd *lcd, u16 addr, u8 bit);
|
||||||
|
void lcd_clear_bit(struct lcd *lcd, u16 addr, u8 bit);
|
||||||
|
|
||||||
// i feel like i'm going to need to call this every cycle and update regs
|
// i feel like i'm going to need to call this every cycle and update regs
|
||||||
int lcd_step(struct lcd *lcd);
|
int lcd_step(struct lcd *lcd);
|
||||||
void lcd_copy(struct lcd *lcd);
|
void lcd_copy(struct lcd *lcd);
|
||||||
|
|
|
@ -19,6 +19,7 @@ int rom_load(struct rom *rom, const char *filename)
|
||||||
|
|
||||||
rom->type = 0; // TODO read type from cart
|
rom->type = 0; // TODO read type from cart
|
||||||
rom->data = malloc(len);
|
rom->data = malloc(len);
|
||||||
|
rom->length = len;
|
||||||
if (fread(rom->data, 1, len, fp) < len) {
|
if (fread(rom->data, 1, len, fp) < len) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
struct rom {
|
struct rom {
|
||||||
|
u32 length;
|
||||||
int type;
|
int type;
|
||||||
u8 *data;
|
u8 *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int rom_load(struct rom *rom, const char *filename);
|
int rom_load(struct rom *rom, const char *filename);
|
||||||
|
|
||||||
void rom_free(struct rom *rom);
|
void rom_free(struct rom *rom);
|
||||||
|
|
|
@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.9)
|
||||||
|
|
||||||
include_directories(../src)
|
include_directories(../src)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "-O3")
|
||||||
|
|
||||||
add_application(Emulator
|
add_application(Emulator
|
||||||
../src/bootstrap.c
|
../src/bootstrap.c
|
||||||
../src/cpu.c
|
../src/cpu.c
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
/* Game Boy emulator for 68k Macs
|
/* Game Boy emulator for 68k Macs
|
||||||
Compiled with Symantec THINK C 5.0
|
|
||||||
(c) 2013 Matt Laux
|
|
||||||
|
|
||||||
emulator.c - entry point */
|
emulator.c - entry point */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -17,14 +14,24 @@
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
|
|
||||||
|
#include "dmg.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
|
||||||
WindowPtr g_wp;
|
WindowPtr g_wp;
|
||||||
|
DialogPtr stateDialog;
|
||||||
unsigned char g_running;
|
unsigned char g_running;
|
||||||
|
unsigned char emulationOn;
|
||||||
|
|
||||||
static Point windowPt = { WINDOW_Y, WINDOW_X };
|
static Point windowPt = { WINDOW_Y, WINDOW_X };
|
||||||
|
|
||||||
static Rect windowBounds = { WINDOW_Y, WINDOW_X, WINDOW_Y + WINDOW_HEIGHT, WINDOW_X + WINDOW_WIDTH };
|
static Rect windowBounds = { WINDOW_Y, WINDOW_X, WINDOW_Y + WINDOW_HEIGHT, WINDOW_X + WINDOW_WIDTH };
|
||||||
|
|
||||||
emu_state theState;
|
struct cpu cpu;
|
||||||
|
struct rom rom;
|
||||||
|
struct lcd lcd;
|
||||||
|
struct dmg dmg;
|
||||||
|
|
||||||
void InitEverything(void)
|
void InitEverything(void)
|
||||||
{
|
{
|
||||||
|
@ -45,10 +52,35 @@ void InitEverything(void)
|
||||||
g_running = 1;
|
g_running = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char offscreen[32 * 256];
|
||||||
|
Rect offscreenRect = { 0, 0, 256, 256 };
|
||||||
|
|
||||||
|
BitMap offscreenBmp;
|
||||||
|
|
||||||
|
int lastTicks;
|
||||||
|
|
||||||
void Render(void)
|
void Render(void)
|
||||||
{
|
{
|
||||||
MoveTo(10, 10);
|
long k = 0, dst;
|
||||||
DrawString("\pTest 123");
|
for (dst = 0; dst < 32 * 256; dst++) {
|
||||||
|
offscreen[dst] = lcd.buf[k++] << 7
|
||||||
|
| lcd.buf[k++] << 6
|
||||||
|
| lcd.buf[k++] << 5
|
||||||
|
| lcd.buf[k++] << 4
|
||||||
|
| lcd.buf[k++] << 3
|
||||||
|
| lcd.buf[k++] << 2
|
||||||
|
| lcd.buf[k++] << 1
|
||||||
|
| lcd.buf[k++];
|
||||||
|
}
|
||||||
|
SetPort(g_wp);
|
||||||
|
CopyBits(&offscreenBmp, &g_wp->portBits, &offscreenRect, &g_wp->portRect, srcCopy, NULL);
|
||||||
|
|
||||||
|
//EraseRect(&g_wp->portRect);
|
||||||
|
MoveTo(10, 160);
|
||||||
|
char debug[128];
|
||||||
|
sprintf(debug, "PC: %04x", cpu.pc);
|
||||||
|
C2PStr(debug);
|
||||||
|
DrawString(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartEmulation(void)
|
void StartEmulation(void)
|
||||||
|
@ -57,7 +89,10 @@ void StartEmulation(void)
|
||||||
noGrowDocProc, (WindowPtr) -1, true, 0);
|
noGrowDocProc, (WindowPtr) -1, true, 0);
|
||||||
SetPort(g_wp);
|
SetPort(g_wp);
|
||||||
|
|
||||||
|
offscreenBmp.baseAddr = offscreen;
|
||||||
|
offscreenBmp.bounds = offscreenRect;
|
||||||
|
offscreenBmp.rowBytes = 32;
|
||||||
|
emulationOn = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadRom(StrFileName fileName, short vRefNum)
|
bool LoadRom(StrFileName fileName, short vRefNum)
|
||||||
|
@ -66,29 +101,28 @@ bool LoadRom(StrFileName fileName, short vRefNum)
|
||||||
short fileNo;
|
short fileNo;
|
||||||
long amtRead;
|
long amtRead;
|
||||||
|
|
||||||
if(theState.rom != NULL) {
|
if(rom.data != NULL) {
|
||||||
// unload existing ROM
|
// unload existing ROM
|
||||||
free((char *) theState.rom);
|
free((char *) rom.data);
|
||||||
theState.romLength = 0;
|
rom.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
err = FSOpen(fileName, vRefNum, &fileNo);
|
err = FSOpen(fileName, vRefNum, &fileNo);
|
||||||
|
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetEOF(fileNo, (long *) &theState.romLength);
|
GetEOF(fileNo, (long *) &rom.length);
|
||||||
theState.rom = (unsigned char *) malloc(theState.romLength);
|
rom.data = (unsigned char *) malloc(rom.length);
|
||||||
if(theState.rom == NULL) {
|
if(rom.data == NULL) {
|
||||||
Alert(ALRT_NOT_ENOUGH_RAM, NULL);
|
Alert(ALRT_NOT_ENOUGH_RAM, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
amtRead = theState.romLength;
|
amtRead = rom.length;
|
||||||
|
|
||||||
FSRead(fileNo, &amtRead, theState.rom);
|
FSRead(fileNo, &amtRead, rom.data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +146,6 @@ bool ShowOpenBox(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogPtr stateDialog;
|
|
||||||
void ShowStateDialog(void)
|
void ShowStateDialog(void)
|
||||||
{
|
{
|
||||||
DialogPtr dp;
|
DialogPtr dp;
|
||||||
|
@ -207,15 +240,34 @@ void OnMouseDown(EventRecord *pEvt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- ENTRY POINT --
|
// -- ENTRY POINT --
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
EventRecord evt;
|
EventRecord evt;
|
||||||
|
|
||||||
|
int executed;
|
||||||
|
int paused = 0;
|
||||||
|
int pause_next = 0;
|
||||||
|
|
||||||
InitEverything();
|
InitEverything();
|
||||||
|
|
||||||
|
lcd_new(&lcd);
|
||||||
|
dmg_new(&dmg, &cpu, &rom, &lcd);
|
||||||
|
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
||||||
|
|
||||||
|
cpu.pc = 0x100;
|
||||||
|
|
||||||
|
int start = TickCount();
|
||||||
while(g_running) {
|
while(g_running) {
|
||||||
if(WaitNextEvent(everyEvent, &evt, 10, 0) != nullEvent) {
|
if (emulationOn) {
|
||||||
|
dmg_step(&dmg);
|
||||||
|
int now = TickCount();
|
||||||
|
if (now > lastTicks + 100) {
|
||||||
|
lastTicks = now;
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(WaitNextEvent(everyEvent, &evt, 0, 0) != nullEvent) {
|
||||||
if (IsDialogEvent(&evt)) {
|
if (IsDialogEvent(&evt)) {
|
||||||
DialogRef hitBox;
|
DialogRef hitBox;
|
||||||
DialogItemIndex hitItem;
|
DialogItemIndex hitItem;
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
/* Game Boy emulator for 68k Macs
|
/* Game Boy emulator for 68k Macs
|
||||||
Compiled with Symantec THINK C 5.0
|
|
||||||
(c) 2013 Matt Laux
|
|
||||||
|
|
||||||
emulator.h - declarations for emulator.c */
|
emulator.h - declarations for emulator.c */
|
||||||
|
|
||||||
#ifndef EMULATOR_H
|
#ifndef EMULATOR_H
|
||||||
|
@ -44,12 +41,4 @@ typedef unsigned char bool;
|
||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
|
|
||||||
typedef struct _emu_state {
|
|
||||||
struct dmg *cpu;
|
|
||||||
u8 *rom;
|
|
||||||
unsigned long int romLength;
|
|
||||||
} emu_state;
|
|
||||||
|
|
||||||
extern emu_state theState;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -4,4 +4,3 @@ void lcd_draw(struct lcd *lcd)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user