From ea3f15498995dc6481a2d5f03b8a4a5e1e90dec4 Mon Sep 17 00:00:00 2001
From: "Adrian.Conlon" <adrian.conlon@gmail.com>
Date: Sun, 17 Sep 2017 09:46:28 +0100
Subject: [PATCH] Preliminary support for 16 row high sprites.  Don't think
 it's working!

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
---
 LR35902/inc/CharacterDefinition.h | 18 +++++++++++-------
 LR35902/inc/Display.h             |  1 +
 LR35902/src/Display.cpp           | 28 +++++++++++++++-------------
 LR35902/src/LR35902.cpp           | 16 ++++++++++------
 4 files changed, 37 insertions(+), 26 deletions(-)

diff --git a/LR35902/inc/CharacterDefinition.h b/LR35902/inc/CharacterDefinition.h
index da227a7..ed558a2 100644
--- a/LR35902/inc/CharacterDefinition.h
+++ b/LR35902/inc/CharacterDefinition.h
@@ -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;
 		};
 	}
 }
\ No newline at end of file
diff --git a/LR35902/inc/Display.h b/LR35902/inc/Display.h
index b9467d4..49335b5 100644
--- a/LR35902/inc/Display.h
+++ b/LR35902/inc/Display.h
@@ -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,
diff --git a/LR35902/src/Display.cpp b/LR35902/src/Display.cpp
index 3862530..43066a3 100644
--- a/LR35902/src/Display.cpp
+++ b/LR35902/src/Display.cpp
@@ -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]);
 		}
diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp
index 7628443..8103606 100644
--- a/LR35902/src/LR35902.cpp
+++ b/LR35902/src/LR35902.cpp
@@ -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);
 }