Preliminary support for 16 row high sprites. Don't think it's working!

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-09-17 09:46:28 +01:00
parent 07d44966ac
commit ea3f154989
4 changed files with 37 additions and 26 deletions

View File

@ -1,7 +1,7 @@
#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <Bus.h>
@ -11,16 +11,20 @@ namespace EightBit {
public:
CharacterDefinition() {}
CharacterDefinition(Bus& bus, uint16_t address) {
CharacterDefinition(Bus& bus, uint16_t address, int height) {
for (auto row = 0; row < 8; ++row) {
const int width = 8;
m_definition.resize(width * height);
for (auto row = 0; row < height; ++row) {
auto planeAddress = address + row * 2;
auto planeLow = bus.peek(planeAddress);
auto planeHigh = bus.peek(planeAddress + 1);
for (int bit = 0; bit < 8; ++bit) {
for (int bit = 0; bit < width; ++bit) {
auto mask = 1 << bit;
@ -29,15 +33,15 @@ namespace EightBit {
auto colour = bitHigh | bitLow;
m_definition[row * 8 + (7 - bit)] = colour;
m_definition[row * width + ((width - 1) - bit)] = colour;
}
}
}
const std::array<int, 8 * 8>& get() const { return m_definition; }
const std::vector<int>& get() const { return m_definition; }
private:
std::array<int, 8 * 8> m_definition;
std::vector<int> m_definition;
};
}
}

View File

@ -48,6 +48,7 @@ namespace EightBit {
void renderObjects(int objBlockHeight);
void renderTile(
int height,
int drawX, int drawY, int offsetX, int offsetY,
bool flipX, bool flipY, bool allowTransparencies,
const std::array<int, 4>& palette,

View File

@ -22,15 +22,12 @@ void EightBit::GameBoy::Display::initialise() {
void EightBit::GameBoy::Display::render() {
auto control = m_bus.peekRegister(Bus::LCDC);
auto on = control & Bus::LcdEnable;
if (on) {
if (control & Bus::LcdEnable) {
const auto bgDisplay = (control & Bus::DisplayBackground) != 0;
if (bgDisplay)
if (control & Bus::DisplayBackground)
renderBackground();
const auto objEnable = (control & Bus::ObjectEnable) != 0;
if (objEnable)
if (control & Bus::ObjectEnable)
renderObjects();
}
}
@ -64,7 +61,7 @@ void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) {
const auto current = ObjectAttribute(m_bus, oamAddress + 4 * i, objBlockHeight);
const auto sprite = current.pattern();
const auto definition = CharacterDefinition(m_bus, objDefinitionAddress + 16 * sprite);
const auto definition = CharacterDefinition(m_bus, objDefinitionAddress + 16 * sprite, objBlockHeight);
const auto spriteX = current.positionX();
const auto spriteY = current.positionY();
const auto& palette = palettes[current.palette()];
@ -72,6 +69,7 @@ void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) {
const auto flipY = current.flipY();
renderTile(
objBlockHeight,
spriteX, spriteY, -8, -16,
flipX, flipY, true,
palette,
@ -118,13 +116,14 @@ void EightBit::GameBoy::Display::renderBackground(
auto definitionPair = definitions.find(character);
if (definitionPair == definitions.end()) {
definitions[character] = CharacterDefinition(m_bus, bgCharacters + 16 * character);
definitions[character] = CharacterDefinition(m_bus, bgCharacters + 16 * character, 8);
definitionPair = definitions.find(character);
}
auto definition = definitionPair->second;
renderTile(
8,
column * 8, row * 8, offsetX - scrollX, offsetY - scrollY,
false, false, false,
palette,
@ -134,26 +133,29 @@ void EightBit::GameBoy::Display::renderBackground(
}
void EightBit::GameBoy::Display::renderTile(
int height,
int drawX, int drawY, int offsetX, int offsetY,
bool flipX, bool flipY, bool allowTransparencies,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) {
for (int cy = 0; cy < 8; ++cy) {
const auto width = 8;
for (int cx = 0; cx < 8; ++cx) {
for (int cy = 0; cy < height; ++cy) {
uint8_t y = drawY + (flipY ? 7 - cy : cy) + offsetY;
for (int cx = 0; cx < width; ++cx) {
uint8_t y = drawY + (flipY ? (height - 1) - cy : cy) + offsetY;
if (y >= RasterHeight)
break;
uint8_t x = drawX + (flipX ? 7 - cx : cx) + offsetX;
uint8_t x = drawX + (flipX ? (width - 1) - cx : cx) + offsetX;
if (x >= RasterWidth)
break;
auto outputPixel = y * RasterWidth + x;
auto colour = definition.get()[cy * 8 + cx];
auto colour = definition.get()[cy * width + cx];
if (!allowTransparencies || (allowTransparencies && (colour > 0)))
m_pixels[outputPixel] = m_colours->getColour(palette[colour]);
}

View File

@ -337,16 +337,20 @@ int EightBit::GameBoy::LR35902::runRasterLines(int limit) {
int EightBit::GameBoy::LR35902::runRasterLine() {
const auto count = run(cyclesPerLine());
m_bus.updateLcdStatusMode(Bus::LcdStatusMode::HBlank);
m_bus.incrementLY();
if ((m_bus.peekRegister(Bus::STAT) & Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY)))
m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus);
if (m_bus.peekRegister(Bus::LCDC) & Bus::LcdEnable) {
m_bus.updateLcdStatusMode(Bus::LcdStatusMode::HBlank);
m_bus.incrementLY();
if ((m_bus.peekRegister(Bus::STAT) & Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY)))
m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus);
}
return count;
}
int EightBit::GameBoy::LR35902::runVerticalBlankLines() {
m_bus.updateLcdStatusMode(Bus::LcdStatusMode::VBlank);
m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank);
if (m_bus.peekRegister(Bus::LCDC) & Bus::LcdEnable) {
m_bus.updateLcdStatusMode(Bus::LcdStatusMode::VBlank);
m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank);
}
return runRasterLines(Bus::TotalLineCount - Display::RasterHeight);
}