mirror of https://github.com/mlaux/gb6.git
fix mbc1, start scrolling routine - it's slow
This commit is contained in:
parent
03ef4d1116
commit
f4ca6cf847
|
@ -13,6 +13,7 @@ extern "C" {
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
#include "instructions.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *A_FORMAT = "A: 0x%02x";
|
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 *L_FORMAT = "L: 0x%02x";
|
||||||
static const char *SP_FORMAT = "SP: 0x%02x";
|
static const char *SP_FORMAT = "SP: 0x%02x";
|
||||||
static const char *PC_FORMAT = "PC: 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 output_image[256 * 256 * 4];
|
||||||
|
unsigned char visible_pixels[160 * 144 * 4];
|
||||||
unsigned char vram_tiles[256 * 96 * 4];
|
unsigned char vram_tiles[256 * 96 * 4];
|
||||||
|
|
||||||
struct key_input {
|
struct key_input {
|
||||||
|
@ -75,6 +78,17 @@ void convert_output(struct lcd *lcd) {
|
||||||
output_image[out_index++] = 255;
|
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) {
|
void convert_vram(struct dmg *dmg) {
|
||||||
|
@ -194,6 +208,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// setup output
|
// setup output
|
||||||
GLuint texture = make_output_texture();
|
GLuint texture = make_output_texture();
|
||||||
|
GLuint vis_texture = make_output_texture();
|
||||||
GLuint vram_texture = make_output_texture();
|
GLuint vram_texture = make_output_texture();
|
||||||
|
|
||||||
editor.ReadFn = read_mem;
|
editor.ReadFn = read_mem;
|
||||||
|
@ -276,6 +291,9 @@ int main(int argc, char *argv[])
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Text(PC_FORMAT, dmg.cpu->pc);
|
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::Checkbox("Z", &z_flag);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("N", &n_flag);
|
ImGui::Checkbox("N", &n_flag);
|
||||||
|
@ -302,10 +320,10 @@ int main(int argc, char *argv[])
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convert_output(dmg.lcd);
|
||||||
{
|
{
|
||||||
ImGui::Begin("Output");
|
ImGui::Begin("Output");
|
||||||
|
|
||||||
convert_output(dmg.lcd);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_image);
|
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));
|
ImGui::Image((void*)(intptr_t) texture, ImVec2(512, 512));
|
||||||
|
@ -313,6 +331,16 @@ int main(int argc, char *argv[])
|
||||||
ImGui::End();
|
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");
|
ImGui::Begin("VRAM");
|
||||||
|
|
||||||
|
|
25
src/cpu.c
25
src/cpu.c
|
@ -269,7 +269,8 @@ static void add(struct cpu *cpu, u8 value, int with_carry)
|
||||||
{
|
{
|
||||||
u8 sum_trunc;
|
u8 sum_trunc;
|
||||||
int sum_full = cpu->a + value;
|
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_full++;
|
||||||
}
|
}
|
||||||
sum_trunc = (u8) 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_ZERO);
|
||||||
}
|
}
|
||||||
clear_flag(cpu, FLAG_SIGN);
|
clear_flag(cpu, FLAG_SIGN);
|
||||||
if (sum_full > sum_trunc) {
|
if (sum_full > 0xff) {
|
||||||
set_flag(cpu, FLAG_CARRY);
|
set_flag(cpu, FLAG_CARRY);
|
||||||
} else {
|
} else {
|
||||||
clear_flag(cpu, FLAG_CARRY);
|
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);
|
set_flag(cpu, FLAG_HALF_CARRY);
|
||||||
} else {
|
} else {
|
||||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
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;
|
u8 sum_trunc;
|
||||||
int sum_full = cpu->a - value;
|
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_full--;
|
||||||
}
|
}
|
||||||
sum_trunc = (u8) (sum_full & 0xff);
|
sum_trunc = (u8) sum_full;
|
||||||
if (!sum_trunc) {
|
if (!sum_trunc) {
|
||||||
set_flag(cpu, FLAG_ZERO);
|
set_flag(cpu, FLAG_ZERO);
|
||||||
} else {
|
} else {
|
||||||
|
@ -508,9 +510,6 @@ static u16 check_interrupts(struct cpu *cpu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void cpu_step(struct cpu *cpu)
|
void cpu_step(struct cpu *cpu)
|
||||||
{
|
{
|
||||||
u8 temp;
|
u8 temp;
|
||||||
|
@ -570,6 +569,13 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->a = rotate_right(cpu, cpu->a);
|
cpu->a = rotate_right(cpu, cpu->a);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x37: // SCF
|
||||||
|
set_flag(cpu, FLAG_CARRY);
|
||||||
|
break;
|
||||||
|
case 0x3f: // CCF
|
||||||
|
clear_flag(cpu, FLAG_CARRY);
|
||||||
|
break;
|
||||||
|
|
||||||
// incs and decs
|
// incs and decs
|
||||||
case 0x03: write_bc(cpu, read_bc(cpu) + 1); break;
|
case 0x03: write_bc(cpu, read_bc(cpu) + 1); break;
|
||||||
case 0x04: inc_with_carry(cpu, &cpu->b); break;
|
case 0x04: inc_with_carry(cpu, &cpu->b); break;
|
||||||
|
@ -864,7 +870,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xde: // SBC A, u8
|
case 0xde: // SBC A, u8
|
||||||
subtract(cpu, read8(cpu, cpu->pc), 0, 1);
|
subtract(cpu, read8(cpu, cpu->pc), 1, 0);
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -992,6 +998,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
break;
|
break;
|
||||||
case 0xf1: // POP AF
|
case 0xf1: // POP AF
|
||||||
write_af(cpu, pop(cpu));
|
write_af(cpu, pop(cpu));
|
||||||
|
cpu->f &= 0xf0;
|
||||||
break;
|
break;
|
||||||
case 0xf2: // LD A,(C)
|
case 0xf2: // LD A,(C)
|
||||||
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
||||||
|
|
24
src/dmg.c
24
src/dmg.c
|
@ -67,13 +67,12 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||||
if (address < 0x4000) {
|
if (address < 0x4000) {
|
||||||
return dmg->rom->data[address];
|
return dmg->rom->data[address];
|
||||||
} else if (address < 0x8000) {
|
} else if (address < 0x8000) {
|
||||||
// TODO switchable rom bank
|
|
||||||
return dmg->rom->data[address];
|
return dmg->rom->data[address];
|
||||||
} else if (address < 0xa000) {
|
} else if (address < 0xa000) {
|
||||||
return dmg->video_ram[address - 0x8000];
|
return dmg->video_ram[address - 0x8000];
|
||||||
} else if (address < 0xc000) {
|
} else if (address < 0xc000) {
|
||||||
// TODO switchable ram bank
|
printf("RAM bank not handled by MBC\n");
|
||||||
return 0;
|
return 0xff;
|
||||||
} else if (address < 0xe000) {
|
} else if (address < 0xe000) {
|
||||||
return dmg->main_ram[address - 0xc000];
|
return dmg->main_ram[address - 0xc000];
|
||||||
} else if (lcd_is_valid_addr(address)) {
|
} else if (lcd_is_valid_addr(address)) {
|
||||||
|
@ -182,6 +181,23 @@ static void render_background(struct dmg *dmg, int lcdc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scroll(struct dmg *dmg)
|
||||||
|
{
|
||||||
|
int scroll_y = lcd_read(dmg->lcd, REG_SCY);
|
||||||
|
int scroll_x = lcd_read(dmg->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);
|
||||||
|
|
||||||
|
dmg->lcd->pixels[lines * 160 + cols] = dmg->lcd->buf[src_off];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct oam_entry {
|
struct oam_entry {
|
||||||
u8 pos_y;
|
u8 pos_y;
|
||||||
u8 pos_x;
|
u8 pos_x;
|
||||||
|
@ -272,6 +288,8 @@ void dmg_step(void *_dmg)
|
||||||
render_objs(dmg);
|
render_objs(dmg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scroll(dmg);
|
||||||
|
|
||||||
// now copy 256x256 buf to 160x144 based on window registers
|
// now copy 256x256 buf to 160x144 based on window registers
|
||||||
lcd_copy(dmg->lcd);
|
lcd_copy(dmg->lcd);
|
||||||
lcd_draw(dmg->lcd);
|
lcd_draw(dmg->lcd);
|
||||||
|
|
|
@ -19,7 +19,10 @@ static int mbc_noop_write(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 data)
|
||||||
static int mbc1_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data)
|
static int mbc1_read(struct mbc *mbc, struct dmg *dmg, u16 addr, u8 *out_data)
|
||||||
{
|
{
|
||||||
if (addr >= 0x4000 && addr <= 0x7fff) {
|
if (addr >= 0x4000 && addr <= 0x7fff) {
|
||||||
int use_bank = mbc->rom_bank || 1;
|
int use_bank = mbc->rom_bank;
|
||||||
|
if (!use_bank) {
|
||||||
|
use_bank = 1;
|
||||||
|
}
|
||||||
*out_data = dmg->rom->data[0x4000 * use_bank + (addr & 0x3fff)];
|
*out_data = dmg->rom->data[0x4000 * use_bank + (addr & 0x3fff)];
|
||||||
return 1;
|
return 1;
|
||||||
} else if (addr >= 0xa000 && addr <= 0xbfff) {
|
} else if (addr >= 0xa000 && addr <= 0xbfff) {
|
||||||
|
|
Loading…
Reference in New Issue