From cc78bfb229fd3213c335ccb4c0880d4245ec146c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 25 Apr 2021 13:00:43 -0400 Subject: [PATCH] Forwards most of the Z80 state. --- Analyser/Static/StaticAnalyser.cpp | 16 +++-- Machines/Sinclair/ZXSpectrum/State.hpp | 32 +++++++++ Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp | 15 +++-- .../Clock Signal.xcodeproj/project.pbxproj | 2 + Storage/State/SNA.cpp | 65 +++++++++++++------ 5 files changed, 97 insertions(+), 33 deletions(-) create mode 100644 Machines/Sinclair/ZXSpectrum/State.hpp diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index e24897264..8cc0954de 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -214,13 +214,15 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) { const std::string extension = get_extension(file_name); // Check whether the file directly identifies a target; if so then just return that. -#define Format(ext, class) \ - if(extension == ext) { \ - auto target = Storage::State::class::load(file_name); \ - if(target) { \ - targets.push_back(std::move(target)); \ - return targets; \ - } \ +#define Format(ext, class) \ + if(extension == ext) { \ + try { \ + auto target = Storage::State::class::load(file_name); \ + if(target) { \ + targets.push_back(std::move(target)); \ + return targets; \ + } \ + } catch(...) {} \ } Format("sna", SNA); diff --git a/Machines/Sinclair/ZXSpectrum/State.hpp b/Machines/Sinclair/ZXSpectrum/State.hpp new file mode 100644 index 000000000..dc6a9bff2 --- /dev/null +++ b/Machines/Sinclair/ZXSpectrum/State.hpp @@ -0,0 +1,32 @@ +// +// State.hpp +// Clock Signal +// +// Created by Thomas Harte on 25/04/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#ifndef State_hpp +#define State_hpp + +#include "../../../Reflection/Struct.hpp" +#include "../../../Processors/Z80/State/State.hpp" + +namespace Sinclair { +namespace ZXSpectrum { + + +struct State: public Reflection::StructImpl { + CPU::Z80::State z80; + + State() { + if(needs_declare()) { + DeclareField(z80); + } + } +}; + +} +} + +#endif /* State_h */ diff --git a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp index 06812cdce..bf3142cfc 100644 --- a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp +++ b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp @@ -8,9 +8,9 @@ #include "ZXSpectrum.hpp" +#include "State.hpp" #include "Video.hpp" - -#define LOG_PREFIX "[Spectrum] " +#include "../Keyboard/Keyboard.hpp" #include "../../../Activity/Source.hpp" #include "../../MachineTypes.hpp" @@ -24,7 +24,9 @@ // just grab the CPC's version of an FDC. #include "../../AmstradCPC/FDC.hpp" +#define LOG_PREFIX "[Spectrum] " #include "../../../Outputs/Log.hpp" + #include "../../../Outputs/Speaker/Implementation/CompoundSource.hpp" #include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp" #include "../../../Outputs/Speaker/Implementation/SampleSource.hpp" @@ -39,10 +41,6 @@ #include "../../../ClockReceiver/JustInTime.hpp" -#include "../../../Processors/Z80/State/State.hpp" - -#include "../Keyboard/Keyboard.hpp" - #include namespace Sinclair { @@ -124,6 +122,11 @@ template class ConcreteMachine: duration_to_press_enter_ = Cycles(5 * clock_rate()); keyboard_.set_key_state(ZX::Keyboard::KeyEnter, true); } + + // Install state if supplied. + if(target.state) { + LOG("TODO: state"); + } } ~ConcreteMachine() { diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 60002f0fd..05d2ef9b4 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1434,6 +1434,7 @@ 4B8DD375263481BB00B3C866 /* StateProducer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StateProducer.hpp; sourceTree = ""; }; 4B8DD3842634D37E00B3C866 /* SNA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SNA.cpp; sourceTree = ""; }; 4B8DD3852634D37E00B3C866 /* SNA.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SNA.hpp; sourceTree = ""; }; + 4B8DD3912635A72F00B3C866 /* State.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = State.hpp; sourceTree = ""; }; 4B8DF4D62546561300F3433C /* MemoryMap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MemoryMap.hpp; sourceTree = ""; }; 4B8DF4D725465B7500F3433C /* IIgsMemoryMapTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = IIgsMemoryMapTests.mm; sourceTree = ""; }; 4B8DF4ED254B840B00F3433C /* AppleClock.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AppleClock.hpp; sourceTree = ""; }; @@ -2215,6 +2216,7 @@ 4B0F1BFA260300D900B85C66 /* ZXSpectrum.cpp */, 4B0F1BFB260300D900B85C66 /* ZXSpectrum.hpp */, 4B0F1C092603BA5F00B85C66 /* Video.hpp */, + 4B8DD3912635A72F00B3C866 /* State.hpp */, ); path = ZXSpectrum; sourceTree = ""; diff --git a/Storage/State/SNA.cpp b/Storage/State/SNA.cpp index 99af049d1..dc2ad8e2b 100644 --- a/Storage/State/SNA.cpp +++ b/Storage/State/SNA.cpp @@ -7,40 +7,65 @@ // #include "SNA.hpp" + +#include "../FileHolder.hpp" + #include "../../Analyser/Static/ZXSpectrum/Target.hpp" +#include "../../Machines/Sinclair/ZXSpectrum/State.hpp" using namespace Storage::State; std::unique_ptr SNA::load(const std::string &file_name) { - using Target = Analyser::Static::ZXSpectrum::Target; - auto result = std::make_unique(); + // Make sure the file is accessible and appropriately sized. + FileHolder file(file_name); + if(file.stats().st_size != 48*1024 + 0x1b) { + return nullptr; + } // SNAs are always for 48kb machines. + using Target = Analyser::Static::ZXSpectrum::Target; + auto result = std::make_unique(); result->model = Target::Model::FortyEightK; - // 0x1a byte header: - // + // Prepare to populate ZX Spectrum state. + auto *const state = new Sinclair::ZXSpectrum::State(); + result->state = std::unique_ptr(state); + + // Comments below: [offset] [contents] + // 00 I - // 01 HL' - // 03 DE' - // 05 BC' - // 07 AF' - // 09 HL - // 0B DE - // 0D BC - // 0F IY - // 11 IX + const uint8_t i = file.get8(); + + // 01 HL'; 03 DE'; 05 BC'; 07 AF' + state->z80.registers.hlDash = file.get16le(); + state->z80.registers.deDash = file.get16le(); + state->z80.registers.bcDash = file.get16le(); + state->z80.registers.afDash = file.get16le(); + + // 09 HL; 0B DE; 0D BC; 0F IY; 11 IX + state->z80.registers.hl = file.get16le(); + state->z80.registers.de = file.get16le(); + state->z80.registers.bc = file.get16le(); + state->z80.registers.iy = file.get16le(); + state->z80.registers.ix = file.get16le(); + // 13 IFF2 (in bit 2) + const uint8_t iff = file.get8(); + state->z80.registers.iff1 = state->z80.registers.iff2 = iff & 4; + // 14 R - // 15 AF - // 17 SP - // 19 interrupt mode + const uint8_t r = file.get8(); + state->z80.registers.ir = uint16_t((i << 8) | r); + + // 15 AF; 17 SP; 19 interrupt mode + state->z80.registers.flags = file.get8(); + state->z80.registers.a = file.get8(); + state->z80.registers.stack_pointer = file.get16le(); + state->z80.registers.interrupt_mode = file.get8(); + + // TODO: border colour, RAM contents, then pop the program counter. // 1A border colour // 1B– 48kb RAM contents - // - // (perform a POP to get the PC) - - (void)file_name; return result; }