mirror of
https://github.com/mlaux/gb6.git
synced 2025-01-07 18:32:53 +00:00
starting on lcd
This commit is contained in:
parent
fe43c07883
commit
b42faf8149
@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
make
|
make
|
||||||
cd ..
|
cd ..
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
#include "dmg.h"
|
#include "dmg.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct cpu cpu;
|
struct cpu cpu;
|
||||||
struct rom rom;
|
struct rom rom;
|
||||||
struct dmg dmg;
|
struct dmg dmg;
|
||||||
int executed = 0;
|
struct lcd lcd;
|
||||||
|
|
||||||
|
int executed;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("no rom specified\n");
|
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
|
// this might be too much abstraction but it'll let me
|
||||||
// test the cpu, rom, and dmg independently and use the cpu
|
// test the cpu, rom, and dmg independently and use the cpu
|
||||||
// for other non-GB stuff
|
// 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_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
||||||
|
|
||||||
cpu.pc = 0;
|
cpu.pc = 0;
|
||||||
|
|
||||||
for (; executed < 100000; executed++) {
|
for (executed = 0; executed < 100000; executed++) {
|
||||||
cpu_step(&cpu);
|
cpu_step(&cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/dmg.c
20
src/dmg.c
@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
|
#include "lcd.h"
|
||||||
#include "dmg.h"
|
#include "dmg.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "bootstrap.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->cpu = cpu;
|
||||||
dmg->rom = rom;
|
dmg->rom = rom;
|
||||||
|
dmg->lcd = lcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 dmg_read(void *_dmg, u16 address)
|
u8 dmg_read(void *_dmg, u16 address)
|
||||||
@ -30,10 +32,13 @@ u8 dmg_read(void *_dmg, u16 address)
|
|||||||
return 0;
|
return 0;
|
||||||
} 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)) {
|
||||||
|
return lcd_read(dmg->lcd, address);
|
||||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
return dmg->zero_page[address - 0xff80];
|
return dmg->zero_page[address - 0xff80];
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// not sure about any of this yet
|
||||||
|
fprintf(stderr, "don't know how to read 0x%04x\n", address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,9 +59,22 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
|||||||
// TODO switchable ram bank
|
// TODO switchable ram bank
|
||||||
} else if (address < 0xe000) {
|
} else if (address < 0xe000) {
|
||||||
dmg->main_ram[address - 0xc000] = data;
|
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) {
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
dmg->zero_page[address - 0xff80] = data;
|
dmg->zero_page[address - 0xff80] = data;
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// 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];
|
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);
|
u8 dmg_read(void *dmg, u16 address);
|
||||||
void dmg_write(void *dmg, u16 address, u8 data);
|
void dmg_write(void *dmg, u16 address, u8 data);
|
||||||
|
|
||||||
|
void dmg_step(void *dmg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
43
src/lcd.c
43
src/lcd.c
@ -3,6 +3,35 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "lcd.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)
|
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
|
||||||
{
|
{
|
||||||
if (x >= LCD_WIDTH || y >= LCD_HEIGHT) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
lcd->pixels[y * LCD_WIDTH + x] = value;
|
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_WIDTH 160
|
||||||
#define LCD_HEIGHT 144
|
#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 {
|
struct lcd {
|
||||||
|
u8 regs[0x0c];
|
||||||
u8 *pixels;
|
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);
|
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
|
#endif
|
Loading…
Reference in New Issue
Block a user