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:
Adrian.Conlon 2017-08-29 22:23:32 +01:00
parent 9da58a5af7
commit ea033d3984
7 changed files with 239 additions and 4 deletions

View 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;
};
}

View 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
View 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;
};
}

View File

@ -5,6 +5,7 @@
#include "IntelProcessor.h"
#include "Bus.h"
#include "Signal.h"
#include "Display.h"
namespace EightBit {
class LR35902 : public IntelProcessor {
@ -29,10 +30,6 @@ namespace EightBit {
void di();
void ei();
int run(int limit);
virtual int execute(uint8_t opcode);
int step();
virtual register16_t& AF() override {
af.low &= 0xf0;
return af;
@ -53,6 +50,30 @@ namespace EightBit {
virtual void reset();
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:
Bus& m_bus;
@ -67,6 +88,17 @@ namespace EightBit {
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) {
switch (r) {
case 0:

86
LR35902/src/Display.cpp Normal file
View 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);
}
}
}
}
}
}

View File

@ -139,8 +139,11 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\inc\AbstractColourPalette.h" />
<ClInclude Include="..\inc\Bus.h" />
<ClInclude Include="..\inc\CharacterDefinition.h" />
<ClInclude Include="..\inc\Disassembler.h" />
<ClInclude Include="..\inc\Display.h" />
<ClInclude Include="..\inc\LR35902.h" />
<ClInclude Include="..\inc\Profiler.h" />
<ClInclude Include="stdafx.h" />
@ -148,6 +151,7 @@
<ItemGroup>
<ClCompile Include="Bus.cpp" />
<ClCompile Include="Disassembler.cpp" />
<ClCompile Include="Display.cpp" />
<ClCompile Include="LR35902.cpp" />
<ClCompile Include="Profiler.cpp" />
<ClCompile Include="stdafx.cpp">

View File

@ -26,6 +26,15 @@
<ClInclude Include="..\inc\Bus.h">
<Filter>Header Files</Filter>
</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>
<ClCompile Include="stdafx.cpp">
@ -43,5 +52,8 @@
<ClCompile Include="Bus.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Display.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>