mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-23 00:29:47 +00:00
GameBoy: Correct a few (very minor C++) niggles in the implementation. No functional changes.
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
33dd479421
commit
759b4a9fa8
@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace EightBit {
|
namespace EightBit {
|
||||||
namespace GameBoy {
|
namespace GameBoy {
|
||||||
@ -14,16 +15,15 @@ namespace EightBit {
|
|||||||
Dark
|
Dark
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractColourPalette() noexcept
|
AbstractColourPalette() = default;
|
||||||
: m_colours(4) {
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getColour(size_t index) const {
|
[[nodiscard]] auto colour(size_t index) const noexcept {
|
||||||
|
assert(index < m_colours.size());
|
||||||
return m_colours[index];
|
return m_colours[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<uint32_t> m_colours;
|
std::array<uint32_t, 4> m_colours;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ namespace EightBit {
|
|||||||
public:
|
public:
|
||||||
CharacterDefinition(Ram& vram, uint16_t address);
|
CharacterDefinition(Ram& vram, uint16_t address);
|
||||||
|
|
||||||
std::array<int, 8> get(int row);
|
[[nodiscard]] std::array<int, 8> get(int row) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ram& m_vram;
|
Ram& m_vram;
|
||||||
|
@ -20,7 +20,7 @@ namespace EightBit {
|
|||||||
static std::string state(LR35902& cpu);
|
static std::string state(LR35902& cpu);
|
||||||
std::string disassemble(LR35902& cpu);
|
std::string disassemble(LR35902& cpu);
|
||||||
|
|
||||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
static std::string flag(uint8_t value, int flag, std::string represents);
|
||||||
static std::string flags(uint8_t value);
|
static std::string flags(uint8_t value);
|
||||||
static std::string hex(uint8_t value);
|
static std::string hex(uint8_t value);
|
||||||
static std::string hex(uint16_t value);
|
static std::string hex(uint16_t value);
|
||||||
@ -70,7 +70,7 @@ namespace EightBit {
|
|||||||
static std::string cc(int flag);
|
static std::string cc(int flag);
|
||||||
static std::string alu(int which);
|
static std::string alu(int which);
|
||||||
|
|
||||||
Bus& BUS() { return m_bus; }
|
Bus& BUS() noexcept { return m_bus; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,9 +29,9 @@ namespace EightBit {
|
|||||||
|
|
||||||
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram);
|
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram);
|
||||||
|
|
||||||
const std::array<uint32_t, PixelCount>& pixels() const;
|
[[nodiscard]] const auto& pixels() const noexcept { return m_pixels; }
|
||||||
|
|
||||||
void render();
|
void renderCurrentScanline();
|
||||||
void loadObjectAttributes();
|
void loadObjectAttributes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -48,7 +48,7 @@ namespace EightBit {
|
|||||||
uint8_t m_control = 0;
|
uint8_t m_control = 0;
|
||||||
uint8_t m_scanLine = 0;
|
uint8_t m_scanLine = 0;
|
||||||
|
|
||||||
std::array<int, 4> createPalette(int address);
|
[[nodiscard]] std::array<int, 4> createPalette(int address);
|
||||||
|
|
||||||
void renderBackground();
|
void renderBackground();
|
||||||
void renderBackground(
|
void renderBackground(
|
||||||
@ -59,12 +59,24 @@ namespace EightBit {
|
|||||||
|
|
||||||
void renderObjects();
|
void renderObjects();
|
||||||
|
|
||||||
|
void renderSpriteTile(
|
||||||
|
int height,
|
||||||
|
int drawX, int drawY,
|
||||||
|
bool flipX, bool flipY,
|
||||||
|
const std::array<int, 4>& palette,
|
||||||
|
const CharacterDefinition& definition);
|
||||||
|
|
||||||
|
void renderBackgroundTile(
|
||||||
|
int drawX, int drawY,
|
||||||
|
const std::array<int, 4>& palette,
|
||||||
|
const CharacterDefinition& definition);
|
||||||
|
|
||||||
void renderTile(
|
void renderTile(
|
||||||
int height,
|
int height,
|
||||||
int drawX, int drawY,
|
int drawX, int drawY,
|
||||||
bool flipX, bool flipY, bool allowTransparencies,
|
bool flipX, bool flipY, bool allowTransparencies,
|
||||||
const std::array<int, 4>& palette,
|
const std::array<int, 4>& palette,
|
||||||
CharacterDefinition& definition);
|
const CharacterDefinition& definition);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,21 +39,21 @@ namespace EightBit {
|
|||||||
virtual void raisePOWER() override;
|
virtual void raisePOWER() override;
|
||||||
virtual void lowerPOWER() override;
|
virtual void lowerPOWER() override;
|
||||||
|
|
||||||
auto& CPU() { return m_cpu; }
|
[[nodiscard]] auto& CPU() noexcept { return m_cpu; }
|
||||||
auto& VRAM() { return m_videoRam; }
|
[[nodiscard]] auto& VRAM() noexcept { return m_videoRam; }
|
||||||
auto& OAMRAM() { return m_oamRam; }
|
[[nodiscard]] auto& OAMRAM() noexcept { return m_oamRam; }
|
||||||
auto& IO() { return m_ioPorts; }
|
[[nodiscard]] auto& IO() noexcept { return m_ioPorts; }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void disableGameRom() { m_disableGameRom = true; }
|
void disableGameRom() noexcept { m_disableGameRom = true; }
|
||||||
void enableGameRom() { m_disableGameRom = false; }
|
void enableGameRom() noexcept { m_disableGameRom = false; }
|
||||||
|
|
||||||
bool gameRomDisabled() const { return m_disableGameRom; }
|
[[nodiscard]] bool gameRomDisabled() const noexcept { return m_disableGameRom; }
|
||||||
bool gameRomEnabled() const { return !gameRomDisabled(); }
|
[[nodiscard]] bool gameRomEnabled() const noexcept { return !gameRomDisabled(); }
|
||||||
|
|
||||||
void loadBootRom(const std::string& path);
|
void loadBootRom(std::string path);
|
||||||
void loadGameRom(const std::string& path);
|
void loadGameRom(std::string path);
|
||||||
|
|
||||||
void runRasterLines();
|
void runRasterLines();
|
||||||
void runVerticalBlankLines();
|
void runVerticalBlankLines();
|
||||||
|
@ -133,35 +133,35 @@ namespace EightBit {
|
|||||||
|
|
||||||
void updateLcdStatusMode(int mode);
|
void updateLcdStatusMode(int mode);
|
||||||
|
|
||||||
void disableBootRom() { m_disableBootRom = true; }
|
void disableBootRom() noexcept { m_disableBootRom = true; }
|
||||||
void enableBootRom() { m_disableBootRom = false; }
|
void enableBootRom() noexcept { m_disableBootRom = false; }
|
||||||
|
|
||||||
auto bootRomDisabled() const { return m_disableBootRom; }
|
auto bootRomDisabled() const noexcept { return m_disableBootRom; }
|
||||||
auto bootRomEnabled() const { return !bootRomDisabled(); }
|
auto bootRomEnabled() const noexcept { return !bootRomDisabled(); }
|
||||||
|
|
||||||
void pressRight() { m_p14 = m_p10 = false; triggerKeypadInterrupt(); }
|
void pressRight() { m_p14 = m_p10 = false; triggerKeypadInterrupt(); }
|
||||||
void releaseRight() { m_p14 = m_p10 = true; }
|
void releaseRight() noexcept { m_p14 = m_p10 = true; }
|
||||||
|
|
||||||
void pressLeft() { m_p14 = m_p11 = false, triggerKeypadInterrupt(); }
|
void pressLeft() { m_p14 = m_p11 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseLeft() { m_p14 = m_p11 = true; }
|
void releaseLeft() noexcept { m_p14 = m_p11 = true; }
|
||||||
|
|
||||||
void pressUp() { m_p14 = m_p12 = false, triggerKeypadInterrupt(); }
|
void pressUp() { m_p14 = m_p12 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseUp() { m_p14 = m_p12 = true; }
|
void releaseUp() noexcept { m_p14 = m_p12 = true; }
|
||||||
|
|
||||||
void pressDown() { m_p14 = m_p13 = false, triggerKeypadInterrupt(); }
|
void pressDown() { m_p14 = m_p13 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseDown() { m_p14 = m_p13 = true; }
|
void releaseDown() noexcept { m_p14 = m_p13 = true; }
|
||||||
|
|
||||||
void pressA() { m_p15 = m_p10 = false, triggerKeypadInterrupt(); }
|
void pressA() { m_p15 = m_p10 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseA() { m_p15 = m_p10 = true; }
|
void releaseA() noexcept { m_p15 = m_p10 = true; }
|
||||||
|
|
||||||
void pressB() { m_p15 = m_p11 = false, triggerKeypadInterrupt(); }
|
void pressB() { m_p15 = m_p11 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseB() { m_p15 = m_p11 = true; }
|
void releaseB() noexcept { m_p15 = m_p11 = true; }
|
||||||
|
|
||||||
void pressSelect() { m_p15 = m_p12 = false, triggerKeypadInterrupt(); }
|
void pressSelect() { m_p15 = m_p12 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseSelect() { m_p15 = m_p12 = true; }
|
void releaseSelect() noexcept { m_p15 = m_p12 = true; }
|
||||||
|
|
||||||
void pressStart() { m_p15 = m_p13 = false, triggerKeypadInterrupt(); }
|
void pressStart() { m_p15 = m_p13 = false, triggerKeypadInterrupt(); }
|
||||||
void releaseStart() { m_p15 = m_p13 = true; }
|
void releaseStart() noexcept { m_p15 = m_p13 = true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Bus& m_bus;
|
Bus& m_bus;
|
||||||
|
@ -26,7 +26,7 @@ namespace EightBit {
|
|||||||
Signal<LR35902> ExecutingInstruction;
|
Signal<LR35902> ExecutingInstruction;
|
||||||
Signal<LR35902> ExecutedInstruction;
|
Signal<LR35902> ExecutedInstruction;
|
||||||
|
|
||||||
auto clockCycles() const {
|
[[nodiscard]] auto clockCycles() const noexcept {
|
||||||
return cycles() * 4;
|
return cycles() * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +35,8 @@ namespace EightBit {
|
|||||||
virtual register16_t& DE() final;
|
virtual register16_t& DE() final;
|
||||||
virtual register16_t& HL() final;
|
virtual register16_t& HL() final;
|
||||||
|
|
||||||
|
uint8_t maskedInterrupts();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int execute() final;
|
virtual int execute() final;
|
||||||
virtual int step() final;
|
virtual int step() final;
|
||||||
@ -55,7 +57,7 @@ namespace EightBit {
|
|||||||
|
|
||||||
bool m_prefixCB = false;
|
bool m_prefixCB = false;
|
||||||
|
|
||||||
bool& IME() { return m_ime; }
|
bool& IME() noexcept { return m_ime; }
|
||||||
|
|
||||||
auto R(const int r) {
|
auto R(const int r) {
|
||||||
ASSUME(r >= 0);
|
ASSUME(r >= 0);
|
||||||
@ -165,9 +167,9 @@ namespace EightBit {
|
|||||||
void increment(uint8_t& operand);
|
void increment(uint8_t& operand);
|
||||||
void decrement(uint8_t& operand);
|
void decrement(uint8_t& operand);
|
||||||
|
|
||||||
void stop() { m_stopped = true; }
|
void stop(bool value = true) noexcept { m_stopped = value; }
|
||||||
void start() { m_stopped = false; }
|
void start() noexcept { stop(false); }
|
||||||
bool stopped() const { return m_stopped; }
|
bool stopped() const noexcept { return m_stopped; }
|
||||||
|
|
||||||
void di();
|
void di();
|
||||||
void ei();
|
void ei();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <Processor.h>
|
#include <Chip.h>
|
||||||
|
|
||||||
namespace EightBit {
|
namespace EightBit {
|
||||||
|
|
||||||
@ -14,18 +14,18 @@ namespace EightBit {
|
|||||||
ObjectAttribute() = default;
|
ObjectAttribute() = default;
|
||||||
ObjectAttribute(Ram& ram, uint16_t address);
|
ObjectAttribute(Ram& ram, uint16_t address);
|
||||||
|
|
||||||
auto positionY() const { return m_positionY; }
|
[[nodiscard]] auto positionY() const noexcept { return m_positionY; }
|
||||||
auto positionX() const { return m_positionX; }
|
[[nodiscard]] auto positionX() const noexcept { return m_positionX; }
|
||||||
auto pattern() const { return m_pattern; }
|
[[nodiscard]] auto pattern() const noexcept { return m_pattern; }
|
||||||
auto flags() const { return m_flags; }
|
[[nodiscard]] auto flags() const noexcept { return m_flags; }
|
||||||
|
|
||||||
auto priority() const { return flags() & Chip::Bit7; }
|
[[nodiscard]] auto priority() const noexcept { return flags() & Chip::Bit7; }
|
||||||
|
|
||||||
auto highPriority() const { return !!priority(); }
|
[[nodiscard]] auto highPriority() const noexcept { return !!priority(); }
|
||||||
auto lowPriority() const { return !priority(); }
|
[[nodiscard]] auto lowPriority() const noexcept { return !priority(); }
|
||||||
auto flipY() const { return !!(flags() & Chip::Bit6); }
|
[[nodiscard]] auto flipY() const noexcept { return !!(flags() & Chip::Bit6); }
|
||||||
auto flipX() const { return !!(flags() & Chip::Bit5); }
|
[[nodiscard]] auto flipX() const noexcept { return !!(flags() & Chip::Bit5); }
|
||||||
auto palette() const { return (flags() & Chip::Bit4) >> 4; }
|
[[nodiscard]] auto palette() const noexcept { return (flags() & Chip::Bit4) >> 4; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t m_positionY;
|
uint8_t m_positionY;
|
||||||
|
@ -8,7 +8,7 @@ EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uin
|
|||||||
m_address(address) {
|
m_address(address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) {
|
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const {
|
||||||
|
|
||||||
std::array<int, 8> returned;
|
std::array<int, 8> returned;
|
||||||
|
|
||||||
@ -26,7 +26,8 @@ std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) {
|
|||||||
|
|
||||||
const auto colour = bitHigh | bitLow;
|
const auto colour = bitHigh | bitLow;
|
||||||
|
|
||||||
returned[7 - bit] = colour;
|
const auto index = 7 - bit;
|
||||||
|
returned[index] = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returned;
|
return returned;
|
||||||
|
@ -525,7 +525,7 @@ void EightBit::GameBoy::Disassembler::disassembleOther(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EightBit::GameBoy::Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
std::string EightBit::GameBoy::Disassembler::flag(uint8_t value, int flag, const std::string represents) {
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
output << (value & flag ? represents : "-");
|
output << (value & flag ? represents : "-");
|
||||||
return output.str();
|
return output.str();
|
||||||
|
@ -14,20 +14,15 @@ EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& b
|
|||||||
m_colours(colours) {
|
m_colours(colours) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::array<uint32_t, EightBit::GameBoy::Display::PixelCount>& EightBit::GameBoy::Display::pixels() const {
|
void EightBit::GameBoy::Display::renderCurrentScanline() {
|
||||||
return m_pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EightBit::GameBoy::Display::render() {
|
|
||||||
m_scanLine = m_bus.IO().peek(IoRegisters::LY);
|
m_scanLine = m_bus.IO().peek(IoRegisters::LY);
|
||||||
if (m_scanLine < RasterHeight) {
|
if (m_scanLine < RasterHeight) {
|
||||||
m_control = m_bus.IO().peek(IoRegisters::LCDC);
|
m_control = m_bus.IO().peek(IoRegisters::LCDC);
|
||||||
if (m_control & IoRegisters::LCD_EN) {
|
assert(m_control & IoRegisters::LCD_EN);
|
||||||
if (m_control & IoRegisters::BG_EN)
|
if (m_control & IoRegisters::BG_EN)
|
||||||
renderBackground();
|
renderBackground();
|
||||||
if (m_control & IoRegisters::OBJ_EN)
|
if (m_control & IoRegisters::OBJ_EN)
|
||||||
renderObjects();
|
renderObjects();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,15 +66,15 @@ void EightBit::GameBoy::Display::renderObjects() {
|
|||||||
const auto drawX = spriteX - 8;
|
const auto drawX = spriteX - 8;
|
||||||
|
|
||||||
const auto sprite = current.pattern();
|
const auto sprite = current.pattern();
|
||||||
auto definition = CharacterDefinition(m_vram, characterAddressMultiplier * sprite);
|
const auto definition = CharacterDefinition(m_vram, characterAddressMultiplier * sprite);
|
||||||
const auto& palette = palettes[current.palette()];
|
const auto& palette = palettes[current.palette()];
|
||||||
const auto flipX = current.flipX();
|
const auto flipX = current.flipX();
|
||||||
const auto flipY = current.flipY();
|
const auto flipY = current.flipY();
|
||||||
|
|
||||||
renderTile(
|
renderSpriteTile(
|
||||||
objBlockHeight,
|
objBlockHeight,
|
||||||
drawX, drawY,
|
drawX, drawY,
|
||||||
flipX, flipY, true,
|
flipX, flipY,
|
||||||
palette,
|
palette,
|
||||||
definition);
|
definition);
|
||||||
}
|
}
|
||||||
@ -120,22 +115,46 @@ void EightBit::GameBoy::Display::renderBackground(
|
|||||||
const auto character = m_vram.peek(address++);
|
const auto character = m_vram.peek(address++);
|
||||||
|
|
||||||
const auto definitionOffset = offsetType == tile_offset_t::Signed ? 16 * (int8_t)character : 16 * character;
|
const auto definitionOffset = offsetType == tile_offset_t::Signed ? 16 * (int8_t)character : 16 * character;
|
||||||
auto definition = CharacterDefinition(m_vram, bgCharacters + definitionOffset);
|
const auto definition = CharacterDefinition(m_vram, bgCharacters + definitionOffset);
|
||||||
renderTile(
|
renderBackgroundTile(
|
||||||
8,
|
|
||||||
column * 8 + offsetX, row * 8 + offsetY,
|
column * 8 + offsetX, row * 8 + offsetY,
|
||||||
false, false, false,
|
|
||||||
palette,
|
palette,
|
||||||
definition);
|
definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EightBit::GameBoy::Display::renderSpriteTile(
|
||||||
|
const int height,
|
||||||
|
const int drawX, const int drawY,
|
||||||
|
const bool flipX, const bool flipY,
|
||||||
|
const std::array<int, 4>& palette,
|
||||||
|
const CharacterDefinition& definition) {
|
||||||
|
renderTile(
|
||||||
|
height,
|
||||||
|
drawX, drawY,
|
||||||
|
flipX, flipY, true,
|
||||||
|
palette,
|
||||||
|
definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::GameBoy::Display::renderBackgroundTile(
|
||||||
|
const int drawX, const int drawY,
|
||||||
|
const std::array<int, 4>& palette,
|
||||||
|
const CharacterDefinition& definition) {
|
||||||
|
renderTile(
|
||||||
|
8,
|
||||||
|
drawX, drawY,
|
||||||
|
false, false, false,
|
||||||
|
palette,
|
||||||
|
definition);
|
||||||
|
}
|
||||||
|
|
||||||
void EightBit::GameBoy::Display::renderTile(
|
void EightBit::GameBoy::Display::renderTile(
|
||||||
const int height,
|
const int height,
|
||||||
const int drawX, const int drawY,
|
const int drawX, const int drawY,
|
||||||
const bool flipX, const bool flipY, const bool allowTransparencies,
|
const bool flipX, const bool flipY, const bool allowTransparencies,
|
||||||
const std::array<int, 4>& palette,
|
const std::array<int, 4>& palette,
|
||||||
CharacterDefinition& definition) {
|
const CharacterDefinition& definition) {
|
||||||
|
|
||||||
const auto width = 8;
|
const auto width = 8;
|
||||||
|
|
||||||
@ -160,7 +179,7 @@ void EightBit::GameBoy::Display::renderTile(
|
|||||||
const auto colour = rowDefinition[cx];
|
const auto colour = rowDefinition[cx];
|
||||||
if (!allowTransparencies || (allowTransparencies && (colour > 0))) {
|
if (!allowTransparencies || (allowTransparencies && (colour > 0))) {
|
||||||
const auto outputPixel = lineAddress + x;
|
const auto outputPixel = lineAddress + x;
|
||||||
m_pixels[outputPixel] = m_colours->getColour(palette[colour]);
|
m_pixels[outputPixel] = m_colours->colour(palette[colour]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ void EightBit::GameBoy::Bus::reset() {
|
|||||||
CPU().lowerRESET();
|
CPU().lowerRESET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::GameBoy::Bus::loadBootRom(const std::string& path) {
|
void EightBit::GameBoy::Bus::loadBootRom(const std::string path) {
|
||||||
m_bootRom.load(path);
|
m_bootRom.load(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::GameBoy::Bus::loadGameRom(const std::string& path) {
|
void EightBit::GameBoy::Bus::loadGameRom(const std::string path) {
|
||||||
const auto bankSize = 0x4000;
|
const auto bankSize = 0x4000;
|
||||||
m_gameRomBanks.resize(1);
|
m_gameRomBanks.resize(1);
|
||||||
const auto size = m_gameRomBanks[0].load(path, 0, 0, bankSize);
|
const auto size = m_gameRomBanks[0].load(path, 0, 0, bankSize);
|
||||||
|
@ -297,6 +297,12 @@ void EightBit::GameBoy::LR35902::ccf() {
|
|||||||
F() = clearBit(F(), CF, F() & CF);
|
F() = clearBit(F(), CF, F() & CF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() {
|
||||||
|
const auto interruptEnable = BUS().peek(IoRegisters::BASE + IoRegisters::IE);
|
||||||
|
const auto interruptFlags = m_bus.IO().peek(IoRegisters::IF);
|
||||||
|
return interruptEnable & interruptFlags;
|
||||||
|
}
|
||||||
|
|
||||||
int EightBit::GameBoy::LR35902::step() {
|
int EightBit::GameBoy::LR35902::step() {
|
||||||
|
|
||||||
ExecutingInstruction.fire(*this);
|
ExecutingInstruction.fire(*this);
|
||||||
@ -304,10 +310,7 @@ int EightBit::GameBoy::LR35902::step() {
|
|||||||
resetCycles();
|
resetCycles();
|
||||||
if (LIKELY(powered())) {
|
if (LIKELY(powered())) {
|
||||||
|
|
||||||
const auto interruptEnable = BUS().peek(IoRegisters::BASE + IoRegisters::IE);
|
const auto masked = maskedInterrupts();
|
||||||
const auto interruptFlags = m_bus.IO().peek(IoRegisters::IF);
|
|
||||||
|
|
||||||
const auto masked = interruptEnable & interruptFlags;
|
|
||||||
if (masked) {
|
if (masked) {
|
||||||
if (IME()) {
|
if (IME()) {
|
||||||
m_bus.IO().poke(IoRegisters::IF, 0);
|
m_bus.IO().poke(IoRegisters::IF, 0);
|
||||||
@ -331,7 +334,6 @@ int EightBit::GameBoy::LR35902::step() {
|
|||||||
|
|
||||||
m_bus.IO().checkTimers(clockCycles());
|
m_bus.IO().checkTimers(clockCycles());
|
||||||
m_bus.IO().transferDma();
|
m_bus.IO().transferDma();
|
||||||
|
|
||||||
}
|
}
|
||||||
ExecutedInstruction.fire(*this);
|
ExecutedInstruction.fire(*this);
|
||||||
return clockCycles();
|
return clockCycles();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace EightBit {
|
|||||||
public:
|
public:
|
||||||
virtual ~BigEndianProcessor() = default;
|
virtual ~BigEndianProcessor() = default;
|
||||||
|
|
||||||
register16_t peekWord(register16_t address) final;
|
[[nodiscard]] register16_t peekWord(register16_t address) final;
|
||||||
void pokeWord(register16_t address, register16_t value) final;
|
void pokeWord(register16_t address, register16_t value) final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -89,9 +89,9 @@ namespace EightBit {
|
|||||||
Low, High
|
Low, High
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr auto raised(const PinLevel line) { return line == PinLevel::High; }
|
[[nodiscard]] static constexpr auto raised(const PinLevel line) { return line == PinLevel::High; }
|
||||||
static void raise(PinLevel& line) noexcept { line = PinLevel::High; }
|
static void raise(PinLevel& line) noexcept { line = PinLevel::High; }
|
||||||
static constexpr auto lowered(const PinLevel line) { return line == PinLevel::Low; }
|
[[nodiscard]] static constexpr auto lowered(const PinLevel line) { return line == PinLevel::Low; }
|
||||||
static void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
|
static void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
|
||||||
|
|
||||||
static void match(PinLevel& line, int condition) noexcept { match(line, condition != 0); }
|
static void match(PinLevel& line, int condition) noexcept { match(line, condition != 0); }
|
||||||
|
@ -17,10 +17,10 @@ namespace EightBit {
|
|||||||
[[nodiscard]] uint8_t& reference(uint16_t address) override;
|
[[nodiscard]] uint8_t& reference(uint16_t address) override;
|
||||||
|
|
||||||
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
||||||
int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
||||||
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
|
||||||
|
|
||||||
AccessType getAccessType() const noexcept { return m_access; }
|
[[nodiscard]] AccessType getAccessType() const noexcept { return m_access; }
|
||||||
void setAccessType(AccessType value) noexcept { m_access = value; }
|
void setAccessType(AccessType value) noexcept { m_access = value; }
|
||||||
|
|
||||||
auto readPort(uint8_t port, AccessType access) {
|
auto readPort(uint8_t port, AccessType access) {
|
||||||
|
@ -10,7 +10,7 @@ namespace EightBit {
|
|||||||
public:
|
public:
|
||||||
~LittleEndianProcessor() = default;
|
~LittleEndianProcessor() = default;
|
||||||
|
|
||||||
register16_t peekWord(register16_t address) final;
|
[[nodiscard]] register16_t peekWord(register16_t address) final;
|
||||||
void pokeWord(register16_t address, register16_t value) final;
|
void pokeWord(register16_t address, register16_t value) final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -22,7 +22,7 @@ namespace EightBit {
|
|||||||
[[nodiscard]] virtual uint8_t& reference(uint16_t);
|
[[nodiscard]] virtual uint8_t& reference(uint16_t);
|
||||||
|
|
||||||
virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
||||||
virtual int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
virtual int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
||||||
virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -23,14 +23,14 @@ namespace EightBit {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
|
static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
|
||||||
static int load(const std::string& path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
|
static int load(std::string path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
|
||||||
|
|
||||||
Rom(size_t size = 0);
|
Rom(size_t size = 0);
|
||||||
|
|
||||||
[[nodiscard]] size_t size() const final;
|
[[nodiscard]] size_t size() const final;
|
||||||
|
|
||||||
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
|
|
||||||
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
||||||
|
@ -20,7 +20,7 @@ namespace EightBit {
|
|||||||
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
||||||
|
|
||||||
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -30,7 +30,7 @@ int EightBit::InputOutput::load(std::ifstream&, int, int, int) {
|
|||||||
throw std::logic_error("load operation not allowed.");
|
throw std::logic_error("load operation not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::InputOutput::load(const std::string&, int, int, int) {
|
int EightBit::InputOutput::load(std::string, int, int, int) {
|
||||||
throw std::logic_error("load operation not allowed.");
|
throw std::logic_error("load operation not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
|
|||||||
for (int i = 0; i < 0x100; ++i)
|
for (int i = 0; i < 0x100; ++i)
|
||||||
m_decodedOpcodes.at(i) = i;
|
m_decodedOpcodes.at(i) = i;
|
||||||
|
|
||||||
LoweredHALT.connect([this](EventArgs) { --PC(); });
|
LoweredHALT.connect([this](EventArgs) noexcept { --PC(); });
|
||||||
RaisedHALT.connect([this](EventArgs) { ++PC(); });
|
RaisedHALT.connect([this](EventArgs) noexcept { ++PC(); });
|
||||||
|
|
||||||
RaisedPOWER.connect([this](EventArgs) {
|
RaisedPOWER.connect([this](EventArgs) {
|
||||||
PC() = SP() = AF() = BC() = DE() = HL() = Mask16;
|
PC() = SP() = AF() = BC() = DE() = HL() = Mask16;
|
||||||
|
@ -25,7 +25,7 @@ int EightBit::Rom::load(std::ifstream& file, std::vector<uint8_t>& output, const
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::Rom::load(const std::string& path, std::vector<uint8_t>& output, const int writeOffset, const int readOffset, const int limit, const int maximumSize) {
|
int EightBit::Rom::load(const std::string path, std::vector<uint8_t>& output, const int writeOffset, const int readOffset, const int limit, const int maximumSize) {
|
||||||
|
|
||||||
std::ifstream file;
|
std::ifstream file;
|
||||||
file.exceptions(std::ios::failbit | std::ios::badbit);
|
file.exceptions(std::ios::failbit | std::ios::badbit);
|
||||||
@ -53,7 +53,7 @@ int EightBit::Rom::load(std::ifstream& file, const int writeOffset, const int re
|
|||||||
return load(file, m_bytes, writeOffset, readOffset, limit, maximumSize);
|
return load(file, m_bytes, writeOffset, readOffset, limit, maximumSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::Rom::load(const std::string& path, const int writeOffset, const int readOffset, const int limit) {
|
int EightBit::Rom::load(const std::string path, const int writeOffset, const int readOffset, const int limit) {
|
||||||
const auto maximumSize = size() - writeOffset;
|
const auto maximumSize = size() - writeOffset;
|
||||||
return load(path, m_bytes, writeOffset, readOffset, limit, maximumSize);
|
return load(path, m_bytes, writeOffset, readOffset, limit, maximumSize);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ int EightBit::UnusedMemory::load(std::ifstream&, int, int, int) {
|
|||||||
throw std::logic_error("load operation not allowed.");
|
throw std::logic_error("load operation not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::UnusedMemory::load(const std::string&, int, int, int) {
|
int EightBit::UnusedMemory::load(std::string, int, int, int) {
|
||||||
throw std::logic_error("load operation not allowed.");
|
throw std::logic_error("load operation not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user