Compare commits

...

5 Commits

Author SHA1 Message Date
Matthew Laux 4cde94d284 a little work on system 6 2022-08-02 01:52:59 -05:00
Matthew Laux 2adf5b741b render objs on top of scrolled area instead of into 256x256 area 2022-08-02 00:51:26 -05:00
Matthew Laux f4ca6cf847 fix mbc1, start scrolling routine - it's slow 2022-08-02 00:37:19 -05:00
Matthew Laux 03ef4d1116 start on mbc1 2022-08-01 22:45:37 -05:00
Matthew Laux 0f43ebf4cc render objs, fix bug with SRL, tetris is playable 2022-08-01 21:26:31 -05:00
14 changed files with 394 additions and 96 deletions

View File

@ -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

View File

@ -13,6 +13,7 @@ extern "C" {
#include "cpu.h"
#include "rom.h"
#include "lcd.h"
#include "instructions.h"
}
static const char *A_FORMAT = "A: 0x%02x";
@ -24,8 +25,10 @@ static const char *H_FORMAT = "H: 0x%02x";
static const char *L_FORMAT = "L: 0x%02x";
static const char *SP_FORMAT = "SP: 0x%02x";
static const char *PC_FORMAT = "PC: 0x%02x";
static const char *INSN_FORMAT = "Next instruction: %s";
unsigned char output_image[256 * 256 * 4];
unsigned char visible_pixels[160 * 144 * 4];
unsigned char vram_tiles[256 * 96 * 4];
struct key_input {
@ -59,7 +62,7 @@ GLuint make_output_texture() {
return image_texture;
}
unsigned char default_palette[] = { 0, 0x55, 0xaa, 0xff };
unsigned char default_palette[] = { 0xff, 0xaa, 0x55, 0x00 };
void convert_output(struct lcd *lcd) {
int x, y;
@ -75,6 +78,17 @@ void convert_output(struct lcd *lcd) {
output_image[out_index++] = 255;
}
}
out_index = 0;
for (y = 0; y < 144; y++) {
for (x = 0; x < 160; x++) {
int val = lcd->pixels[y * 160 + x];
int fill = default_palette[val];
visible_pixels[out_index++] = fill;
visible_pixels[out_index++] = fill;
visible_pixels[out_index++] = fill;
visible_pixels[out_index++] = 255;
}
}
}
void convert_vram(struct dmg *dmg) {
@ -194,6 +208,7 @@ int main(int argc, char *argv[])
// setup output
GLuint texture = make_output_texture();
GLuint vis_texture = make_output_texture();
GLuint vram_texture = make_output_texture();
editor.ReadFn = read_mem;
@ -276,6 +291,9 @@ int main(int argc, char *argv[])
ImGui::SameLine();
ImGui::Text(PC_FORMAT, dmg.cpu->pc);
u8 opc = dmg_read(&dmg, dmg.cpu->pc);
ImGui::Text(INSN_FORMAT, instructions[opc].format);
ImGui::Checkbox("Z", &z_flag);
ImGui::SameLine();
ImGui::Checkbox("N", &n_flag);
@ -302,10 +320,10 @@ int main(int argc, char *argv[])
ImGui::End();
}
convert_output(dmg.lcd);
{
ImGui::Begin("Output");
convert_output(dmg.lcd);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_image);
ImGui::Image((void*)(intptr_t) texture, ImVec2(512, 512));
@ -313,6 +331,16 @@ int main(int argc, char *argv[])
ImGui::End();
}
{
ImGui::Begin("LCD");
glBindTexture(GL_TEXTURE_2D, vis_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 160, 144, 0, GL_RGBA, GL_UNSIGNED_BYTE, visible_pixels);
ImGui::Image((void*)(intptr_t) vis_texture, ImVec2(320, 288));
ImGui::End();
}
{
ImGui::Begin("VRAM");

View File

@ -213,7 +213,7 @@ static u8 srl(struct cpu *cpu, u8 value)
}
clear_flag(cpu, FLAG_SIGN);
clear_flag(cpu, FLAG_HALF_CARRY);
return 0;
return result;
}
static u8 swap(struct cpu *cpu, u8 value)
@ -269,7 +269,8 @@ static void add(struct cpu *cpu, u8 value, int with_carry)
{
u8 sum_trunc;
int sum_full = cpu->a + value;
if (with_carry && flag_isset(cpu, FLAG_CARRY)) {
int carry = (with_carry && flag_isset(cpu, FLAG_CARRY)) ? 1 : 0;
if (carry) {
sum_full++;
}
sum_trunc = (u8) sum_full;
@ -279,12 +280,12 @@ static void add(struct cpu *cpu, u8 value, int with_carry)
clear_flag(cpu, FLAG_ZERO);
}
clear_flag(cpu, FLAG_SIGN);
if (sum_full > sum_trunc) {
if (sum_full > 0xff) {
set_flag(cpu, FLAG_CARRY);
} else {
clear_flag(cpu, FLAG_CARRY);
}
if (((cpu->a & 0xf) + (value & 0xf)) & 0x10) {
if (((cpu->a & 0xf) + (value & 0xf) + carry) & 0x10) {
set_flag(cpu, FLAG_HALF_CARRY);
} else {
clear_flag(cpu, FLAG_HALF_CARRY);
@ -296,10 +297,11 @@ static void subtract(struct cpu *cpu, u8 value, int with_carry, int just_compare
{
u8 sum_trunc;
int sum_full = cpu->a - value;
if (with_carry && flag_isset(cpu, FLAG_CARRY)) {
int carry = (with_carry && flag_isset(cpu, FLAG_CARRY)) ? 1 : 0;
if (carry) {
sum_full--;
}
sum_trunc = (u8) (sum_full & 0xff);
sum_trunc = (u8) sum_full;
if (!sum_trunc) {
set_flag(cpu, FLAG_ZERO);
} else {
@ -453,6 +455,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)
@ -512,6 +542,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;
@ -536,6 +569,13 @@ void cpu_step(struct cpu *cpu)
cpu->a = rotate_right(cpu, cpu->a);
break;
case 0x37: // SCF
set_flag(cpu, FLAG_CARRY);
break;
case 0x3f: // CCF
clear_flag(cpu, FLAG_CARRY);
break;
// incs and decs
case 0x03: write_bc(cpu, read_bc(cpu) + 1); break;
case 0x04: inc_with_carry(cpu, &cpu->b); break;
@ -761,7 +801,7 @@ void cpu_step(struct cpu *cpu)
case 0xd2: // JP NC,a16
temp16 = read16(cpu, cpu->pc);
cpu->pc += 2;
if (flag_isset(cpu, FLAG_CARRY)) {
if (!flag_isset(cpu, FLAG_CARRY)) {
cpu->pc = temp16;
cpu->cycle_count += instructions[opc].cycles_branch - instructions[opc].cycles;
}
@ -772,6 +812,14 @@ void cpu_step(struct cpu *cpu)
cpu->cycle_count += instructions[opc].cycles_branch - instructions[opc].cycles;
}
break;
case 0xda: // JP C, u16
temp16 = read16(cpu, cpu->pc);
cpu->pc += 2;
if (flag_isset(cpu, FLAG_CARRY)) {
cpu->pc = temp16;
cpu->cycle_count += instructions[opc].cycles_branch - instructions[opc].cycles;
}
break;
case 0x80: add(cpu, cpu->b, 0); break;
case 0x81: add(cpu, cpu->c, 0); break;
@ -822,7 +870,7 @@ void cpu_step(struct cpu *cpu)
break;
case 0xde: // SBC A, u8
subtract(cpu, read8(cpu, cpu->pc), 0, 1);
subtract(cpu, read8(cpu, cpu->pc), 1, 0);
cpu->pc++;
break;
@ -884,6 +932,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
@ -949,6 +998,7 @@ void cpu_step(struct cpu *cpu)
break;
case 0xf1: // POP AF
write_af(cpu, pop(cpu));
cpu->f &= 0xf0;
break;
case 0xf2: // LD A,(C)
cpu->a = read8(cpu, 0xff00 + cpu->c);

145
src/dmg.c
View File

@ -5,6 +5,7 @@
#include "rom.h"
#include "lcd.h"
#include "dmg.h"
#include "mbc.h"
#include "types.h"
#include "bootstrap.h"
@ -54,19 +55,24 @@ 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) {
if (address < 0x4000) {
return dmg->rom->data[address];
} else if (address < 0x8000) {
// TODO switchable rom bank
return dmg->rom->data[address];
} else if (address < 0xa000) {
return dmg->video_ram[address - 0x8000];
} else if (address < 0xc000) {
// TODO switchable ram bank
return 0;
printf("RAM bank not handled by MBC\n");
return 0xff;
} else if (address < 0xe000) {
return dmg->main_ram[address - 0xc000];
} else if (lcd_is_valid_addr(address)) {
@ -93,13 +99,16 @@ 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);
dmg->rom->data[address] = data;
} else if (address < 0x8000) {
// TODO switchable rom bank
printf("warning: writing 0x%04x in rom\n", address);
dmg->rom->data[address] = data;
} else if (address < 0xa000) {
dmg->video_ram[address - 0x8000] = data;
} else if (address < 0xc000) {
@ -135,6 +144,86 @@ void dmg_request_interrupt(struct dmg *dmg, int nr)
dmg->interrupt_requested |= nr;
}
// TODO move to lcd.c, it needs to be able to access dmg_read though
static void render_background(struct dmg *dmg, int lcdc)
{
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
int window_base = (lcdc & LCDC_WINDOW_TILE_MAP) ? 0x9c00 : 0x9800;
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
int tilebase = use_unsigned ? 0x8000 : 0x9000;
//printf("%04x %04x %04x\n", bg_base, window_base, tilebase);
int k = 0, off = 0;
int tile_y = 0, tile_x = 0;
for (tile_y = 0; tile_y < 32; tile_y++) {
for (tile_x = 0; tile_x < 32; tile_x++) {
off = 256 * 8 * tile_y + 8 * tile_x;
int tile = dmg_read(dmg, bg_base + (tile_y * 32 + tile_x));
int eff_addr;
if (use_unsigned) {
eff_addr = tilebase + 16 * tile;
} else {
eff_addr = tilebase + 16 * (signed char) tile;
}
int b, i;
for (b = 0; b < 16; b += 2) {
int data1 = dmg_read(dmg, eff_addr + b);
int data2 = dmg_read(dmg, eff_addr + b + 1);
for (i = 7; i >= 0; i--) {
dmg->lcd->buf[off] = ((data1 & (1 << i)) ? 1 : 0) << 1;
dmg->lcd->buf[off] |= (data2 & (1 << i)) ? 1 : 0;
off++;
}
off += 248;
}
}
}
}
struct oam_entry {
u8 pos_y;
u8 pos_x;
u8 tile;
u8 attrs;
};
// TODO: only ten per scanline, priority
static void render_objs(struct dmg *dmg)
{
struct oam_entry *oam = (struct oam_entry *) dmg->lcd->oam;
int k, lcd_x, lcd_y, off;
for (k = 0; k < 40; k++, oam++) {
if (oam->pos_y == 0 || oam->pos_y >= 160) {
continue;
}
if (oam->pos_x == 0 || oam->pos_y >= 168) {
continue;
}
lcd_x = oam->pos_x - 8;
lcd_y = oam->pos_y - 16;
off = 160 * lcd_y + lcd_x;
int eff_addr = 0x8000 + 16 * oam->tile;
int b, i;
for (b = 0; b < 16; b += 2) {
int data1 = dmg_read(dmg, eff_addr + b);
int data2 = dmg_read(dmg, eff_addr + b + 1);
for (i = 7; i >= 0; i--) {
if (off < 0 || off >= 160 * 144) {
// terrible clipping. need to not have an if per-pixel
continue;
}
dmg->lcd->pixels[off] = ((data1 & (1 << i)) ? 1 : 0) << 1;
dmg->lcd->pixels[off] |= (data2 & (1 << i)) ? 1 : 0;
off++;
}
off += 152;
}
}
}
void dmg_step(void *_dmg)
{
struct dmg *dmg = (struct dmg *) _dmg;
@ -165,6 +254,7 @@ void dmg_step(void *_dmg)
lcd_set_mode(dmg->lcd, 1);
}
// TODO: do all of this per-scanline instead of everything in vblank
if (next_scanline == 144) {
// vblank has started, draw all the stuff from ram into the lcd
dmg_request_interrupt(dmg, INT_VBLANK);
@ -173,41 +263,20 @@ void dmg_step(void *_dmg)
}
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
int window_base = (lcdc & LCDC_WINDOW_TILE_MAP) ? 0x9c00 : 0x9800;
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
int tilebase = use_unsigned ? 0x8000 : 0x9000;
//printf("%04x %04x %04x\n", bg_base, window_base, tilebase);
int k = 0, off = 0;
int tile_y = 0, tile_x = 0;
for (tile_y = 0; tile_y < 32; tile_y++) {
for (tile_x = 0; tile_x < 32; tile_x++) {
off = 256 * 8 * tile_y + 8 * tile_x;
int tile = dmg_read(dmg, bg_base + (tile_y * 32 + tile_x));
int eff_addr;
if (use_unsigned) {
eff_addr = tilebase + 16 * tile;
} else {
eff_addr = tilebase + 16 * (signed char) tile;
}
int b, i;
for (b = 0; b < 16; b += 2) {
int data1 = dmg_read(dmg, eff_addr + b);
int data2 = dmg_read(dmg, eff_addr + b + 1);
for (i = 7; i >= 0; i--) {
dmg->lcd->buf[off] = ((data1 & (1 << i)) ? 1 : 0) << 1;
dmg->lcd->buf[off] |= (data2 & (1 << i)) ? 1 : 0;
off++;
}
off += 248;
}
}
if (lcdc & LCDC_ENABLE_BG) {
render_background(dmg, lcdc);
}
if (lcdc & LCDC_ENABLE_WINDOW) {
// printf("window\n");
}
lcd_apply_scroll(dmg->lcd);
if (lcdc & LCDC_ENABLE_OBJ) {
render_objs(dmg);
}
// now copy 256x256 buf to 160x144 based on window registers
lcd_copy(dmg->lcd);
lcd_draw(dmg->lcd);
}
} else {

View File

@ -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;

View File

@ -66,10 +66,20 @@ void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
lcd->pixels[y * LCD_WIDTH + x] = value;
}
void lcd_copy(struct lcd *lcd)
void lcd_apply_scroll(struct lcd *lcd)
{
// use all the registers to compute the pixel data
int scroll_y = lcd_read(lcd, REG_SCY);
int scroll_x = lcd_read(lcd, REG_SCX);
int lines;
for (lines = 0; lines < 144; lines++) {
int src_y = (scroll_y + lines) & 0xff;
int cols;
for (cols = 0; cols < 160; cols++) {
int src_off = (src_y << 8) + ((scroll_x + cols) & 0xff);
lcd->pixels[lines * 160 + cols] = lcd->buf[src_off];
}
}
}
int lcd_step(struct lcd *lcd)

View File

@ -58,9 +58,8 @@ void lcd_clear_bit(struct lcd *lcd, u16 addr, u8 bit);
int lcd_isset(struct lcd *lcd, u16 addr, u8 bit);
void lcd_set_mode(struct lcd *lcd, int mode);
// i feel like i'm going to need to call this every cycle and update regs
int lcd_step(struct lcd *lcd);
void lcd_copy(struct lcd *lcd);
void lcd_apply_scroll(struct lcd *lcd);
// output the pixels to the screen
void lcd_draw(struct lcd *lcd);

94
src/mbc.c Normal file
View File

@ -0,0 +1,94 @@
#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;
if (!use_bank) {
use_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
View 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

View File

@ -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;
}

View File

@ -2,11 +2,12 @@
#define _ROM_H
#include "types.h"
#include "mbc.h"
struct rom {
u32 length;
int type;
u8 *data;
struct mbc *mbc;
};
int rom_load(struct rom *rom, const char *filename);

View File

@ -12,6 +12,7 @@ add_application(Emulator
../src/instructions.c
../src/lcd.c
../src/rom.c
../src/mbc.c
emulator.c
lcd_mac.c
resources.r

View File

@ -18,6 +18,7 @@
#include "cpu.h"
#include "rom.h"
#include "lcd.h"
#include "mbc.h"
WindowPtr g_wp;
DialogPtr stateDialog;
@ -52,8 +53,9 @@ void InitEverything(void)
g_running = 1;
}
char offscreen[32 * 256];
Rect offscreenRect = { 0, 0, 256, 256 };
// 160 pixels / 8 bits per pixel = 20 bytes per line
char offscreen[20 * 144];
Rect offscreenRect = { 0, 0, 144, 160 };
BitMap offscreenBmp;
@ -61,26 +63,34 @@ int lastTicks;
void Render(void)
{
long k = 0, dst;
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++];
long k = 0, dst, bit;
for (dst = 0; dst < 20 * 144; dst++) {
for (bit = 7; bit >= 0; bit--) {
offscreen[dst] |= lcd.pixels[k++];
offscreen[dst] <<= 1;
}
dst++;
}
/*
offscreen[dst] = lcd.pixels[k++] << 7;
offscreen[dst] |= lcd.pixels[k++] << 6;
offscreen[dst] |= lcd.pixels[k++] << 5;
offscreen[dst] |= lcd.pixels[k++] << 4;
offscreen[dst] |= lcd.pixels[k++] << 3;
offscreen[dst] |= lcd.pixels[k++] << 2;
offscreen[dst] |= lcd.pixels[k++] << 1;
offscreen[dst] |= lcd.pixels[k++];
*/
SetPort(g_wp);
CopyBits(&offscreenBmp, &g_wp->portBits, &offscreenRect, &g_wp->portRect, srcCopy, NULL);
CopyBits(&offscreenBmp, &g_wp->portBits, &offscreenRect, &offscreenRect, srcCopy, NULL);
//EraseRect(&g_wp->portRect);
MoveTo(10, 160);
char debug[128];
sprintf(debug, "PC: %04x", cpu.pc);
C2PStr(debug);
DrawString(debug);
// MoveTo(10, 160);
// char debug[128];
// sprintf(debug, "PC: %04x", cpu.pc);
// C2PStr(debug);
// DrawString(debug);
}
void StartEmulation(void)
@ -91,7 +101,7 @@ void StartEmulation(void)
offscreenBmp.baseAddr = offscreen;
offscreenBmp.bounds = offscreenRect;
offscreenBmp.rowBytes = 32;
offscreenBmp.rowBytes = 20;
emulationOn = 1;
}
@ -121,8 +131,15 @@ bool LoadRom(StrFileName fileName, short vRefNum)
}
amtRead = rom.length;
FSRead(fileNo, &amtRead, rom.data);
rom.mbc = mbc_new(rom.data[0x147]);
if (!rom.mbc) {
ParamText("\pThis cartridge type is unsupported.", "\p", "\p", "\p");
Alert(ALRT_4_LINE, NULL);
return false;
}
return true;
}
@ -265,24 +282,25 @@ int main(int argc, char *argv[])
lastTicks = now;
Render();
}
}
if(WaitNextEvent(everyEvent, &evt, 0, 0) != nullEvent) {
if (IsDialogEvent(&evt)) {
DialogRef hitBox;
DialogItemIndex hitItem;
if (DialogSelect(&evt, &hitBox, &hitItem)) {
stateDialog = NULL;
if (Button()) g_running = false;
} else {
if(WaitNextEvent(everyEvent, &evt, 0, 0) != nullEvent) {
if (IsDialogEvent(&evt)) {
DialogRef hitBox;
DialogItemIndex hitItem;
if (DialogSelect(&evt, &hitBox, &hitItem)) {
stateDialog = NULL;
}
} else switch(evt.what) {
case mouseDown:
OnMouseDown(&evt);
break;
case updateEvt:
BeginUpdate((WindowPtr) evt.message);
Render();
EndUpdate((WindowPtr) evt.message);
break;
}
} else switch(evt.what) {
case mouseDown:
OnMouseDown(&evt);
break;
case updateEvt:
BeginUpdate((WindowPtr) evt.message);
Render();
EndUpdate((WindowPtr) evt.message);
break;
}
}
}

View File

@ -7,7 +7,7 @@
#include "types.h"
#include "dmg.h"
#define WINDOW_TITLE "\pEmulator"
#define WINDOW_TITLE "\pOutput"
#define WINDOW_X 100
#define WINDOW_Y 100