fix mbc1, start scrolling routine - it's slow

This commit is contained in:
Matthew Laux 2022-08-02 00:37:19 -05:00
parent 03ef4d1116
commit f4ca6cf847
4 changed files with 70 additions and 14 deletions

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

@ -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 {
@ -508,9 +510,6 @@ static u16 check_interrupts(struct cpu *cpu)
return 0;
}
/*
*/
void cpu_step(struct cpu *cpu)
{
u8 temp;
@ -570,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;
@ -864,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;
@ -992,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);

View File

@ -67,13 +67,12 @@ u8 dmg_read(void *_dmg, u16 address)
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)) {
@ -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 {
u8 pos_y;
u8 pos_x;
@ -272,6 +288,8 @@ void dmg_step(void *_dmg)
render_objs(dmg);
}
scroll(dmg);
// now copy 256x256 buf to 160x144 based on window registers
lcd_copy(dmg->lcd);
lcd_draw(dmg->lcd);

View File

@ -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)
{
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)];
return 1;
} else if (addr >= 0xa000 && addr <= 0xbfff) {