mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-09-30 06:58:08 +00:00
Move a fair amount of code from the GameBoy implementation into the EightBit library for the LR35902
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
9da58a5af7
commit
ea033d3984
27
LR35902/inc/AbstractColourPalette.h
Normal file
27
LR35902/inc/AbstractColourPalette.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
class AbstractColourPalette {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
Off,
|
||||||
|
Light,
|
||||||
|
Medium,
|
||||||
|
Dark
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractColourPalette::AbstractColourPalette()
|
||||||
|
: m_colours(4) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getColour(size_t index) const {
|
||||||
|
return m_colours[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<uint32_t> m_colours;
|
||||||
|
};
|
||||||
|
}
|
41
LR35902/inc/CharacterDefinition.h
Normal file
41
LR35902/inc/CharacterDefinition.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "Bus.h"
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
class CharacterDefinition {
|
||||||
|
public:
|
||||||
|
CharacterDefinition() {}
|
||||||
|
|
||||||
|
CharacterDefinition(Bus& bus, uint16_t address) {
|
||||||
|
|
||||||
|
for (auto row = 0; row < 8; ++row) {
|
||||||
|
|
||||||
|
auto planeAddress = address + row * 2;
|
||||||
|
|
||||||
|
auto planeLow = bus.peek(planeAddress);
|
||||||
|
auto planeHigh = bus.peek(planeAddress + 1);
|
||||||
|
|
||||||
|
for (int bit = 0; bit < 8; ++bit) {
|
||||||
|
|
||||||
|
auto mask = 1 << bit;
|
||||||
|
|
||||||
|
auto bitLow = planeLow & mask ? 1 : 0;
|
||||||
|
auto bitHigh = planeHigh & mask ? 0b10 : 0;
|
||||||
|
|
||||||
|
auto colour = bitHigh | bitLow;
|
||||||
|
|
||||||
|
m_definition[row * 8 + (7 - bit)] = colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<int, 8 * 8>& get() const { return m_definition; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<int, 8 * 8> m_definition;
|
||||||
|
};
|
||||||
|
}
|
33
LR35902/inc/Display.h
Normal file
33
LR35902/inc/Display.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "Bus.h"
|
||||||
|
#include "AbstractColourPalette.h"
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
class Display {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
BufferWidth = 256,
|
||||||
|
BufferHeight = 256,
|
||||||
|
BufferCharacterWidth = BufferWidth / 8,
|
||||||
|
BufferCharacterHeight = BufferHeight / 8,
|
||||||
|
RasterWidth = 160,
|
||||||
|
RasterHeight = 144,
|
||||||
|
};
|
||||||
|
|
||||||
|
Display(const AbstractColourPalette* colours, Bus& bus);
|
||||||
|
|
||||||
|
const std::vector<uint32_t>& pixels() const;
|
||||||
|
|
||||||
|
void initialise();
|
||||||
|
void render();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint32_t> m_pixels;
|
||||||
|
Bus& m_bus;
|
||||||
|
const AbstractColourPalette* m_colours;
|
||||||
|
};
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
#include "IntelProcessor.h"
|
#include "IntelProcessor.h"
|
||||||
#include "Bus.h"
|
#include "Bus.h"
|
||||||
#include "Signal.h"
|
#include "Signal.h"
|
||||||
|
#include "Display.h"
|
||||||
|
|
||||||
namespace EightBit {
|
namespace EightBit {
|
||||||
class LR35902 : public IntelProcessor {
|
class LR35902 : public IntelProcessor {
|
||||||
@ -29,10 +30,6 @@ namespace EightBit {
|
|||||||
void di();
|
void di();
|
||||||
void ei();
|
void ei();
|
||||||
|
|
||||||
int run(int limit);
|
|
||||||
virtual int execute(uint8_t opcode);
|
|
||||||
int step();
|
|
||||||
|
|
||||||
virtual register16_t& AF() override {
|
virtual register16_t& AF() override {
|
||||||
af.low &= 0xf0;
|
af.low &= 0xf0;
|
||||||
return af;
|
return af;
|
||||||
@ -53,6 +50,30 @@ namespace EightBit {
|
|||||||
virtual void reset();
|
virtual void reset();
|
||||||
virtual void initialise();
|
virtual void initialise();
|
||||||
|
|
||||||
|
static int framesPerSecond() { return 60; }
|
||||||
|
static int cyclesPerFrame() { return cyclesPerSecond() / framesPerSecond(); }
|
||||||
|
|
||||||
|
int runRasterLines() {
|
||||||
|
m_bus.resetLY();
|
||||||
|
int cycles = 0;
|
||||||
|
for (int line = 0; line < Display::RasterHeight; ++line)
|
||||||
|
cycles += runRasterLine();
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int runVerticalBlankLines() {
|
||||||
|
m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank);
|
||||||
|
int cycles = 0;
|
||||||
|
for (int line = 0; line < (Bus::TotalLineCount - Display::RasterHeight); ++line)
|
||||||
|
cycles += runRasterLine();
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int run(int limit);
|
||||||
|
virtual int execute(uint8_t opcode);
|
||||||
|
int step();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Bus& m_bus;
|
Bus& m_bus;
|
||||||
|
|
||||||
@ -67,6 +88,17 @@ namespace EightBit {
|
|||||||
|
|
||||||
bool m_stopped;
|
bool m_stopped;
|
||||||
|
|
||||||
|
static int cyclesPerSecond() { return 4 * 1024 * 1024; }
|
||||||
|
static int cyclesPerLine() { return cyclesPerFrame() / Bus::TotalLineCount; }
|
||||||
|
|
||||||
|
int runRasterLine() {
|
||||||
|
auto cycles = run(cyclesPerLine());
|
||||||
|
m_bus.incrementLY();
|
||||||
|
if ((m_bus.peekRegister(Bus::STAT) & Processor::Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY)))
|
||||||
|
m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus);
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t R(int r, uint8_t& a) {
|
uint8_t R(int r, uint8_t& a) {
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 0:
|
case 0:
|
||||||
|
86
LR35902/src/Display.cpp
Normal file
86
LR35902/src/Display.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Display.h"
|
||||||
|
#include "Processor.h"
|
||||||
|
#include "CharacterDefinition.h"
|
||||||
|
|
||||||
|
EightBit::Display::Display(const AbstractColourPalette* colours, Bus& bus)
|
||||||
|
: m_bus(bus),
|
||||||
|
m_colours(colours) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint32_t>& EightBit::Display::pixels() const {
|
||||||
|
return m_pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Display::initialise() {
|
||||||
|
m_pixels.resize(RasterWidth * RasterHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Display::render() {
|
||||||
|
|
||||||
|
auto control = m_bus.peekRegister(Bus::LCDC);
|
||||||
|
auto on = control & Bus::LcdEnable;
|
||||||
|
if (on) {
|
||||||
|
|
||||||
|
auto windowArea = (control & Bus::WindowCodeAreaSelection) ? 0x9c00 : 0x9800;
|
||||||
|
auto window = (control & Bus::WindowEnable) != 0;
|
||||||
|
auto bgCharacters = (control & Bus::BackgroundCharacterDataSelection) ? 0x8000 : 0x8800;
|
||||||
|
auto bgArea = (control & Bus::BackgroundCodeAreaSelection) ? 0x9c00 : 0x9800;
|
||||||
|
auto objBlockHeight = (control & Bus::ObjectBlockCompositionSelection) ? 16 : 8;
|
||||||
|
auto objEnable = (control & Bus::ObjectEnable) != 0;
|
||||||
|
auto bgDisplay = (control & Bus::DisplayBackground) != 0;
|
||||||
|
|
||||||
|
auto scrollX = m_bus.peekRegister(Bus::SCX);
|
||||||
|
auto scrollY = m_bus.peekRegister(Bus::SCY);
|
||||||
|
|
||||||
|
auto paletteRaw = m_bus.peekRegister(Bus::BGP);
|
||||||
|
std::array<int, 4> palette;
|
||||||
|
palette[0] = paletteRaw & 0b11;
|
||||||
|
palette[1] = (paletteRaw & 0b1100) >> 2;
|
||||||
|
palette[2] = (paletteRaw & 0b110000) >> 4;
|
||||||
|
palette[3] = (paletteRaw & 0b11000000) >> 6;
|
||||||
|
|
||||||
|
auto wx = m_bus.peekRegister(Bus::WX);
|
||||||
|
auto wy = m_bus.peekRegister(Bus::WY);
|
||||||
|
|
||||||
|
auto offsetX = window ? wx - 7 : 0;
|
||||||
|
auto offsetY = window ? wy : 0;
|
||||||
|
|
||||||
|
std::map<int, CharacterDefinition> definitions;
|
||||||
|
|
||||||
|
for (int row = 0; row < BufferCharacterHeight; ++row) {
|
||||||
|
for (int column = 0; column < BufferCharacterWidth; ++column) {
|
||||||
|
|
||||||
|
auto address = bgArea + row * BufferCharacterWidth + column;
|
||||||
|
auto character = m_bus.peek(address);
|
||||||
|
|
||||||
|
auto definitionPair = definitions.find(character);
|
||||||
|
|
||||||
|
if (definitionPair == definitions.end()) {
|
||||||
|
definitions[character] = CharacterDefinition(m_bus, bgCharacters + 16 * character);
|
||||||
|
definitionPair = definitions.find(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto definition = definitionPair->second;
|
||||||
|
|
||||||
|
for (int cy = 0; cy < 8; ++cy) {
|
||||||
|
for (int cx = 0; cx < 8; ++cx) {
|
||||||
|
|
||||||
|
uint8_t x = column * 8 + cx + offsetX - scrollX;
|
||||||
|
if (x >= RasterWidth)
|
||||||
|
break;
|
||||||
|
|
||||||
|
uint8_t y = row * 8 + cy + offsetY - scrollY;
|
||||||
|
if (y >= RasterHeight)
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto outputPixel = y * RasterWidth + x;
|
||||||
|
|
||||||
|
auto colour = palette[definition.get()[cy * 8 + cx]];
|
||||||
|
m_pixels[outputPixel] = m_colours->getColour(colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -139,8 +139,11 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\inc\AbstractColourPalette.h" />
|
||||||
<ClInclude Include="..\inc\Bus.h" />
|
<ClInclude Include="..\inc\Bus.h" />
|
||||||
|
<ClInclude Include="..\inc\CharacterDefinition.h" />
|
||||||
<ClInclude Include="..\inc\Disassembler.h" />
|
<ClInclude Include="..\inc\Disassembler.h" />
|
||||||
|
<ClInclude Include="..\inc\Display.h" />
|
||||||
<ClInclude Include="..\inc\LR35902.h" />
|
<ClInclude Include="..\inc\LR35902.h" />
|
||||||
<ClInclude Include="..\inc\Profiler.h" />
|
<ClInclude Include="..\inc\Profiler.h" />
|
||||||
<ClInclude Include="stdafx.h" />
|
<ClInclude Include="stdafx.h" />
|
||||||
@ -148,6 +151,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Bus.cpp" />
|
<ClCompile Include="Bus.cpp" />
|
||||||
<ClCompile Include="Disassembler.cpp" />
|
<ClCompile Include="Disassembler.cpp" />
|
||||||
|
<ClCompile Include="Display.cpp" />
|
||||||
<ClCompile Include="LR35902.cpp" />
|
<ClCompile Include="LR35902.cpp" />
|
||||||
<ClCompile Include="Profiler.cpp" />
|
<ClCompile Include="Profiler.cpp" />
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
@ -26,6 +26,15 @@
|
|||||||
<ClInclude Include="..\inc\Bus.h">
|
<ClInclude Include="..\inc\Bus.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\CharacterDefinition.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\AbstractColourPalette.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\Display.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
@ -43,5 +52,8 @@
|
|||||||
<ClCompile Include="Bus.cpp">
|
<ClCompile Include="Bus.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Display.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user