diff --git a/cli/emulator.c b/cli/emulator.c index 5655363..de31d1a 100644 --- a/cli/emulator.c +++ b/cli/emulator.c @@ -32,9 +32,9 @@ int main(int argc, char *argv[]) dmg_new(&dmg, &cpu, &rom, &lcd); cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write); - cpu.pc = 0; + cpu.pc = 0x100; - // for (executed = 0; executed < 100000; executed++) { + // for (executed = 0; executed < 1000; executed++) { while (1) { dmg_step(&dmg); } diff --git a/src/cpu.c b/src/cpu.c index e57cb33..be0f8b2 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -306,7 +306,9 @@ static void extended_insn(struct cpu *cpu, u8 insn) shift_right // TODO SRL }; +#ifdef GB6_DEBUG printf(" %s\n", instructions[insn + 0x100].format); +#endif cpu->cycle_count += instructions[insn + 0x100].cycles; switch (op) { @@ -337,7 +339,9 @@ void cpu_step(struct cpu *cpu) u8 temp; u16 temp16; u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc); +#ifdef GB6_DEBUG printf("0x%04x %s\n", cpu->pc, instructions[opc].format); +#endif cpu->pc++; cpu->cycle_count += instructions[opc].cycles; switch (opc) { diff --git a/src/dmg.c b/src/dmg.c index 3794907..5b3bb63 100644 --- a/src/dmg.c +++ b/src/dmg.c @@ -77,6 +77,13 @@ void dmg_step(void *_dmg) // each line takes 456 cycles if (dmg->cpu->cycle_count % 456 == 0) { - lcd_step(dmg->lcd); + int next_scanline = lcd_step(dmg->lcd); + if (next_scanline == 144) { + // vblank has started, draw all the stuff from ram into the lcd + + // now copy 256x256 buf to 160x144 based on window registers + lcd_copy(dmg->lcd); + lcd_draw(dmg->lcd); + } } } \ No newline at end of file diff --git a/src/lcd.c b/src/lcd.c index c12c70a..5ec0f53 100644 --- a/src/lcd.c +++ b/src/lcd.c @@ -1,5 +1,6 @@ #include #include +#include #include "types.h" #include "lcd.h" @@ -16,23 +17,34 @@ static void clear_bit(struct lcd *lcd, u16 addr, u8 bit) void lcd_new(struct lcd *lcd) { + lcd->buf = malloc(256 * 256); // todo < 8 bpp lcd->pixels = malloc(LCD_WIDTH * LCD_HEIGHT); } u8 lcd_is_valid_addr(u16 addr) { - return addr >= REG_LCD_BASE && addr <= REG_LCD_LAST; + return (addr >= 0xfe00 && addr < 0xfea0) || (addr >= REG_LCD_BASE && addr <= REG_LCD_LAST); } u8 lcd_read(struct lcd *lcd, u16 addr) { + if (addr >= 0xfe00 && addr < 0xfea0) { + return lcd->oam[addr - 0xfe00]; + } return lcd->regs[addr - REG_LCD_BASE]; } void lcd_write(struct lcd *lcd, u16 addr, u8 value) { - lcd->regs[addr - REG_LCD_BASE] = value; + if (addr >= 0xfe00 && addr < 0xfea0) { + lcd->oam[addr - 0xfe00] = value; + } else { + lcd->regs[addr - REG_LCD_BASE] = value; + if (addr == 0xFF46) { + // OAM DMA + } + } } void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value) @@ -44,7 +56,13 @@ void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value) lcd->pixels[y * LCD_WIDTH + x] = value; } -void lcd_step(struct lcd *lcd) +void lcd_copy(struct lcd *lcd) +{ + // use all the registers to compute the pixel data + +} + +int lcd_step(struct lcd *lcd) { // update LYC if (lcd_read(lcd, REG_LY) == lcd_read(lcd, REG_LYC)) { @@ -56,5 +74,7 @@ void lcd_step(struct lcd *lcd) // step to next scanline 0-153 u8 next_scanline = (lcd_read(lcd, REG_LY) + 1) % 154; lcd_write(lcd, REG_LY, next_scanline); + + return next_scanline; // printf("update lcd %d\n", next_scanline); } \ No newline at end of file diff --git a/src/lcd.h b/src/lcd.h index 60a2456..3562645 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -25,9 +25,20 @@ #define STAT_FLAG_MATCH 2 +#define LCDC_ENABLE_BG (1 << 0) +#define LCDC_ENABLE_OBJ (1 << 1) +#define LCDC_OBJ_SIZE (1 << 2) +#define LCDC_BG_TILE_MAP (1 << 3) +#define LCDC_BG_TILE_DATA (1 << 4) +#define LCDC_ENABLE_WINDOW (1 << 5) +#define LCDC_WINDOW_TILE_MAP (1 << 6) +#define LCDC_ENABLE (1 << 7) + struct lcd { + u8 oam[0xa0]; u8 regs[0x0c]; - u8 *pixels; + u8 *buf; // 256x256 + u8 *pixels; // the actual 160x144 visible area }; void lcd_new(struct lcd *lcd); @@ -38,8 +49,10 @@ void lcd_write(struct lcd *lcd, u16 addr, u8 value); void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value); // i feel like i'm going to need to call this every cycle and update regs -void lcd_step(struct lcd *lcd); +int lcd_step(struct lcd *lcd); +void lcd_copy(struct lcd *lcd); +// output the pixels to the screen void lcd_draw(struct lcd *lcd); #endif \ No newline at end of file