mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-11-12 17:04:46 +00:00
Extensive change warning: lots of "noexcept" and "constexpr" changes. Not sure if I'll keep all of them, but interesting...
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
2f76e901f9
commit
22506ea56c
@ -26,8 +26,8 @@ namespace Gaming {
|
||||
virtual void raisePOWER() override;
|
||||
|
||||
protected:
|
||||
virtual float fps() const = 0;
|
||||
virtual bool useVsync() const = 0;
|
||||
virtual float fps() const noexcept = 0;
|
||||
virtual bool useVsync() const noexcept = 0;
|
||||
|
||||
virtual int windowWidth() const noexcept;
|
||||
virtual int windowHeight() const noexcept;
|
||||
@ -37,7 +37,7 @@ namespace Gaming {
|
||||
virtual int rasterWidth() const noexcept = 0;
|
||||
virtual int rasterHeight() const noexcept = 0;
|
||||
|
||||
virtual std::string title() const = 0;
|
||||
virtual std::string title() const noexcept = 0;
|
||||
|
||||
virtual void handleEvents();
|
||||
virtual void update();
|
||||
|
@ -14,6 +14,10 @@
|
||||
|
||||
namespace EightBit {
|
||||
class Intel8080 final : public IntelProcessor {
|
||||
public:
|
||||
DECLARE_PIN_OUTPUT(DBIN) // Active high
|
||||
DECLARE_PIN_OUTPUT(WR) // Active low
|
||||
|
||||
public:
|
||||
enum StatusBits {
|
||||
SF = Bit7,
|
||||
@ -31,19 +35,16 @@ namespace EightBit {
|
||||
virtual int execute() final;
|
||||
virtual int step() final;
|
||||
|
||||
virtual register16_t& AF() final;
|
||||
virtual register16_t& BC() final;
|
||||
virtual register16_t& DE() final;
|
||||
virtual register16_t& HL() final;
|
||||
[[nodiscard]] virtual register16_t& AF() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& BC() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& DE() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& HL() noexcept final;
|
||||
|
||||
bool requestingIO() noexcept { return m_requestIO; }
|
||||
bool requestingMemory() noexcept { return m_requestMemory; }
|
||||
[[nodiscard]] bool requestingIO() noexcept { return m_requestIO; }
|
||||
[[nodiscard]] bool requestingMemory() noexcept { return m_requestMemory; }
|
||||
|
||||
bool requestingRead() { return raised(DBIN()); }
|
||||
bool requestingWrite() { return lowered(WR()); }
|
||||
|
||||
DECLARE_PIN_OUTPUT(DBIN) // Active high
|
||||
DECLARE_PIN_OUTPUT(WR) // Active low
|
||||
[[nodiscard]] bool requestingRead() noexcept { return raised(DBIN()); }
|
||||
[[nodiscard]] bool requestingWrite() noexcept { return lowered(WR()); }
|
||||
|
||||
protected:
|
||||
void handleRESET() final;
|
||||
|
@ -19,20 +19,20 @@ EightBit::Intel8080::Intel8080(Bus& bus)
|
||||
DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080);
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::AF() {
|
||||
EightBit::register16_t& EightBit::Intel8080::AF() noexcept {
|
||||
af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
|
||||
return af;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::BC() {
|
||||
EightBit::register16_t& EightBit::Intel8080::BC() noexcept {
|
||||
return bc;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::DE() {
|
||||
EightBit::register16_t& EightBit::Intel8080::DE() noexcept {
|
||||
return de;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::HL() {
|
||||
EightBit::register16_t& EightBit::Intel8080::HL() noexcept {
|
||||
return hl;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Fuse {
|
||||
EightBit::register16_t actual, EightBit::register16_t expected) const;
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,9 @@ namespace EightBit {
|
||||
namespace GameBoy {
|
||||
class CharacterDefinition final {
|
||||
public:
|
||||
CharacterDefinition(Ram& vram, uint16_t address);
|
||||
CharacterDefinition(Ram& vram, uint16_t address) noexcept;
|
||||
|
||||
[[nodiscard]] std::array<int, 8> get(int row) const;
|
||||
[[nodiscard]] std::array<int, 8> get(int row) const noexcept;
|
||||
|
||||
private:
|
||||
Ram& m_vram;
|
||||
|
@ -27,12 +27,12 @@ namespace EightBit {
|
||||
PixelCount = RasterWidth * RasterHeight,
|
||||
};
|
||||
|
||||
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram);
|
||||
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept;
|
||||
|
||||
[[nodiscard]] const auto& pixels() const noexcept { return m_pixels; }
|
||||
|
||||
void renderCurrentScanline();
|
||||
void loadObjectAttributes();
|
||||
void renderCurrentScanline() noexcept;
|
||||
void loadObjectAttributes() noexcept;
|
||||
|
||||
private:
|
||||
enum class tile_offset_t {
|
||||
@ -48,35 +48,35 @@ namespace EightBit {
|
||||
uint8_t m_control = 0;
|
||||
uint8_t m_scanLine = 0;
|
||||
|
||||
[[nodiscard]] std::array<int, 4> createPalette(int address);
|
||||
[[nodiscard]] std::array<int, 4> createPalette(int address) noexcept;
|
||||
|
||||
void renderBackground();
|
||||
void renderBackground() noexcept;
|
||||
void renderBackground(
|
||||
int bgArea, int bgCharacters,
|
||||
tile_offset_t offsetType,
|
||||
int offsetX, int offsetY,
|
||||
const std::array<int, 4>& palette);
|
||||
const std::array<int, 4>& palette) noexcept;
|
||||
|
||||
void renderObjects();
|
||||
void renderObjects() noexcept;
|
||||
|
||||
void renderSpriteTile(
|
||||
int height,
|
||||
int drawX, int drawY,
|
||||
bool flipX, bool flipY,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition);
|
||||
const CharacterDefinition& definition) noexcept;
|
||||
|
||||
void renderBackgroundTile(
|
||||
int drawX, int drawY,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition);
|
||||
const CharacterDefinition& definition) noexcept;
|
||||
|
||||
void renderTile(
|
||||
int height,
|
||||
int drawX, int drawY,
|
||||
bool flipX, bool flipY, bool allowTransparencies,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition);
|
||||
const CharacterDefinition& definition) noexcept;
|
||||
};
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ namespace EightBit {
|
||||
void runVerticalBlankLines();
|
||||
|
||||
protected:
|
||||
virtual MemoryMapping mapping(uint16_t address) override;
|
||||
virtual MemoryMapping mapping(uint16_t address) noexcept override;
|
||||
|
||||
private:
|
||||
LR35902 m_cpu;
|
||||
@ -94,7 +94,7 @@ namespace EightBit {
|
||||
|
||||
void validateCartridgeType();
|
||||
|
||||
void Bus_WrittenByte(EightBit::EventArgs);
|
||||
void Bus_WrittenByte(EightBit::EventArgs) noexcept;
|
||||
|
||||
void runRasterLines(int lines);
|
||||
void runVerticalBlankLines(int lines);
|
||||
|
@ -26,16 +26,16 @@ namespace EightBit {
|
||||
Signal<LR35902> ExecutingInstruction;
|
||||
Signal<LR35902> ExecutedInstruction;
|
||||
|
||||
[[nodiscard]] register16_t& AF() final;
|
||||
[[nodiscard]] register16_t& BC() final;
|
||||
[[nodiscard]] register16_t& DE() final;
|
||||
[[nodiscard]] register16_t& HL() final;
|
||||
[[nodiscard]] register16_t& AF() noexcept final;
|
||||
[[nodiscard]] register16_t& BC() noexcept final;
|
||||
[[nodiscard]] register16_t& DE() noexcept final;
|
||||
[[nodiscard]] register16_t& HL() noexcept final;
|
||||
|
||||
bool& IME() noexcept { return m_ime; }
|
||||
|
||||
[[nodiscard]] uint8_t enabledInterrupts();
|
||||
[[nodiscard]] uint8_t flaggedInterrupts();
|
||||
[[nodiscard]] uint8_t maskedInterrupts();
|
||||
[[nodiscard]] uint8_t enabledInterrupts() noexcept;
|
||||
[[nodiscard]] uint8_t flaggedInterrupts() noexcept;
|
||||
[[nodiscard]] uint8_t maskedInterrupts() noexcept;
|
||||
|
||||
Signal<EventArgs> MachineTicked;
|
||||
|
||||
@ -76,33 +76,33 @@ namespace EightBit {
|
||||
[[nodiscard]] uint8_t R(int r);
|
||||
void R(int r, uint8_t value);
|
||||
|
||||
[[nodiscard]] register16_t& RP(int rp);
|
||||
[[nodiscard]] register16_t& RP2(int rp);
|
||||
[[nodiscard]] register16_t& RP(int rp) noexcept;
|
||||
[[nodiscard]] register16_t& RP2(int rp) noexcept;
|
||||
|
||||
[[nodiscard]] static auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
||||
[[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
||||
[[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool convertCondition(uint8_t f, int flag);
|
||||
[[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
|
||||
|
||||
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
||||
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
void stop(bool value = true) noexcept { m_stopped = value; }
|
||||
void start() noexcept { stop(false); }
|
||||
[[nodiscard]] bool stopped() const noexcept { return m_stopped; }
|
||||
|
||||
void di();
|
||||
void ei();
|
||||
void di() noexcept;
|
||||
void ei() noexcept;
|
||||
|
||||
void reti();
|
||||
|
||||
@ -113,33 +113,33 @@ namespace EightBit {
|
||||
|
||||
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value);
|
||||
|
||||
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
||||
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
static void bit(uint8_t& f, int n, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t res(int n, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t set(int n, uint8_t operand);
|
||||
static void bit(uint8_t& f, int n, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
static void scf(uint8_t& f, uint8_t operand);
|
||||
static void ccf(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand);
|
||||
static void scf(uint8_t& f, uint8_t operand) noexcept;
|
||||
static void ccf(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand) noexcept;
|
||||
};
|
||||
}
|
||||
}
|
@ -3,12 +3,12 @@
|
||||
|
||||
#include <Ram.h>
|
||||
|
||||
EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address)
|
||||
EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address) noexcept
|
||||
: m_vram(vram),
|
||||
m_address(address) {
|
||||
}
|
||||
|
||||
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const {
|
||||
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const noexcept {
|
||||
|
||||
std::array<int, 8> returned;
|
||||
|
||||
|
@ -7,14 +7,14 @@
|
||||
|
||||
#include <Processor.h>
|
||||
|
||||
EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram)
|
||||
EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept
|
||||
: m_bus(bus),
|
||||
m_oam(oam),
|
||||
m_vram(vram),
|
||||
m_colours(colours) {
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Display::renderCurrentScanline() {
|
||||
void EightBit::GameBoy::Display::renderCurrentScanline() noexcept {
|
||||
m_scanLine = m_bus.IO().peek(IoRegisters::LY);
|
||||
if (m_scanLine < RasterHeight) {
|
||||
m_control = m_bus.IO().peek(IoRegisters::LCDC);
|
||||
@ -26,7 +26,7 @@ void EightBit::GameBoy::Display::renderCurrentScanline() {
|
||||
}
|
||||
}
|
||||
|
||||
std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) {
|
||||
std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) noexcept {
|
||||
const auto raw = m_bus.IO().peek(address);
|
||||
const std::array<int, 4> palette = {
|
||||
raw & 0b11,
|
||||
@ -37,12 +37,12 @@ std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address)
|
||||
return palette;
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Display::loadObjectAttributes() {
|
||||
void EightBit::GameBoy::Display::loadObjectAttributes() noexcept {
|
||||
for (int i = 0; i < 40; ++i)
|
||||
m_objectAttributes[i] = ObjectAttribute(m_oam, 4 * i);
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Display::renderObjects() {
|
||||
void EightBit::GameBoy::Display::renderObjects() noexcept {
|
||||
|
||||
const auto objBlockHeight = (m_control & IoRegisters::OBJ_SIZE) ? 16 : 8;
|
||||
|
||||
@ -81,7 +81,7 @@ void EightBit::GameBoy::Display::renderObjects() {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Display::renderBackground() {
|
||||
void EightBit::GameBoy::Display::renderBackground() noexcept {
|
||||
|
||||
const auto palette = createPalette(IoRegisters::BGP);
|
||||
|
||||
@ -105,7 +105,7 @@ void EightBit::GameBoy::Display::renderBackground() {
|
||||
void EightBit::GameBoy::Display::renderBackground(
|
||||
int bgArea, int bgCharacters, tile_offset_t offsetType,
|
||||
int offsetX, int offsetY,
|
||||
const std::array<int, 4>& palette) {
|
||||
const std::array<int, 4>& palette) noexcept {
|
||||
|
||||
const int row = (m_scanLine - offsetY) / 8;
|
||||
auto address = bgArea + row * BufferCharacterWidth;
|
||||
@ -128,7 +128,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
|
||||
const int drawX, const int drawY,
|
||||
const bool flipX, const bool flipY,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition) {
|
||||
const CharacterDefinition& definition) noexcept {
|
||||
renderTile(
|
||||
height,
|
||||
drawX, drawY,
|
||||
@ -140,7 +140,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
|
||||
void EightBit::GameBoy::Display::renderBackgroundTile(
|
||||
const int drawX, const int drawY,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition) {
|
||||
const CharacterDefinition& definition) noexcept {
|
||||
renderTile(
|
||||
8,
|
||||
drawX, drawY,
|
||||
@ -154,7 +154,7 @@ void EightBit::GameBoy::Display::renderTile(
|
||||
const int drawX, const int drawY,
|
||||
const bool flipX, const bool flipY, const bool allowTransparencies,
|
||||
const std::array<int, 4>& palette,
|
||||
const CharacterDefinition& definition) {
|
||||
const CharacterDefinition& definition) noexcept {
|
||||
|
||||
const auto width = 8;
|
||||
|
||||
|
@ -40,7 +40,7 @@ void EightBit::GameBoy::Bus::loadGameRom(const std::string path) {
|
||||
validateCartridgeType();
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) {
|
||||
void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) noexcept {
|
||||
|
||||
const auto address = ADDRESS().word;
|
||||
const auto value = DATA();
|
||||
@ -161,7 +161,7 @@ void EightBit::GameBoy::Bus::validateCartridgeType() {
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::MemoryMapping EightBit::GameBoy::Bus::mapping(uint16_t address) {
|
||||
EightBit::MemoryMapping EightBit::GameBoy::Bus::mapping(uint16_t address) noexcept {
|
||||
|
||||
if ((address < 0x100) && IO().bootRomEnabled())
|
||||
return { m_bootRom, 0x0000, 0xffff, MemoryMapping::AccessLevel::ReadOnly };
|
||||
|
@ -13,20 +13,20 @@ EightBit::GameBoy::LR35902::LR35902(Bus& memory)
|
||||
});
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::AF() {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::AF() noexcept {
|
||||
af.low = higherNibble(af.low);
|
||||
return af;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() noexcept {
|
||||
return bc;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() noexcept {
|
||||
return de;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() noexcept {
|
||||
return hl;
|
||||
}
|
||||
|
||||
@ -87,15 +87,15 @@ void EightBit::GameBoy::LR35902::ret() {
|
||||
tickMachine();
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::di() {
|
||||
void EightBit::GameBoy::LR35902::di() noexcept {
|
||||
IME() = false;
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::ei() {
|
||||
void EightBit::GameBoy::LR35902::ei() noexcept {
|
||||
IME() = true;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const uint8_t result = operand + 1;
|
||||
f = adjustZero<LR35902>(f, result);
|
||||
@ -103,7 +103,7 @@ uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand)
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, NF);
|
||||
f = clearBit(f, HC, lowNibble(operand));
|
||||
const uint8_t result = operand - 1;
|
||||
@ -165,7 +165,7 @@ void EightBit::GameBoy::LR35902::R(const int r, const uint8_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) noexcept {
|
||||
switch (rp) {
|
||||
case 0b00:
|
||||
return BC();
|
||||
@ -180,7 +180,7 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) {
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) {
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) noexcept {
|
||||
switch (rp) {
|
||||
case 0b00:
|
||||
return BC();
|
||||
@ -195,7 +195,7 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) {
|
||||
}
|
||||
}
|
||||
|
||||
bool EightBit::GameBoy::LR35902::convertCondition(const uint8_t f, int flag) {
|
||||
bool EightBit::GameBoy::LR35902::convertCondition(const uint8_t f, int flag) noexcept {
|
||||
ASSUME(flag >= 0);
|
||||
ASSUME(flag <= 7);
|
||||
switch (flag) {
|
||||
@ -249,7 +249,7 @@ EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const registe
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
|
||||
uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t addition = operand + value + carry;
|
||||
const auto result = addition.low;
|
||||
@ -263,11 +263,11 @@ uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return add(f, operand, value, (f & CF) >> 4);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
|
||||
uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t subtraction = operand - value - carry;
|
||||
const auto result = subtraction.low;
|
||||
@ -281,11 +281,11 @@ uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand,
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return subtract(f, operand, value, (f & CF) >> 4);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, CF | NF);
|
||||
const uint8_t result = operand & value;
|
||||
@ -293,76 +293,76 @@ uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, cons
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand ^ value;
|
||||
f = adjustZero<LR35902>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand | value;
|
||||
f = adjustZero<LR35902>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) {
|
||||
void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
|
||||
subtract(f, operand, value);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
const auto carry = operand & Bit7;
|
||||
f = setBit(f, CF, carry);
|
||||
return (operand << 1) | (carry >> 7);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
const auto carry = operand & Bit0;
|
||||
f = setBit(f, CF, carry);
|
||||
return (operand >> 1) | (carry << 7);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
return (operand << 1) | (carry >> 4); // CF at Bit4
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
return (operand >> 1) | (carry << 3); // CF at Bit4
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
return operand << 1;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
return (operand >> 1) | (operand & Bit7);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | CF);
|
||||
return promoteNibble(operand) | demoteNibble(operand);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC | ZF);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
return (operand >> 1) & ~Bit7;
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) {
|
||||
void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
|
||||
ASSUME(n >= 0);
|
||||
ASSUME(n <= 7);
|
||||
const auto carry = f & CF;
|
||||
@ -370,19 +370,19 @@ void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t oper
|
||||
f = setBit(f, CF, carry);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) noexcept {
|
||||
ASSUME(n >= 0);
|
||||
ASSUME(n <= 7);
|
||||
return clearBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) noexcept {
|
||||
ASSUME(n >= 0);
|
||||
ASSUME(n <= 7);
|
||||
return setBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) noexcept {
|
||||
|
||||
int updated = operand;
|
||||
|
||||
@ -407,30 +407,30 @@ uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, HC | NF);
|
||||
return ~operand;
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) {
|
||||
void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, CF);
|
||||
f = clearBit(f, HC | NF);
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) {
|
||||
void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = clearBit(f, CF, f & CF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() {
|
||||
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() noexcept {
|
||||
return BUS().peek(IoRegisters::BASE + IoRegisters::IE);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() {
|
||||
uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() noexcept {
|
||||
return m_bus.IO().peek(IoRegisters::IF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() {
|
||||
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept {
|
||||
return enabledInterrupts() & flaggedInterrupts();
|
||||
}
|
||||
|
||||
|
@ -34,13 +34,13 @@ namespace EightBit {
|
||||
int execute() final;
|
||||
[[nodiscard]] int step() final;
|
||||
|
||||
[[nodiscard]] auto& X() { return x; }
|
||||
[[nodiscard]] auto& Y() { return y; }
|
||||
[[nodiscard]] auto& A() { return a; }
|
||||
[[nodiscard]] auto& S() { return s; }
|
||||
[[nodiscard]] constexpr auto& X() noexcept { return x; }
|
||||
[[nodiscard]] constexpr auto& Y() noexcept { return y; }
|
||||
[[nodiscard]] constexpr auto& A() noexcept { return a; }
|
||||
[[nodiscard]] constexpr auto& S() noexcept { return s; }
|
||||
|
||||
[[nodiscard]] auto& P() { return p; }
|
||||
[[nodiscard]] const auto& P() const { return p; }
|
||||
[[nodiscard]] constexpr auto& P() noexcept { return p; }
|
||||
[[nodiscard]] constexpr const auto& P() const noexcept { return p; }
|
||||
|
||||
DECLARE_PIN_INPUT(NMI)
|
||||
DECLARE_PIN_INPUT(SO)
|
||||
@ -55,15 +55,15 @@ namespace EightBit {
|
||||
void busWrite() final;
|
||||
[[nodiscard]] uint8_t busRead() final;
|
||||
|
||||
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
|
||||
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data);
|
||||
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
|
||||
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
|
||||
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
|
||||
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data) noexcept;
|
||||
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow) noexcept;
|
||||
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow) noexcept;
|
||||
|
||||
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
|
||||
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data);
|
||||
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry);
|
||||
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry);
|
||||
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0) noexcept;
|
||||
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data) noexcept;
|
||||
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry) noexcept;
|
||||
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry) noexcept;
|
||||
|
||||
private:
|
||||
const uint8_t IRQvector = 0xfe; // IRQ vector
|
||||
@ -111,29 +111,29 @@ namespace EightBit {
|
||||
|
||||
// Flag adjustment
|
||||
|
||||
void adjustZero(const uint8_t datum) { P() = clearBit(P(), ZF, datum); }
|
||||
void adjustNegative(const uint8_t datum) { P() = setBit(P(), NF, datum & NF); }
|
||||
void adjustZero(const uint8_t datum) noexcept { P() = clearBit(P(), ZF, datum); }
|
||||
void adjustNegative(const uint8_t datum) noexcept { P() = setBit(P(), NF, datum & NF); }
|
||||
|
||||
void adjustNZ(const uint8_t datum) {
|
||||
void adjustNZ(const uint8_t datum) noexcept {
|
||||
adjustZero(datum);
|
||||
adjustNegative(datum);
|
||||
}
|
||||
|
||||
// Flag checking
|
||||
|
||||
[[nodiscard]] auto interruptMasked() const { return P() & IF; }
|
||||
[[nodiscard]] auto decimal() const { return P() & DF; }
|
||||
[[nodiscard]] auto interruptMasked() const noexcept { return P() & IF; }
|
||||
[[nodiscard]] auto decimal() const noexcept { return P() & DF; }
|
||||
|
||||
[[nodiscard]] auto negative() const { return P() & NF; }
|
||||
[[nodiscard]] auto zero() const { return P() & ZF; }
|
||||
[[nodiscard]] auto overflow() const { return P() & VF; }
|
||||
[[nodiscard]] auto carry() const { return P() & CF; }
|
||||
[[nodiscard]] auto negative() const noexcept { return P() & NF; }
|
||||
[[nodiscard]] auto zero() const noexcept { return P() & ZF; }
|
||||
[[nodiscard]] auto overflow() const noexcept { return P() & VF; }
|
||||
[[nodiscard]] auto carry() const noexcept { return P() & CF; }
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
void branch(int condition);
|
||||
|
||||
[[nodiscard]] auto through(const uint8_t data) {
|
||||
[[nodiscard]] auto through(const uint8_t data) noexcept {
|
||||
adjustNZ(data);
|
||||
return data;
|
||||
}
|
||||
@ -146,29 +146,29 @@ namespace EightBit {
|
||||
|
||||
// Instruction implementations
|
||||
|
||||
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data);
|
||||
[[nodiscard]] uint8_t asl(uint8_t value);
|
||||
void bit(uint8_t operand, uint8_t data);
|
||||
void cmp(uint8_t first, uint8_t second);
|
||||
[[nodiscard]] uint8_t dec(uint8_t value);
|
||||
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data);
|
||||
[[nodiscard]] uint8_t inc(uint8_t value);
|
||||
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data) noexcept;
|
||||
[[nodiscard]] uint8_t asl(uint8_t value) noexcept;
|
||||
void bit(uint8_t operand, uint8_t data) noexcept;
|
||||
void cmp(uint8_t first, uint8_t second) noexcept;
|
||||
[[nodiscard]] uint8_t dec(uint8_t value) noexcept;
|
||||
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data) noexcept;
|
||||
[[nodiscard]] uint8_t inc(uint8_t value) noexcept;
|
||||
void jsr();
|
||||
[[nodiscard]] uint8_t lsr(uint8_t value);
|
||||
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data);
|
||||
[[nodiscard]] uint8_t lsr(uint8_t value) noexcept;
|
||||
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data) noexcept;
|
||||
void php();
|
||||
void plp();
|
||||
[[nodiscard]] uint8_t rol(uint8_t operand);
|
||||
[[nodiscard]] uint8_t ror(uint8_t operand);
|
||||
[[nodiscard]] uint8_t rol(uint8_t operand) noexcept;
|
||||
[[nodiscard]] uint8_t ror(uint8_t operand) noexcept;
|
||||
void rti();
|
||||
void rts();
|
||||
|
||||
// Undocumented compound instructions
|
||||
|
||||
void anc(uint8_t value);
|
||||
void arr(uint8_t value);
|
||||
void asr(uint8_t value);
|
||||
void axs(uint8_t value);
|
||||
void anc(uint8_t value) noexcept;
|
||||
void arr(uint8_t value) noexcept;
|
||||
void asr(uint8_t value) noexcept;
|
||||
void axs(uint8_t value) noexcept;
|
||||
void dcp(uint8_t value);
|
||||
void isb(uint8_t value);
|
||||
void rla(uint8_t value);
|
||||
|
@ -437,17 +437,15 @@ uint8_t EightBit::MOS6502::Address_ZeroPageY() {
|
||||
}
|
||||
|
||||
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteX() {
|
||||
auto address = Address_Absolute();
|
||||
const auto address = Address_Absolute();
|
||||
const auto page = address.high;
|
||||
address += X();
|
||||
return { address, page };
|
||||
return { address + X(), page };
|
||||
}
|
||||
|
||||
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteY() {
|
||||
auto address = Address_Absolute();
|
||||
const auto address = Address_Absolute();
|
||||
const auto page = address.high;
|
||||
address += Y();
|
||||
return { address, page };
|
||||
return { address + Y(), page };
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() {
|
||||
@ -455,10 +453,9 @@ EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() {
|
||||
}
|
||||
|
||||
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_IndirectIndexedY() {
|
||||
auto address = Address_ZeroPageIndirect();
|
||||
const auto address = Address_ZeroPageIndirect();
|
||||
const auto page = address.high;
|
||||
address += Y();
|
||||
return { address, page };
|
||||
return { address + Y(), page };
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::MOS6502::Address_relative_byte() {
|
||||
@ -488,7 +485,7 @@ uint8_t EightBit::MOS6502::AM_AbsoluteX(const PageCrossingBehavior behaviour) {
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::AM_AbsoluteY() {
|
||||
const auto[address, page] = Address_AbsoluteY();
|
||||
const auto [address, page] = Address_AbsoluteY();
|
||||
auto possible = getBytePaged(page, address.low);
|
||||
if (UNLIKELY(page != address.high))
|
||||
possible = memoryRead(address);
|
||||
@ -524,13 +521,13 @@ void EightBit::MOS6502::branch(const int condition) {
|
||||
const auto page = PC().high;
|
||||
jump(destination);
|
||||
if (UNLIKELY(PC().high != page))
|
||||
memoryRead(register16_t(PC().low, page));
|
||||
getBytePaged(page, PC().low);
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) {
|
||||
uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) noexcept {
|
||||
|
||||
const auto returned = sub(operand, data, ~P() & CF);
|
||||
|
||||
@ -542,16 +539,16 @@ uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) {
|
||||
return returned;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::sub(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||
uint8_t EightBit::MOS6502::sub(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
|
||||
return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, borrow);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||
uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
|
||||
m_intermediate.word = operand - data - borrow;
|
||||
return m_intermediate.low;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||
uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
|
||||
m_intermediate.word = operand - data - borrow;
|
||||
|
||||
uint8_t low = lowNibble(operand) - lowNibble(data) - borrow;
|
||||
@ -567,17 +564,17 @@ uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, cons
|
||||
return promoteNibble(high) | lowNibble(low);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::adc(const uint8_t operand, const uint8_t data) {
|
||||
uint8_t EightBit::MOS6502::adc(const uint8_t operand, const uint8_t data) noexcept {
|
||||
const auto returned = add(operand, data, carry());
|
||||
adjustNZ(m_intermediate.low);
|
||||
return returned;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::add(uint8_t operand, uint8_t data, int carry) {
|
||||
uint8_t EightBit::MOS6502::add(uint8_t operand, uint8_t data, int carry) noexcept {
|
||||
return decimal() ? add_d(operand, data, carry) : add_b(operand, data, carry);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) {
|
||||
uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) noexcept {
|
||||
m_intermediate.word = operand + data + carry;
|
||||
|
||||
P() = setBit(P(), VF, ~(operand ^ data) & (operand ^ m_intermediate.low) & NF);
|
||||
@ -586,7 +583,7 @@ uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) {
|
||||
return m_intermediate.low;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) {
|
||||
uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) noexcept {
|
||||
|
||||
m_intermediate.word = operand + data + carry;
|
||||
|
||||
@ -605,36 +602,36 @@ uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) {
|
||||
return promoteNibble(high) | lowNibble(low);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::andr(const uint8_t operand, const uint8_t data) {
|
||||
uint8_t EightBit::MOS6502::andr(const uint8_t operand, const uint8_t data) noexcept {
|
||||
return through(operand & data);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::asl(const uint8_t value) {
|
||||
uint8_t EightBit::MOS6502::asl(const uint8_t value) noexcept {
|
||||
P() = setBit(P(), CF, value & Bit7);
|
||||
return through(value << 1);
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::bit(const uint8_t operand, const uint8_t data) {
|
||||
void EightBit::MOS6502::bit(const uint8_t operand, const uint8_t data) noexcept {
|
||||
P() = setBit(P(), VF, data & VF);
|
||||
adjustZero(operand & data);
|
||||
adjustNegative(data);
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::cmp(const uint8_t first, const uint8_t second) {
|
||||
void EightBit::MOS6502::cmp(const uint8_t first, const uint8_t second) noexcept {
|
||||
const register16_t result = first - second;
|
||||
adjustNZ(result.low);
|
||||
P() = clearBit(P(), CF, result.high);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::dec(const uint8_t value) {
|
||||
uint8_t EightBit::MOS6502::dec(const uint8_t value) noexcept {
|
||||
return through(value - 1);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::eorr(const uint8_t operand, const uint8_t data) {
|
||||
uint8_t EightBit::MOS6502::eorr(const uint8_t operand, const uint8_t data) noexcept {
|
||||
return through(operand ^ data);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::inc(const uint8_t value) {
|
||||
uint8_t EightBit::MOS6502::inc(const uint8_t value) noexcept {
|
||||
return through(value + 1);
|
||||
}
|
||||
|
||||
@ -646,12 +643,12 @@ void EightBit::MOS6502::jsr() {
|
||||
PC().low = low;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::lsr(const uint8_t value) {
|
||||
uint8_t EightBit::MOS6502::lsr(const uint8_t value) noexcept {
|
||||
P() = setBit(P(), CF, value & Bit0);
|
||||
return through(value >> 1);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::orr(const uint8_t operand, const uint8_t data) {
|
||||
uint8_t EightBit::MOS6502::orr(const uint8_t operand, const uint8_t data) noexcept {
|
||||
return through(operand | data);
|
||||
}
|
||||
|
||||
@ -663,14 +660,14 @@ void EightBit::MOS6502::plp() {
|
||||
P() = (pop() | RF) & ~BF;
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::rol(const uint8_t operand) {
|
||||
uint8_t EightBit::MOS6502::rol(const uint8_t operand) noexcept {
|
||||
const auto carryIn = carry();
|
||||
P() = setBit(P(), CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | carryIn;
|
||||
return through(result);
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::ror(const uint8_t operand) {
|
||||
uint8_t EightBit::MOS6502::ror(const uint8_t operand) noexcept {
|
||||
const auto carryIn = carry();
|
||||
P() = setBit(P(), CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (carryIn << 7);
|
||||
@ -691,24 +688,24 @@ void EightBit::MOS6502::rts() {
|
||||
|
||||
// Undocumented compound instructions
|
||||
|
||||
void EightBit::MOS6502::anc(const uint8_t value) {
|
||||
void EightBit::MOS6502::anc(const uint8_t value) noexcept {
|
||||
A() = andr(A(), value);
|
||||
P() = setBit(P(), CF, A() & Bit7);
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::arr(const uint8_t value) {
|
||||
void EightBit::MOS6502::arr(const uint8_t value) noexcept {
|
||||
A() = andr(A(), value);
|
||||
A() = ror(A());
|
||||
P() = setBit(P(), CF, A() & Bit6);
|
||||
P() = setBit(P(), VF, ((A() & Bit6) >> 6) ^((A() & Bit5) >> 5));
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::asr(const uint8_t value) {
|
||||
void EightBit::MOS6502::asr(const uint8_t value) noexcept {
|
||||
A() = andr(A(), value);
|
||||
A() = lsr(A());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::axs(const uint8_t value) {
|
||||
void EightBit::MOS6502::axs(const uint8_t value) noexcept {
|
||||
X() = through(sub(A() & X(), value));
|
||||
P() = clearBit(P(), CF, m_intermediate.high);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,14 @@
|
||||
|
||||
namespace EightBit {
|
||||
class mc6809 : public BigEndianProcessor {
|
||||
public:
|
||||
DECLARE_PIN_INPUT(NMI)
|
||||
DECLARE_PIN_INPUT(FIRQ)
|
||||
DECLARE_PIN_INPUT(HALT)
|
||||
DECLARE_PIN_OUTPUT(BA)
|
||||
DECLARE_PIN_OUTPUT(BS)
|
||||
DECLARE_PIN_OUTPUT(RW)
|
||||
|
||||
public:
|
||||
enum StatusBits {
|
||||
|
||||
@ -89,13 +97,6 @@ namespace EightBit {
|
||||
void halt() noexcept { --PC(); lowerHALT(); }
|
||||
void proceed() noexcept { ++PC(); raiseHALT(); }
|
||||
|
||||
DECLARE_PIN_INPUT(NMI)
|
||||
DECLARE_PIN_INPUT(FIRQ)
|
||||
DECLARE_PIN_INPUT(HALT)
|
||||
DECLARE_PIN_OUTPUT(BA)
|
||||
DECLARE_PIN_OUTPUT(BS)
|
||||
DECLARE_PIN_OUTPUT(RW)
|
||||
|
||||
protected:
|
||||
// Default push/pop handlers
|
||||
|
||||
|
@ -111,7 +111,7 @@ void Board::initialise() {
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::MemoryMapping Board::mapping(uint16_t address) {
|
||||
EightBit::MemoryMapping Board::mapping(uint16_t address) noexcept {
|
||||
|
||||
if (address < 0x8000)
|
||||
return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
|
||||
private:
|
||||
const Configuration& m_configuration;
|
||||
|
@ -36,6 +36,6 @@ void Board::initialise() {
|
||||
});
|
||||
}
|
||||
|
||||
EightBit::MemoryMapping Board::mapping(uint16_t) {
|
||||
EightBit::MemoryMapping Board::mapping(uint16_t) noexcept {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
protected:
|
||||
void initialise() final;
|
||||
|
||||
EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||
EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
|
||||
private:
|
||||
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM
|
||||
|
@ -7,6 +7,49 @@
|
||||
|
||||
namespace EightBit {
|
||||
class mc6850 final : public ClockedChip {
|
||||
public:
|
||||
// Receive data, (I) Active high
|
||||
DECLARE_PIN_INPUT(RXDATA)
|
||||
|
||||
// Transmit data, (O) Active high
|
||||
DECLARE_PIN_OUTPUT(TXDATA)
|
||||
|
||||
// Request to send, (O) Active low
|
||||
DECLARE_PIN_OUTPUT(RTS)
|
||||
|
||||
// Clear to send, (I) Active low
|
||||
DECLARE_PIN_INPUT(CTS)
|
||||
|
||||
// Data carrier detect, (I) Active low
|
||||
DECLARE_PIN_INPUT(DCD)
|
||||
|
||||
// Transmit clock, (I) Active high
|
||||
DECLARE_PIN_INPUT(RXCLK)
|
||||
|
||||
// Receive clock, (I) Active high
|
||||
DECLARE_PIN_INPUT(TXCLK)
|
||||
|
||||
// Chip select, bit 0, (I) Active high
|
||||
DECLARE_PIN_INPUT(CS0)
|
||||
|
||||
// Chip select, bit 1, (I) Active high
|
||||
DECLARE_PIN_INPUT(CS1)
|
||||
|
||||
// Chip select, bit 2, (I) Active low
|
||||
DECLARE_PIN_INPUT(CS2)
|
||||
|
||||
// Register select, (I) Active high
|
||||
DECLARE_PIN_INPUT(RS)
|
||||
|
||||
// Read/Write, (I) Read high, write low
|
||||
DECLARE_PIN_INPUT(RW)
|
||||
|
||||
// ACIA Enable, (I) Active high
|
||||
DECLARE_PIN_INPUT(E)
|
||||
|
||||
// Interrupt request, (O) Active low
|
||||
DECLARE_PIN_OUTPUT(IRQ)
|
||||
|
||||
public:
|
||||
mc6850();
|
||||
|
||||
@ -58,7 +101,7 @@ namespace EightBit {
|
||||
CR4 = 0b10000, // "
|
||||
CR5 = 0b100000, // Transmit control
|
||||
CR6 = 0b1000000, // "
|
||||
CR7 = 0b10000000 // Receive control
|
||||
CR7 = 0b10000000 // Receive control
|
||||
};
|
||||
|
||||
// CR0 and CR1
|
||||
@ -71,13 +114,13 @@ namespace EightBit {
|
||||
|
||||
// CR2, CR3 and CR4
|
||||
enum WordSelect {
|
||||
SevenEvenTwo = 0b000,
|
||||
SevenEvenTwo = 0b000,
|
||||
SevenOddTwo = 0b001,
|
||||
SevenEvenOne = 0b010,
|
||||
SevenEvenOne = 0b010,
|
||||
SevenOddOne = 0b011,
|
||||
EightTwo = 0b100,
|
||||
EightOne = 0b101,
|
||||
EightEvenOne = 0b110,
|
||||
EightTwo = 0b100,
|
||||
EightOne = 0b101,
|
||||
EightEvenOne = 0b110,
|
||||
EightOddOne = 0b111,
|
||||
};
|
||||
|
||||
@ -219,48 +262,6 @@ namespace EightBit {
|
||||
Signal<EventArgs> Receiving;
|
||||
Signal<EventArgs> Received;
|
||||
|
||||
// Receive data, (I) Active high
|
||||
DECLARE_PIN_INPUT(RXDATA)
|
||||
|
||||
// Transmit data, (O) Active high
|
||||
DECLARE_PIN_OUTPUT(TXDATA)
|
||||
|
||||
// Request to send, (O) Active low
|
||||
DECLARE_PIN_OUTPUT(RTS)
|
||||
|
||||
// Clear to send, (I) Active low
|
||||
DECLARE_PIN_INPUT(CTS)
|
||||
|
||||
// Data carrier detect, (I) Active low
|
||||
DECLARE_PIN_INPUT(DCD)
|
||||
|
||||
// Transmit clock, (I) Active high
|
||||
DECLARE_PIN_INPUT(RXCLK)
|
||||
|
||||
// Receive clock, (I) Active high
|
||||
DECLARE_PIN_INPUT(TXCLK)
|
||||
|
||||
// Chip select, bit 0, (I) Active high
|
||||
DECLARE_PIN_INPUT(CS0)
|
||||
|
||||
// Chip select, bit 1, (I) Active high
|
||||
DECLARE_PIN_INPUT(CS1)
|
||||
|
||||
// Chip select, bit 2, (I) Active low
|
||||
DECLARE_PIN_INPUT(CS2)
|
||||
|
||||
// Register select, (I) Active high
|
||||
DECLARE_PIN_INPUT(RS)
|
||||
|
||||
// Read/Write, (I) Read high, write low
|
||||
DECLARE_PIN_INPUT(RW)
|
||||
|
||||
// ACIA Enable, (I) Active high
|
||||
DECLARE_PIN_INPUT(E)
|
||||
|
||||
// Interrupt request, (O) Active low
|
||||
DECLARE_PIN_OUTPUT(IRQ)
|
||||
|
||||
private:
|
||||
void step();
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace EightBit {
|
||||
virtual ~Ricoh2A03() = default;
|
||||
|
||||
protected:
|
||||
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow) final;
|
||||
virtual uint8_t add(uint8_t operand, uint8_t data, int carry) final;
|
||||
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow) noexcept final;
|
||||
virtual uint8_t add(uint8_t operand, uint8_t data, int carry) noexcept final;
|
||||
};
|
||||
}
|
@ -5,10 +5,10 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
|
||||
: MOS6502(bus) {
|
||||
}
|
||||
|
||||
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, uint8_t data, int borrow) {
|
||||
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, uint8_t data, int borrow) noexcept {
|
||||
return MOS6502::sub_b(operand ,data, borrow);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Ricoh2A03::add(uint8_t operand, uint8_t data, int carry) {
|
||||
uint8_t EightBit::Ricoh2A03::add(uint8_t operand, uint8_t data, int carry) noexcept {
|
||||
return MOS6502::add_b(operand, data, carry);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ void Fuse::TestRunner::lowerPOWER() {
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) {
|
||||
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) noexcept {
|
||||
|
||||
const bool memory = m_cpu.requestingMemory();
|
||||
if (memory)
|
||||
|
@ -48,7 +48,7 @@ namespace Fuse {
|
||||
static void dumpEvent(const TestEvent& event);
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
|
||||
public:
|
||||
TestRunner(const Test& test, const ExpectedTestResult& expected);
|
||||
|
175
Z80/inc/Z80.h
175
Z80/inc/Z80.h
@ -14,22 +14,44 @@ namespace EightBit {
|
||||
class Bus;
|
||||
|
||||
class Z80 final : public IntelProcessor {
|
||||
public:
|
||||
// ** From the Z80 CPU User Manual
|
||||
// RFSH.Refresh(output, active Low). RFSH, together with MREQ, indicates that the lower
|
||||
// seven bits of the system’s address bus can be used as a refresh address to the system’s
|
||||
// dynamic memories.
|
||||
DECLARE_PIN_OUTPUT(RFSH)
|
||||
|
||||
DECLARE_PIN_INPUT(NMI)
|
||||
DECLARE_PIN_OUTPUT(M1)
|
||||
DECLARE_PIN_OUTPUT(MREQ)
|
||||
DECLARE_PIN_OUTPUT(IORQ)
|
||||
DECLARE_PIN_OUTPUT(RD)
|
||||
DECLARE_PIN_OUTPUT(WR)
|
||||
|
||||
private:
|
||||
DEFINE_PIN_ACTIVATOR_LOW(RFSH)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(M1)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(MREQ)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(IORQ)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(RD)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(WR)
|
||||
|
||||
public:
|
||||
struct refresh_t {
|
||||
|
||||
bool high : 1;
|
||||
uint8_t variable : 7;
|
||||
|
||||
refresh_t(const uint8_t value)
|
||||
refresh_t(const uint8_t value) noexcept
|
||||
: high(!!(value & Bit7)),
|
||||
variable(value & Mask7)
|
||||
{ }
|
||||
|
||||
operator uint8_t() const {
|
||||
constexpr operator uint8_t() const noexcept {
|
||||
return (high << 7) | variable;
|
||||
}
|
||||
|
||||
auto& operator++() {
|
||||
constexpr auto& operator++() noexcept {
|
||||
++variable;
|
||||
return *this;
|
||||
}
|
||||
@ -67,18 +89,18 @@ namespace EightBit {
|
||||
int execute() final;
|
||||
int step() final;
|
||||
|
||||
[[nodiscard]] register16_t& AF() final;
|
||||
[[nodiscard]] register16_t& BC() final;
|
||||
[[nodiscard]] register16_t& DE() final;
|
||||
[[nodiscard]] register16_t& HL() final;
|
||||
[[nodiscard]] register16_t& AF() noexcept final;
|
||||
[[nodiscard]] register16_t& BC() noexcept final;
|
||||
[[nodiscard]] register16_t& DE() noexcept final;
|
||||
[[nodiscard]] register16_t& HL() noexcept final;
|
||||
|
||||
[[nodiscard]] auto& IX() { return m_ix; }
|
||||
[[nodiscard]] auto& IXH() { return IX().high; }
|
||||
[[nodiscard]] auto& IXL() { return IX().low; }
|
||||
[[nodiscard]] auto& IX() noexcept { return m_ix; }
|
||||
[[nodiscard]] auto& IXH() noexcept { return IX().high; }
|
||||
[[nodiscard]] auto& IXL() noexcept { return IX().low; }
|
||||
|
||||
[[nodiscard]] auto& IY() { return m_iy; }
|
||||
[[nodiscard]] auto& IYH() { return IY().high; }
|
||||
[[nodiscard]] auto& IYL() { return IY().low; }
|
||||
[[nodiscard]] auto& IY() noexcept { return m_iy; }
|
||||
[[nodiscard]] auto& IYH() noexcept { return IY().high; }
|
||||
[[nodiscard]] auto& IYL() noexcept { return IY().low; }
|
||||
|
||||
// ** From the Z80 CPU User Manual
|
||||
// Memory Refresh(R) Register.The Z80 CPU contains a memory refresh counter,
|
||||
@ -91,34 +113,21 @@ namespace EightBit {
|
||||
// can load the R register for testing purposes, but this register is normally not used by the
|
||||
// programmer. During refresh, the contents of the I Register are placed on the upper eight
|
||||
// bits of the address bus.
|
||||
[[nodiscard]] auto& REFRESH() { return m_refresh; }
|
||||
[[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; }
|
||||
|
||||
[[nodiscard]] auto& IV() { return iv; }
|
||||
[[nodiscard]] auto& IM() { return m_interruptMode; }
|
||||
[[nodiscard]] auto& IFF1() { return m_iff1; }
|
||||
[[nodiscard]] auto& IFF2() { return m_iff2; }
|
||||
[[nodiscard]] constexpr auto& IV() noexcept { return iv; }
|
||||
[[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; }
|
||||
[[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; }
|
||||
[[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; }
|
||||
|
||||
void exx() { m_registerSet ^= 1; }
|
||||
void exxAF() { m_accumulatorFlagsSet ^= 1; }
|
||||
constexpr void exx() noexcept { m_registerSet ^= 1; }
|
||||
constexpr void exxAF() noexcept { m_accumulatorFlagsSet ^= 1; }
|
||||
|
||||
[[nodiscard]] auto requestingIO() const { return lowered(IORQ()); }
|
||||
[[nodiscard]] auto requestingMemory() const { return lowered(MREQ()); }
|
||||
[[nodiscard]] constexpr auto requestingIO() const noexcept { return lowered(IORQ()); }
|
||||
[[nodiscard]] constexpr auto requestingMemory() const noexcept { return lowered(MREQ()); }
|
||||
|
||||
[[nodiscard]] auto requestingRead() const { return lowered(RD()); }
|
||||
[[nodiscard]] auto requestingWrite() const { return lowered(WR()); }
|
||||
|
||||
// ** From the Z80 CPU User Manual
|
||||
// RFSH.Refresh(output, active Low). RFSH, together with MREQ, indicates that the lower
|
||||
// seven bits of the system’s address bus can be used as a refresh address to the system’s
|
||||
// dynamic memories.
|
||||
DECLARE_PIN_OUTPUT(RFSH)
|
||||
|
||||
DECLARE_PIN_INPUT(NMI)
|
||||
DECLARE_PIN_OUTPUT(M1)
|
||||
DECLARE_PIN_OUTPUT(MREQ)
|
||||
DECLARE_PIN_OUTPUT(IORQ)
|
||||
DECLARE_PIN_OUTPUT(RD)
|
||||
DECLARE_PIN_OUTPUT(WR)
|
||||
[[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); }
|
||||
[[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); }
|
||||
|
||||
protected:
|
||||
void handleRESET() final;
|
||||
@ -136,14 +145,6 @@ namespace EightBit {
|
||||
int jrConditional(int condition) final;
|
||||
|
||||
private:
|
||||
|
||||
DEFINE_PIN_ACTIVATOR_LOW(RFSH)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(M1)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(MREQ)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(IORQ)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(RD)
|
||||
DEFINE_PIN_ACTIVATOR_LOW(WR)
|
||||
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
|
||||
std::array<std::array<register16_t, 3>, 2> m_registers;
|
||||
@ -171,10 +172,10 @@ namespace EightBit {
|
||||
|
||||
void handleNMI();
|
||||
|
||||
void resetPrefixes();
|
||||
void resetPrefixes() noexcept;
|
||||
|
||||
[[nodiscard]] auto displaced() const { return m_prefixDD || m_prefixFD; }
|
||||
[[nodiscard]] uint16_t displacedAddress();
|
||||
[[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
|
||||
[[nodiscard]] uint16_t displacedAddress() noexcept;
|
||||
void fetchDisplacement();
|
||||
[[nodiscard]] uint8_t fetchOpCode();
|
||||
|
||||
@ -187,34 +188,34 @@ namespace EightBit {
|
||||
typedef std::function<uint8_t(void)> reader_t;
|
||||
void readInternalRegister(reader_t reader);
|
||||
|
||||
[[nodiscard]] register16_t& HL2();
|
||||
[[nodiscard]] register16_t& RP(int rp);
|
||||
[[nodiscard]] register16_t& RP2(int rp);
|
||||
[[nodiscard]] register16_t& HL2() noexcept;
|
||||
[[nodiscard]] register16_t& RP(int rp) noexcept;
|
||||
[[nodiscard]] register16_t& RP2(int rp) noexcept;
|
||||
|
||||
[[nodiscard]] uint8_t R(int r);
|
||||
void R(int r, uint8_t value);
|
||||
void R2(int r, uint8_t value);
|
||||
|
||||
[[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation);
|
||||
[[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation);
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation);
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative);
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation);
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative);
|
||||
[[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
|
||||
|
||||
[[nodiscard]] static bool convertCondition(uint8_t f, int flag);
|
||||
[[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
|
||||
|
||||
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
||||
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
|
||||
void executeCB(int x, int y, int z);
|
||||
void executeED(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
void di();
|
||||
void ei();
|
||||
void di() noexcept;
|
||||
void ei() noexcept;
|
||||
|
||||
void retn();
|
||||
void reti();
|
||||
@ -228,33 +229,33 @@ namespace EightBit {
|
||||
[[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value);
|
||||
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0);
|
||||
|
||||
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
||||
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
||||
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
static void compare(uint8_t& f, uint8_t operand, uint8_t value);
|
||||
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
static void bit(uint8_t& f, int n, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t res(int n, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t set(int n, uint8_t operand);
|
||||
static void bit(uint8_t& f, int n, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
static void scf(uint8_t& f, uint8_t operand);
|
||||
static void ccf(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand);
|
||||
static void scf(uint8_t& f, uint8_t operand) noexcept;
|
||||
static void ccf(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
void xhtl(register16_t& exchange);
|
||||
|
||||
@ -290,7 +291,7 @@ namespace EightBit {
|
||||
void outd();
|
||||
[[nodiscard]] bool otdr();
|
||||
|
||||
[[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand);
|
||||
[[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand) noexcept;
|
||||
|
||||
void rrd(uint8_t& f, register16_t address, uint8_t& update);
|
||||
void rld(uint8_t& f, register16_t address, uint8_t& update);
|
||||
|
@ -127,15 +127,11 @@ std::string EightBit::Disassembler::R(int r) const {
|
||||
return "IYL";
|
||||
return "L";
|
||||
case 6:
|
||||
if (m_prefixDD || m_prefixFD) {
|
||||
if (m_prefixDD)
|
||||
return "IX+%4%";
|
||||
if (m_prefixFD)
|
||||
return "IY+%4%";
|
||||
}
|
||||
else {
|
||||
return "(HL)";
|
||||
}
|
||||
if (m_prefixDD)
|
||||
return "IX+%4%";
|
||||
if (m_prefixFD)
|
||||
return "IY+%4%";
|
||||
return "(HL)";
|
||||
case 7:
|
||||
return "A";
|
||||
}
|
||||
|
@ -41,19 +41,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(RD, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(WR, Z80);
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::AF() {
|
||||
EightBit::register16_t& EightBit::Z80::AF() noexcept {
|
||||
return m_accumulatorFlags[m_accumulatorFlagsSet];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::BC() {
|
||||
EightBit::register16_t& EightBit::Z80::BC() noexcept {
|
||||
return m_registers[m_registerSet][BC_IDX];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::DE() {
|
||||
EightBit::register16_t& EightBit::Z80::DE() noexcept {
|
||||
return m_registers[m_registerSet][DE_IDX];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::HL() {
|
||||
EightBit::register16_t& EightBit::Z80::HL() noexcept {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
|
||||
@ -160,15 +160,15 @@ void EightBit::Z80::handleINT() {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::di() {
|
||||
void EightBit::Z80::di() noexcept {
|
||||
IFF1() = IFF2() = false;
|
||||
}
|
||||
|
||||
void EightBit::Z80::ei() {
|
||||
void EightBit::Z80::ei() noexcept {
|
||||
IFF1() = IFF2() = true;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const uint8_t result = operand + 1;
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
@ -177,7 +177,7 @@ uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, NF);
|
||||
f = clearBit(f, HC, lowNibble(operand));
|
||||
const uint8_t result = operand - 1;
|
||||
@ -186,33 +186,33 @@ uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
||||
uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
||||
uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) {
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
|
||||
return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) {
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) {
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
|
||||
return adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) {
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
bool EightBit::Z80::convertCondition(const uint8_t f, int flag) {
|
||||
bool EightBit::Z80::convertCondition(const uint8_t f, int flag) noexcept {
|
||||
switch (flag) {
|
||||
case 0:
|
||||
return !(f & ZF);
|
||||
@ -328,7 +328,7 @@ EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
|
||||
uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t addition = operand + value + carry;
|
||||
const auto result = addition.low;
|
||||
@ -343,11 +343,11 @@ uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t valu
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return add(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
|
||||
uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t subtraction = operand - value - carry;
|
||||
const auto result = subtraction.low;
|
||||
@ -362,17 +362,17 @@ uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
|
||||
uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
const auto subtraction = subtract(f, operand, value, carry);
|
||||
f = adjustXY<Z80>(f, subtraction);
|
||||
return subtraction;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return sub(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, CF | NF);
|
||||
const uint8_t result = operand & value;
|
||||
@ -380,26 +380,26 @@ uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t val
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand ^ value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) {
|
||||
uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand | value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) {
|
||||
void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
|
||||
subtract(f, operand, value);
|
||||
f = adjustXY<Z80>(f, value);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit7;
|
||||
f = setBit(f, CF, carry);
|
||||
@ -408,7 +408,7 @@ uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit0;
|
||||
f = setBit(f, CF, carry);
|
||||
@ -417,7 +417,7 @@ uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
@ -426,7 +426,7 @@ uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
@ -437,7 +437,7 @@ uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) {
|
||||
|
||||
//
|
||||
|
||||
uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = operand << 1;
|
||||
@ -445,7 +445,7 @@ uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (operand & Bit7);
|
||||
@ -453,7 +453,7 @@ uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | Bit0;
|
||||
@ -461,7 +461,7 @@ uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) & ~Bit7;
|
||||
@ -470,7 +470,7 @@ uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) {
|
||||
void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, NF);
|
||||
const auto discarded = operand & Chip::bit(n);
|
||||
@ -478,15 +478,15 @@ void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) {
|
||||
f = clearBit(f, PF, discarded);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::res(const int n, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::res(const int n, const uint8_t operand) noexcept {
|
||||
return clearBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::set(const int n, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::set(const int n, const uint8_t operand) noexcept {
|
||||
return setBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) {
|
||||
uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) noexcept {
|
||||
|
||||
f = setBit(f, PF, operand == Bit7);
|
||||
f = setBit(f, CF, operand);
|
||||
@ -502,7 +502,7 @@ uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) {
|
||||
uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) noexcept {
|
||||
|
||||
const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9);
|
||||
const auto highAdjust = (f & CF) || (operand > 0x99);
|
||||
@ -527,20 +527,20 @@ uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) {
|
||||
return updated;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) {
|
||||
uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, HC | NF);
|
||||
const uint8_t result = ~operand;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) {
|
||||
void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, CF);
|
||||
f = clearBit(f, HC | NF);
|
||||
f = adjustXY<Z80>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) {
|
||||
void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, HC, carry);
|
||||
@ -766,13 +766,13 @@ uint8_t EightBit::Z80::portRead() {
|
||||
|
||||
//
|
||||
|
||||
void EightBit::Z80::resetPrefixes() {
|
||||
void EightBit::Z80::resetPrefixes() noexcept {
|
||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint16_t EightBit::Z80::displacedAddress() {
|
||||
uint16_t EightBit::Z80::displacedAddress() noexcept {
|
||||
return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
}
|
||||
|
||||
@ -851,7 +851,7 @@ void EightBit::Z80::readInternalRegister(reader_t reader) {
|
||||
tick();
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::HL2() {
|
||||
EightBit::register16_t& EightBit::Z80::HL2() noexcept {
|
||||
if (UNLIKELY(m_prefixDD))
|
||||
return IX();
|
||||
if (UNLIKELY(m_prefixFD))
|
||||
@ -859,7 +859,7 @@ EightBit::register16_t& EightBit::Z80::HL2() {
|
||||
return HL();
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::RP(const int rp) {
|
||||
EightBit::register16_t& EightBit::Z80::RP(const int rp) noexcept {
|
||||
switch (rp) {
|
||||
case 0b00:
|
||||
return BC();
|
||||
@ -874,7 +874,7 @@ EightBit::register16_t& EightBit::Z80::RP(const int rp) {
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::RP2(const int rp) {
|
||||
EightBit::register16_t& EightBit::Z80::RP2(const int rp) noexcept {
|
||||
switch (rp) {
|
||||
case 0b00:
|
||||
return BC();
|
||||
|
@ -8,10 +8,10 @@ namespace EightBit {
|
||||
|
||||
class BigEndianProcessor : public Processor {
|
||||
public:
|
||||
virtual ~BigEndianProcessor() = default;
|
||||
virtual ~BigEndianProcessor() noexcept {};
|
||||
|
||||
[[nodiscard]] register16_t peekWord(register16_t address) final;
|
||||
void pokeWord(register16_t address, register16_t value) final;
|
||||
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
|
||||
void pokeWord(register16_t address, register16_t value) noexcept final;
|
||||
|
||||
protected:
|
||||
BigEndianProcessor(Bus& memory);
|
||||
|
20
inc/Bus.h
20
inc/Bus.h
@ -12,7 +12,7 @@
|
||||
namespace EightBit {
|
||||
class Bus : public Mapper {
|
||||
public:
|
||||
virtual ~Bus() = default;
|
||||
virtual ~Bus() {};
|
||||
|
||||
Signal<EventArgs> WritingByte;
|
||||
Signal<EventArgs> WrittenByte;
|
||||
@ -26,12 +26,12 @@ namespace EightBit {
|
||||
[[nodiscard]] auto DATA() const noexcept { return m_data; }
|
||||
[[nodiscard]] auto& DATA() noexcept { return m_data; }
|
||||
|
||||
[[nodiscard]] auto peek() { return reference(); }
|
||||
[[nodiscard]] virtual uint8_t peek(const uint16_t address) { return reference(address); }
|
||||
[[nodiscard]] auto peek(const register16_t address) { return peek(address.word); }
|
||||
void poke(const uint8_t value) { reference() = value; }
|
||||
virtual void poke(const uint16_t address, const uint8_t value) { reference(address) = value; }
|
||||
void poke(const register16_t address, const uint8_t value) { poke(address.word, value); }
|
||||
[[nodiscard]] auto peek() noexcept { return reference(); }
|
||||
[[nodiscard]] virtual uint8_t peek(const uint16_t address) noexcept { return reference(address); }
|
||||
[[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); }
|
||||
void poke(const uint8_t value) noexcept { reference() = value; }
|
||||
virtual void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; }
|
||||
void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); }
|
||||
|
||||
[[nodiscard]] uint8_t read();
|
||||
template<class T> [[nodiscard]] auto read(const T address) {
|
||||
@ -52,9 +52,9 @@ namespace EightBit {
|
||||
virtual void initialise() = 0;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address);
|
||||
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); }
|
||||
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); }
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept;
|
||||
[[nodiscard]] auto& reference(const register16_t address) noexcept { return reference(address.word); }
|
||||
[[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS()); }
|
||||
|
||||
void loadHexFile(std::string path);
|
||||
|
||||
|
16
inc/Chip.h
16
inc/Chip.h
@ -57,18 +57,18 @@ namespace EightBit {
|
||||
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const uint32_t condition) noexcept { return clearBit(input, which, !!condition); }
|
||||
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const bool condition) noexcept { return setBit(input, which, !condition); }
|
||||
|
||||
[[nodiscard]] static constexpr auto highNibble(const int value) { return value >> 4; }
|
||||
[[nodiscard]] static constexpr auto lowNibble(const int value) { return value & Mask4; }
|
||||
[[nodiscard]] static constexpr auto highNibble(const int value) noexcept { return value >> 4; }
|
||||
[[nodiscard]] static constexpr auto lowNibble(const int value) noexcept { return value & Mask4; }
|
||||
|
||||
[[nodiscard]] static constexpr auto higherNibble(const int value) { return value & 0xf0; }
|
||||
[[nodiscard]] static constexpr auto lowerNibble(const int value) { return lowNibble(value); }
|
||||
[[nodiscard]] static constexpr auto higherNibble(const int value) noexcept { return value & 0xf0; }
|
||||
[[nodiscard]] static constexpr auto lowerNibble(const int value) noexcept { return lowNibble(value); }
|
||||
|
||||
[[nodiscard]] static constexpr auto promoteNibble(const int value) { return value << 4; }
|
||||
[[nodiscard]] static constexpr auto demoteNibble(const int value) { return highNibble(value); }
|
||||
[[nodiscard]] static constexpr auto promoteNibble(const int value) noexcept { return value << 4; }
|
||||
[[nodiscard]] static constexpr auto demoteNibble(const int value) noexcept { return highNibble(value); }
|
||||
|
||||
~Chip() = default;
|
||||
virtual ~Chip() {}
|
||||
|
||||
protected:
|
||||
Chip() = default;
|
||||
Chip() noexcept = default;
|
||||
};
|
||||
}
|
||||
|
@ -7,16 +7,18 @@
|
||||
namespace EightBit {
|
||||
class ClockedChip : public Chip {
|
||||
public:
|
||||
~ClockedChip() = default;
|
||||
virtual ~ClockedChip() noexcept {};
|
||||
|
||||
Signal<EventArgs> Ticked;
|
||||
|
||||
[[nodiscard]] auto cycles() const noexcept { return m_cycles; }
|
||||
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
|
||||
|
||||
void tick(int extra);
|
||||
void tick();
|
||||
|
||||
protected:
|
||||
ClockedChip() noexcept = default;
|
||||
|
||||
void resetCycles() noexcept;
|
||||
|
||||
private:
|
||||
|
37
inc/Device.h
37
inc/Device.h
@ -48,11 +48,11 @@
|
||||
template <class T> class _Activate ## name final { \
|
||||
T& m_parent; \
|
||||
public: \
|
||||
_Activate ## name(T& parent) \
|
||||
_Activate ## name(T& parent) noexcept \
|
||||
: m_parent(parent) { \
|
||||
m_parent. on ## name(); \
|
||||
} \
|
||||
~_Activate ## name() { \
|
||||
~_Activate ## name() noexcept { \
|
||||
m_parent. off ## name(); \
|
||||
} \
|
||||
};
|
||||
@ -66,10 +66,10 @@
|
||||
#define DECLARE_PIN(name, visibility) \
|
||||
public: \
|
||||
DECLARE_PIN_SIGNALS(name) \
|
||||
[[nodiscard]] PinLevel& name () noexcept { \
|
||||
[[nodiscard]] constexpr auto& name () noexcept { \
|
||||
return m_## name ## _Line; \
|
||||
} \
|
||||
[[nodiscard]] const PinLevel& name () const noexcept { \
|
||||
[[nodiscard]] constexpr const auto& name () const noexcept { \
|
||||
return m_## name ## _Line; \
|
||||
} \
|
||||
visibility : \
|
||||
@ -92,22 +92,23 @@ namespace EightBit {
|
||||
Low, High
|
||||
};
|
||||
|
||||
[[nodiscard]] static constexpr auto raised(const PinLevel line) { return line == PinLevel::High; }
|
||||
static void raise(PinLevel& line) noexcept { line = PinLevel::High; }
|
||||
[[nodiscard]] static constexpr auto lowered(const PinLevel line) { return 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, bool condition) noexcept { condition ? raise(line) : lower(line); }
|
||||
static void match(PinLevel& out, PinLevel in) noexcept { out = in; }
|
||||
|
||||
virtual ~Device() = default;
|
||||
|
||||
[[nodiscard]] bool powered() const noexcept { return raised(POWER()); }
|
||||
|
||||
DECLARE_PIN_INPUT(POWER)
|
||||
|
||||
public:
|
||||
[[nodiscard]] static constexpr auto raised(const PinLevel line) noexcept { return line == PinLevel::High; }
|
||||
static constexpr void raise(PinLevel& line) noexcept { line = PinLevel::High; }
|
||||
[[nodiscard]] static constexpr auto lowered(const PinLevel line) noexcept { return line == PinLevel::Low; }
|
||||
static constexpr void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
|
||||
|
||||
static constexpr void match(PinLevel& line, int condition) noexcept { match(line, condition != 0); }
|
||||
static constexpr void match(PinLevel& line, bool condition) noexcept { condition ? raise(line) : lower(line); }
|
||||
static constexpr void match(PinLevel& out, PinLevel in) noexcept { out = in; }
|
||||
|
||||
virtual ~Device() noexcept {};
|
||||
|
||||
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
|
||||
|
||||
protected:
|
||||
Device() noexcept = default;
|
||||
Device() noexcept {};
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
@ -9,7 +11,6 @@
|
||||
#endif
|
||||
|
||||
#if !(defined(_MSC_VER) || defined(__GNUG__))
|
||||
# include <cassert>
|
||||
# include <bitset>
|
||||
#endif
|
||||
|
||||
@ -70,18 +71,18 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
# define ASSUME(x) __assume(x);
|
||||
# define ASSUME(x) __assume(x);
|
||||
|
||||
# define LIKELY(x) (x)
|
||||
# define LIKELY(x) (x)
|
||||
# define UNLIKELY(x) (x)
|
||||
|
||||
# define UNREACHABLE { ASSUME(0); throw std::exception("unreachable"); }
|
||||
# define UNREACHABLE { ASSUME(0); assert(false && "unreachable"); }
|
||||
|
||||
#elif defined(__GNUG__)
|
||||
|
||||
# define ASSUME(x) { if (!x) __builtin_unreachable(); }
|
||||
# define ASSUME(x) { if (!x) __builtin_unreachable(); }
|
||||
|
||||
# define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
# define UNREACHABLE __builtin_unreachable();
|
||||
@ -90,7 +91,7 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
|
||||
|
||||
# define ASSUME(x) assert(x);
|
||||
|
||||
# define LIKELY(x) (x)
|
||||
# define LIKELY(x) (x)
|
||||
# define UNLIKELY(x) (x)
|
||||
|
||||
# define UNREACHABLE ASSUME(0)
|
||||
|
@ -6,6 +6,6 @@ namespace EightBit {
|
||||
static EventArgs m_empty;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto& empty() noexcept { return m_empty; }
|
||||
[[nodiscard]] static constexpr auto& empty() noexcept { return m_empty; }
|
||||
};
|
||||
}
|
||||
|
@ -11,39 +11,40 @@ namespace EightBit {
|
||||
enum class AccessType { Unknown, Reading, Writing };
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept override;
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const override;
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const noexcept override;
|
||||
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address) override;
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept override;
|
||||
|
||||
int load(std::ifstream& file, 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;
|
||||
|
||||
[[nodiscard]] const AccessType& accessType() const noexcept { return m_access; }
|
||||
[[nodiscard]] AccessType& accessType() noexcept { return m_access; }
|
||||
[[nodiscard]] constexpr const auto& accessType() const noexcept { return m_access; }
|
||||
[[nodiscard]] constexpr auto& accessType() noexcept { return m_access; }
|
||||
|
||||
[[nodiscard]] auto readPort(uint8_t port, AccessType access) {
|
||||
[[nodiscard]] auto readPort(uint8_t port, AccessType access) noexcept {
|
||||
accessType() = access;
|
||||
return reference(port);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto readInputPort(uint8_t port) { return readPort(port, AccessType::Reading); }
|
||||
[[nodiscard]] auto readOutputPort(uint8_t port) { return readPort(port, AccessType::Writing); }
|
||||
[[nodiscard]] auto readInputPort(uint8_t port) noexcept { return readPort(port, AccessType::Reading); }
|
||||
[[nodiscard]] auto readOutputPort(uint8_t port) noexcept { return readPort(port, AccessType::Writing); }
|
||||
|
||||
void writePort(uint8_t port, uint8_t value, AccessType access) {
|
||||
void writePort(uint8_t port, uint8_t value, AccessType access) noexcept {
|
||||
accessType() = access;
|
||||
reference(port) = value;
|
||||
}
|
||||
|
||||
void writeInputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Reading); }
|
||||
void writeOutputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Writing); }
|
||||
void writeInputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Reading); }
|
||||
void writeOutputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Writing); }
|
||||
|
||||
protected:
|
||||
void poke(uint16_t address, uint8_t value) override;
|
||||
void poke(uint16_t address, uint8_t value) noexcept override;
|
||||
|
||||
private:
|
||||
Ram m_input = 0x100;
|
||||
Ram m_output = 0x100;
|
||||
uint8_t m_delivered = 0xff;
|
||||
|
||||
AccessType m_access = AccessType::Unknown;
|
||||
};
|
||||
|
@ -23,9 +23,9 @@ namespace EightBit {
|
||||
int p = 0;
|
||||
int q = 0;
|
||||
|
||||
opcode_decoded_t() noexcept {}
|
||||
constexpr opcode_decoded_t() noexcept {}
|
||||
|
||||
opcode_decoded_t(const uint8_t opcode) noexcept {
|
||||
constexpr opcode_decoded_t(const uint8_t opcode) noexcept {
|
||||
x = (opcode & 0b11000000) >> 6; // 0 - 3
|
||||
y = (opcode & 0b00111000) >> 3; // 0 - 7
|
||||
z = (opcode & 0b00000111); // 0 - 7
|
||||
@ -34,77 +34,77 @@ namespace EightBit {
|
||||
}
|
||||
};
|
||||
|
||||
~IntelProcessor() = default;
|
||||
virtual ~IntelProcessor() {};
|
||||
|
||||
[[nodiscard]] const auto& getDecodedOpcode(const size_t i) const noexcept {
|
||||
[[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
|
||||
return m_decodedOpcodes[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto& MEMPTR() noexcept { return m_memptr; }
|
||||
[[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; }
|
||||
|
||||
[[nodiscard]] auto& SP() noexcept { return m_sp; }
|
||||
[[nodiscard]] constexpr auto& SP() noexcept { return m_sp; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& AF() = 0;
|
||||
[[nodiscard]] auto& A() { return AF().high; }
|
||||
[[nodiscard]] auto& F() { return AF().low; }
|
||||
[[nodiscard]] virtual register16_t& AF() noexcept = 0;
|
||||
[[nodiscard]] auto& A() noexcept { return AF().high; }
|
||||
[[nodiscard]] auto& F() noexcept { return AF().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& BC() = 0;
|
||||
[[nodiscard]] auto& B() { return BC().high; }
|
||||
[[nodiscard]] auto& C() { return BC().low; }
|
||||
[[nodiscard]] virtual register16_t& BC() noexcept = 0;
|
||||
[[nodiscard]] auto& B() noexcept { return BC().high; }
|
||||
[[nodiscard]] auto& C() noexcept { return BC().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& DE() = 0;
|
||||
[[nodiscard]] auto& D() { return DE().high; }
|
||||
[[nodiscard]] auto& E() { return DE().low; }
|
||||
[[nodiscard]] virtual register16_t& DE() noexcept = 0;
|
||||
[[nodiscard]] auto& D() noexcept { return DE().high; }
|
||||
[[nodiscard]] auto& E() noexcept { return DE().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& HL() = 0;
|
||||
[[nodiscard]] auto& H() { return HL().high; }
|
||||
[[nodiscard]] auto& L() { return HL().low; }
|
||||
[[nodiscard]] virtual register16_t& HL() noexcept = 0;
|
||||
[[nodiscard]] auto& H() noexcept { return HL().high; }
|
||||
[[nodiscard]] auto& L() noexcept { return HL().low; }
|
||||
|
||||
DECLARE_PIN_OUTPUT(HALT)
|
||||
|
||||
protected:
|
||||
IntelProcessor(Bus& bus);
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustSign(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept {
|
||||
return setBit(f, T::SF, value & T::SF);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustZero(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustZero(uint8_t f, const uint8_t value) noexcept {
|
||||
return clearBit(f, T::ZF, value);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustParity(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustParity(uint8_t f, const uint8_t value) noexcept {
|
||||
return clearBit(f, T::PF, PARITY(value));
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustSZ(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZ(uint8_t f, const uint8_t value) noexcept {
|
||||
const auto intermediate = adjustSign<T>(f, value);
|
||||
return adjustZero<T>(intermediate, value);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustSZP(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZP(uint8_t f, const uint8_t value) noexcept {
|
||||
const auto intermediate = adjustSZ<T>(f, value);
|
||||
return adjustParity<T>(intermediate, value);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustXY(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustXY(uint8_t f, const uint8_t value) noexcept {
|
||||
const auto intermediate = setBit(f, T::XF, value & T::XF);
|
||||
return setBit(intermediate, T::YF, value & T::YF);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustSZPXY(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZPXY(uint8_t f, const uint8_t value) noexcept {
|
||||
const auto intermediate = adjustSZP<T>(f, value);
|
||||
return adjustXY<T>(intermediate, value);
|
||||
}
|
||||
|
||||
template<class T> [[nodiscard]] static uint8_t adjustSZXY(uint8_t f, const uint8_t value) {
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZXY(uint8_t f, const uint8_t value) noexcept {
|
||||
const auto intermediate = adjustSZ<T>(f, value);
|
||||
return adjustXY<T>(intermediate, value);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
[[nodiscard]] static constexpr auto buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) {
|
||||
[[nodiscard]] static constexpr auto buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ namespace EightBit {
|
||||
return halfCarryTableAdd[index & Mask3];
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
[[nodiscard]] static constexpr auto calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
std::array<int, 8> halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } };
|
||||
const auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
return halfCarryTableSub[index & Mask3];
|
||||
|
@ -8,10 +8,10 @@ namespace EightBit {
|
||||
|
||||
class LittleEndianProcessor : public Processor {
|
||||
public:
|
||||
~LittleEndianProcessor() = default;
|
||||
virtual ~LittleEndianProcessor() {};
|
||||
|
||||
[[nodiscard]] register16_t peekWord(register16_t address) final;
|
||||
void pokeWord(register16_t address, register16_t value) final;
|
||||
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
|
||||
void pokeWord(register16_t address, register16_t value) noexcept final;
|
||||
|
||||
protected:
|
||||
LittleEndianProcessor(Bus& memory);
|
||||
|
@ -7,8 +7,8 @@
|
||||
namespace EightBit {
|
||||
class Mapper {
|
||||
public:
|
||||
virtual ~Mapper() = default;
|
||||
virtual ~Mapper() {};
|
||||
|
||||
[[nodiscard]] virtual MemoryMapping mapping(uint16_t address) = 0;
|
||||
[[nodiscard]] virtual MemoryMapping mapping(uint16_t address) noexcept = 0;
|
||||
};
|
||||
}
|
||||
|
13
inc/Memory.h
13
inc/Memory.h
@ -14,18 +14,21 @@ namespace EightBit {
|
||||
// *) Possibly 'reference'able (Very likely if you've exposed 'poke')
|
||||
class Memory {
|
||||
public:
|
||||
virtual ~Memory() = default;
|
||||
virtual ~Memory() {};
|
||||
|
||||
[[nodiscard]] virtual size_t size() const = 0;
|
||||
[[nodiscard]] virtual uint8_t peek(uint16_t address) const = 0;
|
||||
[[nodiscard]] virtual size_t size() const noexcept = 0;
|
||||
[[nodiscard]] virtual uint8_t peek(uint16_t address) const noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual uint8_t& reference(uint16_t);
|
||||
[[nodiscard]] virtual uint8_t& reference(uint16_t) noexcept;
|
||||
|
||||
virtual int load(std::ifstream& file, 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;
|
||||
|
||||
protected:
|
||||
virtual void poke(uint16_t address, uint8_t value) = 0;
|
||||
virtual void poke(uint16_t address, uint8_t value) noexcept = 0;
|
||||
|
||||
private:
|
||||
uint8_t m_delivered = 0xff;
|
||||
};
|
||||
}
|
||||
|
@ -21,26 +21,26 @@ namespace EightBit {
|
||||
return result;
|
||||
}
|
||||
|
||||
~Processor() = default;
|
||||
virtual ~Processor() noexcept {}
|
||||
|
||||
[[nodiscard]] auto& PC() noexcept { return m_pc; }
|
||||
[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
|
||||
|
||||
int run(int limit);
|
||||
virtual int step() = 0;
|
||||
virtual int execute() = 0;
|
||||
int execute(uint8_t value);
|
||||
|
||||
[[nodiscard]] virtual register16_t peekWord(register16_t address) = 0;
|
||||
virtual void pokeWord(register16_t address, register16_t value) = 0;
|
||||
[[nodiscard]] virtual register16_t peekWord(register16_t address) noexcept = 0;
|
||||
virtual void pokeWord(register16_t address, register16_t value) noexcept = 0;
|
||||
|
||||
DECLARE_PIN_INPUT(RESET)
|
||||
DECLARE_PIN_INPUT(INT)
|
||||
|
||||
protected:
|
||||
Processor(Bus& memory);
|
||||
Processor(Bus& memory) noexcept;
|
||||
|
||||
[[nodiscard]] auto& opcode() noexcept { return m_opcode; }
|
||||
[[nodiscard]] auto& BUS() noexcept { return m_bus; }
|
||||
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
|
||||
[[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
|
||||
|
||||
virtual void handleRESET();
|
||||
virtual void handleINT();
|
||||
|
@ -9,7 +9,7 @@ namespace EightBit {
|
||||
public:
|
||||
Ram(size_t size = 0) noexcept;
|
||||
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address) final;
|
||||
void poke(uint16_t address, uint8_t value) final;
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept final;
|
||||
void poke(uint16_t address, uint8_t value) noexcept final;
|
||||
};
|
||||
}
|
||||
|
@ -70,20 +70,20 @@ namespace EightBit {
|
||||
}
|
||||
};
|
||||
|
||||
inline auto operator==(const register16_t lhs, const register16_t rhs) noexcept {
|
||||
[[nodiscard]] inline auto operator==(const register16_t lhs, const register16_t rhs) noexcept {
|
||||
return lhs.word == rhs.word;
|
||||
}
|
||||
|
||||
inline auto operator!=(const register16_t lhs, const register16_t rhs) noexcept {
|
||||
[[nodiscard]] inline auto operator!=(const register16_t lhs, const register16_t rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline auto operator+(register16_t lhs, const register16_t rhs) noexcept {
|
||||
[[nodiscard]] inline auto operator+(register16_t lhs, const register16_t rhs) noexcept {
|
||||
lhs += rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline auto operator-(register16_t lhs, const register16_t rhs) noexcept {
|
||||
[[nodiscard]] inline auto operator-(register16_t lhs, const register16_t rhs) noexcept {
|
||||
lhs -= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
@ -19,20 +19,20 @@ namespace EightBit {
|
||||
[[nodiscard]] const auto& BYTES() const noexcept { return m_bytes; }
|
||||
[[nodiscard]] auto& BYTES() noexcept { return m_bytes; }
|
||||
|
||||
void poke(uint16_t address, uint8_t value) override;
|
||||
void poke(uint16_t address, uint8_t value) noexcept override;
|
||||
|
||||
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::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) noexcept;
|
||||
|
||||
[[nodiscard]] size_t size() const final;
|
||||
[[nodiscard]] size_t size() const noexcept final;
|
||||
|
||||
int load(std::ifstream& file, 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;
|
||||
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const noexcept final;
|
||||
};
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#endif
|
||||
|
||||
namespace EightBit {
|
||||
template<class ConfigurationT, class BoardT> class TestHarness {
|
||||
template<class ConfigurationT, class BoardT> class TestHarness final {
|
||||
public:
|
||||
TestHarness(const ConfigurationT& configuration)
|
||||
: m_board(configuration) {
|
||||
|
@ -13,18 +13,18 @@ namespace EightBit {
|
||||
// is being read.
|
||||
class UnusedMemory final : public Memory {
|
||||
public:
|
||||
UnusedMemory(size_t size, uint8_t value);
|
||||
UnusedMemory(size_t size, uint8_t value) noexcept;
|
||||
~UnusedMemory() = default;
|
||||
|
||||
[[nodiscard]] size_t size() const final;
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const final;
|
||||
[[nodiscard]] size_t size() const noexcept final;
|
||||
[[nodiscard]] uint8_t peek(uint16_t address) const noexcept final;
|
||||
|
||||
int load(std::ifstream& file, 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;
|
||||
|
||||
protected:
|
||||
void poke(uint16_t address, uint8_t value) final;
|
||||
void poke(uint16_t address, uint8_t value) noexcept final;
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
|
@ -47,13 +47,13 @@ EightBit::register16_t EightBit::BigEndianProcessor::popWord() {
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::peekWord(const register16_t address) {
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::peekWord(const register16_t address) noexcept {
|
||||
const auto high = BUS().peek(address);
|
||||
const auto low = BUS().peek(address + 1);
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::BigEndianProcessor::pokeWord(const register16_t address, const register16_t value) {
|
||||
void EightBit::BigEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
|
||||
BUS().poke(address, value.high);
|
||||
BUS().poke(address + 1, value.low);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ void EightBit::Bus::loadHexFile(const std::string path) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t& EightBit::Bus::reference(const uint16_t address) {
|
||||
uint8_t& EightBit::Bus::reference(const uint16_t address) noexcept {
|
||||
const auto mapped = mapping(address);
|
||||
const uint16_t offset = (address - mapped.begin) & mapped.mask;
|
||||
if (mapped.access == MemoryMapping::AccessLevel::ReadOnly) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "../inc/InputOutput.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../inc/Register.h"
|
||||
@ -9,11 +10,12 @@ size_t EightBit::InputOutput::size() const noexcept {
|
||||
return 0x100;
|
||||
}
|
||||
|
||||
uint8_t EightBit::InputOutput::peek(uint16_t) const {
|
||||
throw std::logic_error("Peek operation not allowed.");
|
||||
uint8_t EightBit::InputOutput::peek(uint16_t) const noexcept {
|
||||
assert(false && "Peek operation not allowed.");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
uint8_t& EightBit::InputOutput::reference(uint16_t address) {
|
||||
uint8_t& EightBit::InputOutput::reference(uint16_t address) noexcept {
|
||||
const auto port = register16_t(address).low;
|
||||
switch (accessType()) {
|
||||
case AccessType::Reading:
|
||||
@ -21,8 +23,9 @@ uint8_t& EightBit::InputOutput::reference(uint16_t address) {
|
||||
case AccessType::Writing:
|
||||
return m_output.reference(port);
|
||||
default:
|
||||
throw std::logic_error("Unknown I/O access type.");
|
||||
assert(false && "Unknown I/O access type.");
|
||||
}
|
||||
return m_delivered;
|
||||
}
|
||||
|
||||
int EightBit::InputOutput::load(std::ifstream&, int, int, int) {
|
||||
@ -37,6 +40,6 @@ int EightBit::InputOutput::load(const std::vector<uint8_t>&, int, int, int) {
|
||||
throw std::logic_error("load operation not allowed.");
|
||||
}
|
||||
|
||||
void EightBit::InputOutput::poke(uint16_t, uint8_t) {
|
||||
throw std::logic_error("Poke operation not allowed.");
|
||||
void EightBit::InputOutput::poke(uint16_t, uint8_t) noexcept {
|
||||
assert(false && "Poke operation not allowed.");
|
||||
}
|
||||
|
@ -47,13 +47,13 @@ EightBit::register16_t EightBit::LittleEndianProcessor::popWord() {
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::peekWord(const register16_t address) {
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::peekWord(const register16_t address) noexcept {
|
||||
const auto low = BUS().peek(address);
|
||||
const auto high = BUS().peek(address + 1);
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::LittleEndianProcessor::pokeWord(const register16_t address, const register16_t value) {
|
||||
void EightBit::LittleEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
|
||||
BUS().poke(address, value.low);
|
||||
BUS().poke(address + 1, value.high);
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "../inc/Memory.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
uint8_t& EightBit::Memory::reference(uint16_t) {
|
||||
throw std::logic_error("Reference operation not allowed.");
|
||||
uint8_t& EightBit::Memory::reference(uint16_t) noexcept {
|
||||
assert(false && "Reference operation not allowed.");
|
||||
return m_delivered;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "../inc/Processor.h"
|
||||
|
||||
EightBit::Processor::Processor(Bus& bus)
|
||||
EightBit::Processor::Processor(Bus& bus) noexcept
|
||||
: m_bus(bus) {
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
EightBit::Ram::Ram(const size_t size) noexcept
|
||||
: Rom(size) {}
|
||||
|
||||
uint8_t& EightBit::Ram::reference(const uint16_t address) {
|
||||
uint8_t& EightBit::Ram::reference(const uint16_t address) noexcept {
|
||||
return BYTES()[address];
|
||||
}
|
||||
|
||||
void EightBit::Ram::poke(const uint16_t address, const uint8_t value) {
|
||||
void EightBit::Ram::poke(const uint16_t address, const uint8_t value) noexcept {
|
||||
Rom::poke(address, value);
|
||||
}
|
||||
|
@ -37,14 +37,14 @@ int EightBit::Rom::load(const std::string path, std::vector<uint8_t>& output, co
|
||||
return size;
|
||||
}
|
||||
|
||||
void EightBit::Rom::poke(const uint16_t address, const uint8_t value) {
|
||||
void EightBit::Rom::poke(const uint16_t address, const uint8_t value) noexcept {
|
||||
BYTES()[address] = value;
|
||||
}
|
||||
|
||||
EightBit::Rom::Rom(const size_t size)
|
||||
EightBit::Rom::Rom(const size_t size) noexcept
|
||||
: m_bytes(size) {}
|
||||
|
||||
size_t EightBit::Rom::size() const {
|
||||
size_t EightBit::Rom::size() const noexcept {
|
||||
return m_bytes.size();
|
||||
}
|
||||
|
||||
@ -72,6 +72,6 @@ int EightBit::Rom::load(const std::vector<uint8_t>& bytes, const int writeOffset
|
||||
return limit;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Rom::peek(const uint16_t address) const {
|
||||
uint8_t EightBit::Rom::peek(const uint16_t address) const noexcept {
|
||||
return BYTES()[address];
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
#include "stdafx.h"
|
||||
#include "../inc/UnusedMemory.h"
|
||||
|
||||
EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value)
|
||||
#include <cassert>
|
||||
|
||||
EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value) noexcept
|
||||
: m_size(size), m_value(value) {}
|
||||
|
||||
size_t EightBit::UnusedMemory::size() const {
|
||||
size_t EightBit::UnusedMemory::size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
uint8_t EightBit::UnusedMemory::peek(uint16_t) const {
|
||||
uint8_t EightBit::UnusedMemory::peek(uint16_t) const noexcept {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
@ -24,6 +26,6 @@ int EightBit::UnusedMemory::load(const std::vector<uint8_t>&, int, int, int) {
|
||||
throw std::logic_error("load operation not allowed.");
|
||||
}
|
||||
|
||||
void EightBit::UnusedMemory::poke(uint16_t, uint8_t) {
|
||||
throw std::logic_error("Poke operation not allowed.");
|
||||
void EightBit::UnusedMemory::poke(uint16_t, uint8_t) noexcept {
|
||||
assert(false && "Poke operation not allowed.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user