mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-11 17:29:57 +00:00
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:
parent
07d44966ac
commit
ea3f154989
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user