mirror of
https://github.com/mlaux/gb6.git
synced 2025-01-06 12:31:12 +00:00
starting on lcd
This commit is contained in:
parent
fe43c07883
commit
b42faf8149
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
cd ..
|
||||
|
@ -3,13 +3,16 @@
|
||||
#include "dmg.h"
|
||||
#include "cpu.h"
|
||||
#include "rom.h"
|
||||
#include "lcd.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct cpu cpu;
|
||||
struct rom rom;
|
||||
struct dmg dmg;
|
||||
int executed = 0;
|
||||
struct lcd lcd;
|
||||
|
||||
int executed;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("no rom specified\n");
|
||||
@ -24,12 +27,12 @@ int main(int argc, char *argv[])
|
||||
// this might be too much abstraction but it'll let me
|
||||
// test the cpu, rom, and dmg independently and use the cpu
|
||||
// for other non-GB stuff
|
||||
dmg_new(&dmg, &cpu, &rom);
|
||||
dmg_new(&dmg, &cpu, &rom, &lcd);
|
||||
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
||||
|
||||
cpu.pc = 0;
|
||||
|
||||
for (; executed < 100000; executed++) {
|
||||
for (executed = 0; executed < 100000; executed++) {
|
||||
cpu_step(&cpu);
|
||||
}
|
||||
|
||||
|
20
src/dmg.c
20
src/dmg.c
@ -2,14 +2,16 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "rom.h"
|
||||
#include "lcd.h"
|
||||
#include "dmg.h"
|
||||
#include "types.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom)
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd)
|
||||
{
|
||||
dmg->cpu = cpu;
|
||||
dmg->rom = rom;
|
||||
dmg->lcd = lcd;
|
||||
}
|
||||
|
||||
u8 dmg_read(void *_dmg, u16 address)
|
||||
@ -30,10 +32,13 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||
return 0;
|
||||
} else if (address < 0xe000) {
|
||||
return dmg->main_ram[address - 0xc000];
|
||||
} else if (lcd_is_valid_addr(address)) {
|
||||
return lcd_read(dmg->lcd, address);
|
||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||
return dmg->zero_page[address - 0xff80];
|
||||
} else {
|
||||
// not sure about any of this yet
|
||||
fprintf(stderr, "don't know how to read 0x%04x\n", address);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -54,9 +59,22 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
||||
// TODO switchable ram bank
|
||||
} else if (address < 0xe000) {
|
||||
dmg->main_ram[address - 0xc000] = data;
|
||||
} else if (lcd_is_valid_addr(address)) {
|
||||
lcd_write(dmg->lcd, address, data);
|
||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||
dmg->zero_page[address - 0xff80] = data;
|
||||
} else {
|
||||
// not sure about any of this yet
|
||||
}
|
||||
}
|
||||
|
||||
void dmg_step(void *_dmg)
|
||||
{
|
||||
struct dmg *dmg = (struct dmg *) _dmg;
|
||||
|
||||
// order of dependencies? i think cpu needs to step first then update
|
||||
// all other hw
|
||||
cpu_step(dmg->cpu);
|
||||
|
||||
lcd_step(dmg->lcd);
|
||||
}
|
@ -13,9 +13,12 @@ struct dmg {
|
||||
u8 zero_page[0x80];
|
||||
};
|
||||
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom);
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd);
|
||||
|
||||
// why did i make these void *
|
||||
u8 dmg_read(void *dmg, u16 address);
|
||||
void dmg_write(void *dmg, u16 address, u8 data);
|
||||
|
||||
void dmg_step(void *dmg);
|
||||
|
||||
#endif
|
||||
|
43
src/lcd.c
43
src/lcd.c
@ -3,6 +3,35 @@
|
||||
#include "types.h"
|
||||
#include "lcd.h"
|
||||
|
||||
static void set_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||
{
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) | (1 << bit));
|
||||
}
|
||||
|
||||
static void clear_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||
{
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) & ~(1 << bit));
|
||||
}
|
||||
|
||||
u8 lcd_is_valid_addr(u16 addr)
|
||||
{
|
||||
return addr >= REG_LCD_BASE && addr <= REG_LCD_LAST;
|
||||
}
|
||||
|
||||
u8 lcd_read(struct lcd *lcd, u16 addr)
|
||||
{
|
||||
return lcd->regs[addr - REG_LCD_BASE];
|
||||
}
|
||||
|
||||
void lcd_write(struct lcd *lcd, u16 addr, u8 value)
|
||||
{
|
||||
if (addr == REG_LY) {
|
||||
// writing to this register always resets it
|
||||
value = 0;
|
||||
}
|
||||
lcd->regs[addr - REG_LCD_BASE] = value;
|
||||
}
|
||||
|
||||
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
|
||||
{
|
||||
if (x >= LCD_WIDTH || y >= LCD_HEIGHT) {
|
||||
@ -10,4 +39,18 @@ void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
|
||||
return;
|
||||
}
|
||||
lcd->pixels[y * LCD_WIDTH + x] = value;
|
||||
}
|
||||
|
||||
void 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
|
||||
u8 next_scanline = (lcd_read(lcd, REG_LY) + 1) % 154;
|
||||
lcd_write(lcd, REG_LY, next_scanline);
|
||||
}
|
27
src/lcd.h
27
src/lcd.h
@ -6,10 +6,37 @@
|
||||
#define LCD_WIDTH 160
|
||||
#define LCD_HEIGHT 144
|
||||
|
||||
#define REG_LCD_BASE 0xff40
|
||||
|
||||
#define REG_LCDC 0xff40
|
||||
#define REG_STAT 0xff41
|
||||
#define REG_SCY 0xff42
|
||||
#define REG_SCX 0xff43
|
||||
#define REG_LY 0xff44
|
||||
#define REG_LYC 0xff45
|
||||
#define REG_DMA 0xff46
|
||||
#define REG_BGP 0xff47
|
||||
#define REG_OBP0 0xff48
|
||||
#define REG_OBP1 0xff49
|
||||
#define REG_WY 0xff4a
|
||||
#define REG_WX 0xff4b
|
||||
|
||||
#define REG_LCD_LAST REG_WX
|
||||
|
||||
#define STAT_FLAG_MATCH 2
|
||||
|
||||
struct lcd {
|
||||
u8 regs[0x0c];
|
||||
u8 *pixels;
|
||||
};
|
||||
|
||||
u8 lcd_is_valid_addr(u16 addr);
|
||||
u8 lcd_read(struct lcd *lcd, u16 addr);
|
||||
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);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user