2021-04-25 03:17:47 +00:00
|
|
|
|
//
|
|
|
|
|
// SNA.cpp
|
|
|
|
|
// Clock Signal
|
|
|
|
|
//
|
|
|
|
|
// Created by Thomas Harte on 24/04/2021.
|
|
|
|
|
// Copyright © 2021 Thomas Harte. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "SNA.hpp"
|
2021-04-25 17:00:43 +00:00
|
|
|
|
|
|
|
|
|
#include "../FileHolder.hpp"
|
|
|
|
|
|
2021-04-25 03:38:00 +00:00
|
|
|
|
#include "../../Analyser/Static/ZXSpectrum/Target.hpp"
|
2021-04-25 17:00:43 +00:00
|
|
|
|
#include "../../Machines/Sinclair/ZXSpectrum/State.hpp"
|
2021-04-25 03:17:47 +00:00
|
|
|
|
|
|
|
|
|
using namespace Storage::State;
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Analyser::Static::Target> SNA::load(const std::string &file_name) {
|
2021-04-25 17:00:43 +00:00
|
|
|
|
// Make sure the file is accessible and appropriately sized.
|
|
|
|
|
FileHolder file(file_name);
|
|
|
|
|
if(file.stats().st_size != 48*1024 + 0x1b) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2021-04-25 03:38:00 +00:00
|
|
|
|
|
|
|
|
|
// SNAs are always for 48kb machines.
|
2021-04-25 17:00:43 +00:00
|
|
|
|
using Target = Analyser::Static::ZXSpectrum::Target;
|
|
|
|
|
auto result = std::make_unique<Target>();
|
2021-04-25 03:38:00 +00:00
|
|
|
|
result->model = Target::Model::FortyEightK;
|
|
|
|
|
|
2021-04-25 17:00:43 +00:00
|
|
|
|
// Prepare to populate ZX Spectrum state.
|
|
|
|
|
auto *const state = new Sinclair::ZXSpectrum::State();
|
|
|
|
|
result->state = std::unique_ptr<Reflection::Struct>(state);
|
|
|
|
|
|
|
|
|
|
// Comments below: [offset] [contents]
|
|
|
|
|
|
2021-04-25 03:17:47 +00:00
|
|
|
|
// 00 I
|
2021-04-25 17:00:43 +00:00
|
|
|
|
const uint8_t i = file.get8();
|
|
|
|
|
|
|
|
|
|
// 01 HL'; 03 DE'; 05 BC'; 07 AF'
|
2021-04-25 18:11:36 +00:00
|
|
|
|
state->z80.registers.hl_dash = file.get16le();
|
|
|
|
|
state->z80.registers.de_dash = file.get16le();
|
|
|
|
|
state->z80.registers.bc_dash = file.get16le();
|
|
|
|
|
state->z80.registers.af_dash = file.get16le();
|
2021-04-25 17:00:43 +00:00
|
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
|
|
2021-04-25 03:17:47 +00:00
|
|
|
|
// 13 IFF2 (in bit 2)
|
2021-04-25 17:00:43 +00:00
|
|
|
|
const uint8_t iff = file.get8();
|
|
|
|
|
state->z80.registers.iff1 = state->z80.registers.iff2 = iff & 4;
|
|
|
|
|
|
2021-04-25 03:17:47 +00:00
|
|
|
|
// 14 R
|
2021-04-25 17:00:43 +00:00
|
|
|
|
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();
|
|
|
|
|
|
2021-04-25 03:17:47 +00:00
|
|
|
|
// 1A border colour
|
2021-04-25 18:00:12 +00:00
|
|
|
|
state->video.border_colour = file.get8();
|
2021-04-25 17:18:26 +00:00
|
|
|
|
|
2021-04-25 03:17:47 +00:00
|
|
|
|
// 1B– 48kb RAM contents
|
2021-04-25 17:18:26 +00:00
|
|
|
|
state->ram = file.read(48*1024);
|
|
|
|
|
|
2021-04-25 17:26:53 +00:00
|
|
|
|
// To establish program counter, point it to a RET that
|
|
|
|
|
// I know is in the 16/48kb ROM. This avoids having to
|
|
|
|
|
// try to do a pop here, given that the true program counter
|
|
|
|
|
// might currently be in the ROM.
|
|
|
|
|
state->z80.registers.program_counter = 0x1d83;
|
2021-04-25 03:38:00 +00:00
|
|
|
|
|
|
|
|
|
return result;
|
2021-04-25 03:17:47 +00:00
|
|
|
|
}
|