Skip to content

Commit

Permalink
ZX Spectrum +2A/+3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
ghidosoft committed Mar 10, 2024
1 parent 2966280 commit 8c34e3f
Show file tree
Hide file tree
Showing 11 changed files with 3,737 additions and 17 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ This is a cross-platform ZX Spectrum 48K/128K/+2 emulator written, for the fun o
- Sound
- Drag&drop file loading
- Kempston joystick emulation (arrows and right-control for fire)
- ZX 48K/128K/+2 spectrum
- ZX 48K/128K/+2/+2A/+3 spectrum

## Roadmap
- +2A/+3 spectrum
- AY sound chip
- .z80 snapshots
- Fast loading
Expand Down
1 change: 0 additions & 1 deletion src/core/src/Emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ namespace epoch

struct EmulatorInfo
{
std::string name;
unsigned width;
unsigned height;
std::size_t frameClocks;
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ namespace epoch::frontend
assert(!m_window);
const auto& emulatorInfo = m_emulator->info();
m_window = std::make_unique<Window>(WindowInfo{
.title = "Epoch emulator: " + emulatorInfo.name,
.title = "Epoch emulator: " + m_currentEntry->name,
.width = emulatorInfo.width * 2,
.height = emulatorInfo.height * 2,
});
Expand Down Expand Up @@ -350,7 +350,7 @@ namespace epoch::frontend
m_emulator = entry.factory();
m_currentEntry = &entry;
m_settings->current().emulator.key = m_currentEntry->key;
m_window->setTitle("Epoch emulator: " + m_emulator->info().name);
m_window->setTitle("Epoch emulator: " + m_currentEntry->name);
}

void Application::setShader(const std::size_t index)
Expand Down
5 changes: 5 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ int main()
.name = "ZX Spectrum 128K+2",
.factory = []() { return epoch::zxspectrum::ZXSpectrumEmulator::create128KPlus2(); },
},
{
.key = "ZXSpectrum128K+3",
.name = "ZX Spectrum 128K+2A/+3",
.factory = []() { return epoch::zxspectrum::ZXSpectrumEmulator::create128KPlus3(); },
},
},
};
epoch::frontend::Application application{configuration};
Expand Down
1 change: 1 addition & 0 deletions src/zxspectrum/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_library(epoch_zxspectrum
"src/roms/Rom48K.cpp"
"src/roms/Rom128K.cpp"
"src/roms/Rom128K+2.cpp"
"src/roms/Rom128K+3.cpp"
"src/roms/RomZXTest.cpp"
)

Expand Down
3 changes: 3 additions & 0 deletions src/zxspectrum/src/Roms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ namespace epoch::zxspectrum::roms
// 128K+2 rom downloaded from https://mdfs.net/Software/Spectrum/ROMImages/128k+2.rom
extern const uint8_t Rom128KPlus2[32 * 1024];

// 128K+3 rom downloaded from https://mdfs.net/Software/Spectrum/ROMImages/128k+3.rom
extern const uint8_t Rom128KPlus3[64 * 1024];

extern const uint8_t RomZXTest[8 * 1024];
} // namespace epoch::zxspectrum::roms

Expand Down
41 changes: 41 additions & 0 deletions src/zxspectrum/src/Ula.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <cassert>
#include <cstring>
#include <stdexcept>

namespace epoch::zxspectrum
{
Expand Down Expand Up @@ -65,6 +66,7 @@ namespace epoch::zxspectrum
m_vramSelect = 5;
m_romSelect = 0;
m_pagingState = 0;
m_pagingPlus3 = 0;

m_frameCounter = 0;
m_x = -HorizontalRetrace;
Expand Down Expand Up @@ -143,6 +145,8 @@ namespace epoch::zxspectrum
return m_pagingState;
}
break;
case UlaType::zx128kplus3:
break;
}
return 0xff;
}
Expand Down Expand Up @@ -177,6 +181,43 @@ namespace epoch::zxspectrum
}
}
break;
case UlaType::zx128kplus3:
{
bool shouldUpdate = false;
if ((port & 0b1100000000000010) == 0b0100000000000000)
{
if ((m_pagingState & 0b00100000) == 0)
{
m_pagingState = value;
shouldUpdate = true;
}
}
else if ((port & 0b1111000000000010) == 0b0001000000000000)
{
if ((m_pagingState & 0b00100000) == 0)
{
m_pagingPlus3 = value;
shouldUpdate = true;
}
}
if (shouldUpdate)
{
if (m_pagingPlus3 & 0x01)
{
// Special paging mode
const auto modeSelect = (m_pagingPlus3 >> 1) & 0x03;
throw std::runtime_error("Paging special mode not yet implemented");
}
else
{
// Normal paging mode
m_ramSelect = m_pagingState & 0x07;
m_vramSelect = (m_pagingState & 0b00001000) ? 7 : 5;
m_romSelect = ((m_pagingPlus3 >> 1) & 0x02) | ((m_pagingState >> 4) & 0x01);
}
}
break;
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/zxspectrum/src/Ula.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ namespace epoch::zxspectrum
enum class UlaType
{
zx48k,
zx128k
zx128k,
zx128kplus3,
};

class Ula final : public Z80Interface
Expand Down Expand Up @@ -75,13 +76,14 @@ namespace epoch::zxspectrum
private:
UlaType m_type;

std::array<MemoryBank, 2> m_rom{};
std::array<MemoryBank, 4> m_rom{};
std::array<MemoryBank, 8> m_ram{};

uint8_t m_ramSelect{0};
uint8_t m_vramSelect{5};
uint8_t m_romSelect{0};
uint8_t m_pagingState{};
uint8_t m_pagingPlus3{};

uint8_t m_floatingBusValue{};
uint8_t m_border{};
Expand Down
19 changes: 10 additions & 9 deletions src/zxspectrum/src/ZXSpectrumEmulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ namespace epoch::zxspectrum
};
const Palette ZXSpectrumEmulator::DefaultPalette{defaultColors};

ZXSpectrumEmulator::ZXSpectrumEmulator(std::string name, std::unique_ptr<Ula> ula)
: Emulator{{std::move(name),
Width,
ZXSpectrumEmulator::ZXSpectrumEmulator(std::unique_ptr<Ula> ula)
: Emulator{{Width,
Height,
TStatesPerFrame,
FramesPerSecond,
Expand All @@ -66,20 +65,22 @@ namespace epoch::zxspectrum

std::unique_ptr<ZXSpectrumEmulator> ZXSpectrumEmulator::create48K()
{
return std::make_unique<ZXSpectrumEmulator>("ZX Spectrum 48K",
std::make_unique<Ula>(UlaType::zx48k, roms::Rom48K));
return std::make_unique<ZXSpectrumEmulator>(std::make_unique<Ula>(UlaType::zx48k, roms::Rom48K));
}

std::unique_ptr<ZXSpectrumEmulator> ZXSpectrumEmulator::create128K()
{
return std::make_unique<ZXSpectrumEmulator>("ZX Spectrum 128K",
std::make_unique<Ula>(UlaType::zx128k, roms::Rom128K));
return std::make_unique<ZXSpectrumEmulator>(std::make_unique<Ula>(UlaType::zx128k, roms::Rom128K));
}

std::unique_ptr<ZXSpectrumEmulator> ZXSpectrumEmulator::create128KPlus2()
{
return std::make_unique<ZXSpectrumEmulator>("ZX Spectrum 128K+2",
std::make_unique<Ula>(UlaType::zx128k, roms::Rom128KPlus2));
return std::make_unique<ZXSpectrumEmulator>(std::make_unique<Ula>(UlaType::zx128k, roms::Rom128KPlus2));
}

std::unique_ptr<ZXSpectrumEmulator> ZXSpectrumEmulator::create128KPlus3()
{
return std::make_unique<ZXSpectrumEmulator>(std::make_unique<Ula>(UlaType::zx128kplus3, roms::Rom128KPlus3));
}

void ZXSpectrumEmulator::reset()
Expand Down
3 changes: 2 additions & 1 deletion src/zxspectrum/src/ZXSpectrumEmulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ namespace epoch::zxspectrum
static const Palette DefaultPalette;

public:
ZXSpectrumEmulator(std::string name, std::unique_ptr<Ula> ula);
explicit ZXSpectrumEmulator(std::unique_ptr<Ula> ula);
~ZXSpectrumEmulator() override;

public:
static std::unique_ptr<ZXSpectrumEmulator> create48K();
static std::unique_ptr<ZXSpectrumEmulator> create128K();
static std::unique_ptr<ZXSpectrumEmulator> create128KPlus2();
static std::unique_ptr<ZXSpectrumEmulator> create128KPlus3();

public:
ZXSpectrumEmulator(const ZXSpectrumEmulator& other) = delete;
Expand Down
Loading

0 comments on commit 8c34e3f

Please sign in to comment.