frontend with sfml window displaying tile data
This commit is contained in:
parent
d0a4b5a217
commit
6263386b11
4 changed files with 151 additions and 6 deletions
6
Makeconf
6
Makeconf
|
@ -1,4 +1,4 @@
|
||||||
TARGETS := libemu.a vgbc vgbc.test vgbc.inspect vgbc.gbdif
|
TARGETS := libemu.a vgbc vgbc.test vgbc.inspect vgbc.gbdif vgbc.lcdtest
|
||||||
|
|
||||||
sfml_packages := sfml-graphics
|
sfml_packages := sfml-graphics
|
||||||
sfml_CXXFLAGS := $(shell pkg-config --cflags $(sfml_packages))
|
sfml_CXXFLAGS := $(shell pkg-config --cflags $(sfml_packages))
|
||||||
|
@ -39,3 +39,7 @@ verb_vgbc.inspect := link
|
||||||
# Game Boy Doctor Interface
|
# Game Boy Doctor Interface
|
||||||
modules_vgbc.gbdif := misc/gbdif.o libemu.a
|
modules_vgbc.gbdif := misc/gbdif.o libemu.a
|
||||||
verb_vgbc.gbdif := link
|
verb_vgbc.gbdif := link
|
||||||
|
|
||||||
|
modules_vgbc.lcdtest := lcd/lcdtest.o libemu.a
|
||||||
|
verb_vgbc.lcdtest := link
|
||||||
|
LDFLAGS_vgbc.lcdtest := $(sfml_LDFLAGS)
|
||||||
|
|
52
lcd/lcd.cpp
52
lcd/lcd.cpp
|
@ -1,21 +1,47 @@
|
||||||
#include <lcd/lcd.h>
|
#include <lcd/lcd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
LCD::LCD(Cpu& cpu)
|
LCD::LCD(Cpu& cpu)
|
||||||
: screenbuffer(), regLY(0), regLYC(0),
|
: screenbuffer(), regLY(90), regLYC(0),
|
||||||
intHBlank(false), intVBlank(false), intOAM(false), intLYC(false),
|
intHBlank(false), intVBlank(false), intOAM(false), intLYC(false),
|
||||||
cpu(cpu), bgp(false), obp{Palette(true),Palette(true)},
|
cpu(cpu), bgp(false), obp{Palette(true),Palette(true)},
|
||||||
vram_dirty(true)
|
vram_dirty(true), currentMode(ModeVBlank)
|
||||||
{
|
{
|
||||||
screenbuffer.create(160,144);
|
screenbuffer.create(160,144);
|
||||||
screenbuffer.clear();
|
screenbuffer.clear();
|
||||||
|
|
||||||
std::memset(vram_raw, 0, 0x2000);
|
std::memset(vram_raw, 0, 0x2000);
|
||||||
|
|
||||||
for(int i = 0; i < 256; i++)
|
for(int i = 0; i < 384; i++)
|
||||||
tilemap[i].create(8,8);
|
{
|
||||||
|
tiles[i].create(8,8,sf::Color::Red);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LCD::generate_tile(int idx)
|
||||||
|
{
|
||||||
|
std::cerr << "Updating tile " << idx << std::endl;
|
||||||
|
for(int y = 0, addr = idx << 4; y < 8; y++, addr+=2)
|
||||||
|
{
|
||||||
|
u8 a = vram_raw[addr];
|
||||||
|
u8 b = vram_raw[addr+1];
|
||||||
|
for(int x = 7; x >= 0; x--, a>>=1, b>>=1)
|
||||||
|
{
|
||||||
|
tiles[idx].setPixel(x,y,bgp.getColorByIdx( ((a&0x1) << 1) | (b&0x1)));
|
||||||
|
//tiles[idx].setPixel(x,y,sf::Color::Red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCD::vram_write(u16 addr, u8 data)
|
||||||
|
{
|
||||||
|
if (Range(0x8000, 0x97FF).contains(addr))
|
||||||
|
{
|
||||||
|
generate_tile((addr & 0x1FFF) >> 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LCD::write8(u16 addr, u8 data) {
|
void LCD::write8(u16 addr, u8 data) {
|
||||||
// VRAM access
|
// VRAM access
|
||||||
|
@ -23,6 +49,7 @@ void LCD::write8(u16 addr, u8 data) {
|
||||||
{
|
{
|
||||||
vram_raw[addr-0x8000] = data;
|
vram_raw[addr-0x8000] = data;
|
||||||
vram_dirty = true;
|
vram_dirty = true;
|
||||||
|
vram_write(addr, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,3 +142,20 @@ u8 LCD::read8(u16 addr) {
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LCD::render(sf::RenderTarget& target)
|
||||||
|
{
|
||||||
|
cpu.signalInterrupt(INT_VBlank);
|
||||||
|
for(int row = 0; row < 16; row++)
|
||||||
|
for(int col = 0; col < 12; col++)
|
||||||
|
{
|
||||||
|
unsigned int idx = row*12+col;
|
||||||
|
sf::Texture txt;
|
||||||
|
sf::Sprite spr;
|
||||||
|
|
||||||
|
txt.loadFromImage(tiles[idx]);
|
||||||
|
spr.setTexture(txt,true);
|
||||||
|
spr.setPosition(col*8,row*8);
|
||||||
|
target.draw(spr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class LCD : public Mem_device {
|
||||||
private:
|
private:
|
||||||
// Graphics
|
// Graphics
|
||||||
sf::RenderTexture screenbuffer;
|
sf::RenderTexture screenbuffer;
|
||||||
sf::Image tilemap[256];
|
sf::Image tiles[384];
|
||||||
|
|
||||||
// Emulated device
|
// Emulated device
|
||||||
u8 regLY;
|
u8 regLY;
|
||||||
|
@ -47,9 +47,13 @@ private:
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool vram_dirty;
|
bool vram_dirty;
|
||||||
|
|
||||||
|
void vram_write(u16 addr, u8 data);
|
||||||
|
void generate_tile(int idx);
|
||||||
public:
|
public:
|
||||||
LCD(Cpu& cpu);
|
LCD(Cpu& cpu);
|
||||||
|
|
||||||
virtual void write8(u16 addr, u8 data);
|
virtual void write8(u16 addr, u8 data);
|
||||||
virtual u8 read8(u16 addr);
|
virtual u8 read8(u16 addr);
|
||||||
|
|
||||||
|
void render(sf::RenderTarget& target);
|
||||||
};
|
};
|
||||||
|
|
93
lcd/lcdtest.cpp
Normal file
93
lcd/lcdtest.cpp
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
#include <cartridge/cartridge.h>
|
||||||
|
#include <cartridge/mbc/mbc1.h>
|
||||||
|
#include <memory/ram.h>
|
||||||
|
#include <memory/bus.h>
|
||||||
|
#include <memory/register.h>
|
||||||
|
#include <lcd/lcd.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if(argc < 2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
std::ifstream file(argv[1]);
|
||||||
|
Cartridge cart(file);
|
||||||
|
|
||||||
|
if(cart.type() != CT_MBC1 && cart.type() != CT_ROM_ONLY)
|
||||||
|
{
|
||||||
|
std::cerr << "Wrong cart type (" << (int)cart.type() << ")" << std::endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode(12*8,16*8), "VGBC tiles view");
|
||||||
|
|
||||||
|
RAM wram1(0x1000);
|
||||||
|
RAM wram2(0x1000);
|
||||||
|
RAM hram(0x100);
|
||||||
|
RAM oam(0x100);
|
||||||
|
|
||||||
|
MBC1 mbc1(cart);
|
||||||
|
|
||||||
|
Bus b;
|
||||||
|
Cpu cpu(&b);
|
||||||
|
|
||||||
|
LCD lcd(cpu);
|
||||||
|
|
||||||
|
b.map_device(0x0000, 0x7FFF, &mbc1);
|
||||||
|
b.map_device(0x8000, 0x9FFF, &lcd, 0x8000);
|
||||||
|
b.map_device(0xA000, 0xBFFF, &mbc1, 0xA000);
|
||||||
|
b.map_device(0xC000, 0xCFFF, &wram1);
|
||||||
|
b.map_device(0xD000, 0xDFFF, &wram2);
|
||||||
|
b.map_device(0xE000, 0xFDFF, &wram1);
|
||||||
|
b.map_device(0xFE00, 0xFE9F, &oam);
|
||||||
|
b.map_device(0xFF40, 0xFF4F, &lcd, 0xFF40);
|
||||||
|
b.map_device(0xFF80, 0xFFFE, &hram);
|
||||||
|
|
||||||
|
|
||||||
|
BoundRegister ie_mapped(cpu.state.IE);
|
||||||
|
BoundRegister if_mapped(cpu.state.IF);
|
||||||
|
b.map_device(0xFFFF, 0xFFFF, &ie_mapped);
|
||||||
|
b.map_device(0xFF0F, 0xFF0F, &if_mapped);
|
||||||
|
|
||||||
|
cpu.state.A = 0x1;
|
||||||
|
cpu.state.carry = true;
|
||||||
|
cpu.state.halfcarry = true;
|
||||||
|
cpu.state.subtract = false;
|
||||||
|
cpu.state.zero = true;
|
||||||
|
|
||||||
|
cpu.state.B = 0x00;
|
||||||
|
cpu.state.C = 0x13;
|
||||||
|
cpu.state.D = 0x00;
|
||||||
|
cpu.state.E = 0xD8;
|
||||||
|
cpu.state.H = 0x01;
|
||||||
|
cpu.state.L = 0x4D;
|
||||||
|
|
||||||
|
cpu.state.SP = 0xFFFE;
|
||||||
|
cpu.state.PC = 0x100;
|
||||||
|
|
||||||
|
const std::chrono::milliseconds delay(1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while(!cpu.state.stopped)
|
||||||
|
{
|
||||||
|
|
||||||
|
cpu.run(4194304/4000);
|
||||||
|
|
||||||
|
window.clear(sf::Color::Black);
|
||||||
|
lcd.render(window);
|
||||||
|
window.display();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(delay);
|
||||||
|
}
|
||||||
|
} catch(CpuException& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue