initial commit
This commit is contained in:
commit
ae2b3d3451
40 changed files with 55111 additions and 0 deletions
40
src/audio.cpp
Normal file
40
src/audio.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <iostream>
|
||||
#include "memory.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "bus.hpp"
|
||||
|
||||
Audio::Audio(Bus* bus): bus(bus), spec({}), device(0)
|
||||
{
|
||||
SDL_AudioSpec spec = {};
|
||||
spec.freq = 15360;
|
||||
spec.format = AUDIO_U8;
|
||||
spec.channels = 1;
|
||||
spec.samples = 256;
|
||||
|
||||
this->device = SDL_OpenAudioDevice(nullptr, 0, &spec, &this->spec, 0);
|
||||
if (!this->device) {
|
||||
std::cerr << "I had trouble creating the audio device!\nSDL error: " << SDL_GetError() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
SDL_PauseAudioDevice(this->device, 0);
|
||||
}
|
||||
|
||||
Audio::~Audio()
|
||||
{
|
||||
if (this->device) {
|
||||
SDL_PauseAudioDevice(this->device, 1);
|
||||
SDL_CloseAudioDevice(this->device);
|
||||
this->device = 0;
|
||||
}
|
||||
this->spec = {};
|
||||
this->bus = nullptr;
|
||||
}
|
||||
|
||||
void Audio::Play()
|
||||
{
|
||||
uint32_t location = (uint32_t)this->bus->memory->mem[6] << 16 | this->bus->memory->mem[7] << 8;
|
||||
|
||||
if (SDL_QueueAudio(this->device, this->bus->memory->mem + location, 256)) {
|
||||
std::cerr << "I had trouble playing audio!\nSDL error: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
}
|
13
src/bus.cpp
Normal file
13
src/bus.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "bus.hpp"
|
||||
|
||||
Bus::Bus(): memory(nullptr), cpu(nullptr), display(nullptr), audio(nullptr), input(nullptr)
|
||||
{}
|
||||
|
||||
Bus::~Bus()
|
||||
{
|
||||
this->memory = nullptr;
|
||||
this->cpu = nullptr;
|
||||
this->display = nullptr;
|
||||
this->audio = nullptr;
|
||||
this->input = nullptr;
|
||||
}
|
49
src/cpu.cpp
Normal file
49
src/cpu.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "cpu.hpp"
|
||||
#include "bus.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
// i'm sorry but there's no way i'm typing this every time i want to access memory
|
||||
// (which is a lot of times in this file)
|
||||
#define MEMORY this->bus->memory->mem
|
||||
|
||||
CPU::CPU(Bus* bus): bus(bus)
|
||||
{
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
CPU::~CPU()
|
||||
{
|
||||
this->bus = nullptr;
|
||||
}
|
||||
|
||||
void CPU::Step()
|
||||
{
|
||||
uint32_t destination = (uint32_t)this->pc[3] << 16 | (uint32_t)this->pc[4] << 8 | this->pc[5];
|
||||
uint32_t source = (uint32_t)this->pc[0] << 16 | (uint32_t)this->pc[1] << 8 | this->pc[2];
|
||||
uint32_t jump = (uint32_t)this->pc[6] << 16 | (uint32_t)this->pc[7] << 8 | this->pc[8];
|
||||
|
||||
MEMORY[destination] = MEMORY[source];
|
||||
this->pc = MEMORY + jump;
|
||||
}
|
||||
|
||||
void CPU::Reset()
|
||||
{
|
||||
this->pc = MEMORY + ((uint32_t)MEMORY[2]<<16 | (uint32_t)MEMORY[3]<<8 | MEMORY[4]);
|
||||
}
|
||||
|
||||
void CPU::setKeyBit(uint8_t index)
|
||||
{
|
||||
uint32_t* keyboard = (uint32_t*)MEMORY;
|
||||
if (index < 8) *keyboard |= 1 << (index + 8);
|
||||
else *keyboard |= 1 << (index - 8);
|
||||
}
|
||||
|
||||
void CPU::clearKeyBit(uint8_t index)
|
||||
{
|
||||
uint32_t* keyboard = (uint32_t*)MEMORY;
|
||||
if (index < 8) *keyboard &= ~(1 << (index + 8));
|
||||
else *keyboard &= ~(1 << (index - 8));
|
||||
}
|
||||
|
||||
#undef MEMORY
|
||||
// goodbye
|
55
src/display.cpp
Normal file
55
src/display.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <iostream>
|
||||
#include "memory.hpp"
|
||||
#include "display.hpp"
|
||||
#include "bus.hpp"
|
||||
|
||||
Display::Display(Bus* bus, SDL_Renderer* ren): bus(bus)
|
||||
{
|
||||
this->Reset();
|
||||
this->displayTexture = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (!displayTexture) {
|
||||
std::cerr << "Texture creation error: " << SDL_GetError() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
this->PrepareColorPalette();
|
||||
}
|
||||
|
||||
void Display::Reset()
|
||||
{
|
||||
for (auto& el: this->display) el = {0, 0, 0, 255};
|
||||
}
|
||||
|
||||
void Display::PrepareColorPalette()
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for (size_t r = 0; r < 256; r += 0x33) {
|
||||
for (size_t g = 0; g < 256; g += 0x33) {
|
||||
for (size_t b = 0; b < 256; b += 0x33) {
|
||||
this->colorPalette[i].r = r;
|
||||
this->colorPalette[i].g = g;
|
||||
this->colorPalette[i].b = b;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display::UpdateTexture()
|
||||
{
|
||||
uint32_t location = (uint32_t)this->bus->memory->mem[5];
|
||||
|
||||
for (size_t y = 0; y < 256; y++) {
|
||||
for (size_t x = 0; x < 256; x++) {
|
||||
this->display[(y * 256) + x] = this->colorPalette[this->bus->memory->mem[location << 16 | y << 8 | x ]];
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(this->displayTexture, NULL, display, width * 4);
|
||||
}
|
||||
|
||||
Display::~Display()
|
||||
{
|
||||
SDL_DestroyTexture(this->displayTexture);
|
||||
}
|
74
src/input.cpp
Normal file
74
src/input.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "input.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "bus.hpp"
|
||||
|
||||
Input::Input(Bus* bus): bus(bus) {}
|
||||
|
||||
Input::~Input()
|
||||
{
|
||||
this->bus = nullptr;
|
||||
}
|
||||
|
||||
void Input::HandleKeyDown(SDL_Keycode keycode)
|
||||
{
|
||||
switch (keycode)
|
||||
{
|
||||
case SDLK_1: this->SetKeyBit(1); break;
|
||||
case SDLK_2: this->SetKeyBit(2); break;
|
||||
case SDLK_3: this->SetKeyBit(3); break;
|
||||
case SDLK_4: this->SetKeyBit(12); break;
|
||||
case SDLK_q: this->SetKeyBit(4); break;
|
||||
case SDLK_w: this->SetKeyBit(5); break;
|
||||
case SDLK_e: this->SetKeyBit(6); break;
|
||||
case SDLK_r: this->SetKeyBit(13); break;
|
||||
case SDLK_a: this->SetKeyBit(7); break;
|
||||
case SDLK_s: this->SetKeyBit(8); break;
|
||||
case SDLK_d: this->SetKeyBit(9); break;
|
||||
case SDLK_f: this->SetKeyBit(14); break;
|
||||
case SDLK_z: this->SetKeyBit(10); break;
|
||||
case SDLK_x: this->SetKeyBit(0); break;
|
||||
case SDLK_c: this->SetKeyBit(11); break;
|
||||
case SDLK_v: this->SetKeyBit(15); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::HandleKeyUp(SDL_Keycode keycode)
|
||||
{
|
||||
switch (keycode)
|
||||
{
|
||||
case SDLK_1: this->UnsetKeyBit(1); break;
|
||||
case SDLK_2: this->UnsetKeyBit(2); break;
|
||||
case SDLK_3: this->UnsetKeyBit(3); break;
|
||||
case SDLK_4: this->UnsetKeyBit(12); break;
|
||||
case SDLK_q: this->UnsetKeyBit(4); break;
|
||||
case SDLK_w: this->UnsetKeyBit(5); break;
|
||||
case SDLK_e: this->UnsetKeyBit(6); break;
|
||||
case SDLK_r: this->UnsetKeyBit(13); break;
|
||||
case SDLK_a: this->UnsetKeyBit(7); break;
|
||||
case SDLK_s: this->UnsetKeyBit(8); break;
|
||||
case SDLK_d: this->UnsetKeyBit(9); break;
|
||||
case SDLK_f: this->UnsetKeyBit(14); break;
|
||||
case SDLK_z: this->UnsetKeyBit(10); break;
|
||||
case SDLK_x: this->UnsetKeyBit(0); break;
|
||||
case SDLK_c: this->UnsetKeyBit(11); break;
|
||||
case SDLK_v: this->UnsetKeyBit(15); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::SetKeyBit(uint8_t bit)
|
||||
{
|
||||
uint32_t* keyboard = (uint32_t*)this->bus->memory->mem;
|
||||
if (bit < 8) *keyboard |= (1 << (bit + 8));
|
||||
else *keyboard |= (1 << (bit - 8));
|
||||
}
|
||||
|
||||
void Input::UnsetKeyBit(uint8_t bit)
|
||||
{
|
||||
uint32_t* keyboard = (uint32_t*)this->bus->memory->mem;
|
||||
if (bit < 8) *keyboard &= ~(1 << (bit + 8));
|
||||
else *keyboard &= ~(1 << (bit - 8));
|
||||
}
|
247
src/main.cpp
Normal file
247
src/main.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <bitset>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <imgui.h>
|
||||
#include <ImGuiFileDialog.h>
|
||||
#include <imgui_sdl.h>
|
||||
#include <ctime>
|
||||
|
||||
#include "bus.hpp"
|
||||
#include "cpu.hpp"
|
||||
#include "display.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "input.hpp"
|
||||
|
||||
#define MILLISECONDS std::milli::den
|
||||
#define FRAMERATE 60.0f
|
||||
#define FRAMELENGTH (MILLISECONDS / FRAMERATE)
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
// SDL initialisation
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("Bytepusher++", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 700, SDL_WINDOW_RESIZABLE);
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
||||
// VM initialisation
|
||||
Bus* bus = new Bus();
|
||||
|
||||
Memory* memory = new Memory(bus);
|
||||
bus->memory = memory;
|
||||
|
||||
CPU* cpu = new CPU(bus);
|
||||
bus->cpu = cpu;
|
||||
|
||||
Display* display = new Display(bus, renderer);
|
||||
bus->display = display;
|
||||
|
||||
Audio* audio = new Audio(bus);
|
||||
bus->audio = audio;
|
||||
|
||||
Input* input = new Input(bus);
|
||||
bus->input = input;
|
||||
|
||||
ImGui::CreateContext();
|
||||
ImGuiSDL::Initialize(renderer, 900, 700);
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
// Clears screen
|
||||
SDL_Texture* clear = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, 100, 100);
|
||||
{
|
||||
SDL_SetRenderTarget(renderer, clear);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_SetRenderTarget(renderer, nullptr);
|
||||
}
|
||||
|
||||
std::time_t res = std::time(nullptr);
|
||||
std::string date = std::ctime(&res);
|
||||
date = date.substr(0, date.length() - 1);
|
||||
int snapshotIncrement = 1;
|
||||
|
||||
bool run = true;
|
||||
bool paused = false;
|
||||
|
||||
bool showBytepusher = true;
|
||||
bool showDebug = true;
|
||||
|
||||
while (run)
|
||||
{
|
||||
size_t begin = SDL_GetTicks();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
int wheel = 0;
|
||||
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
if (e.type == SDL_QUIT) run = false;
|
||||
|
||||
else if (e.type == SDL_KEYDOWN) {
|
||||
if (!paused && memory->ROMLoaded)
|
||||
input->HandleKeyDown(e.key.keysym.sym);
|
||||
} else if (e.type == SDL_KEYUP) {
|
||||
input->HandleKeyUp(e.key.keysym.sym);
|
||||
} else if (e.type == SDL_WINDOWEVENT) {
|
||||
if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
io.DisplaySize.x = static_cast<float>(e.window.data1);
|
||||
io.DisplaySize.y = static_cast<float>(e.window.data2);
|
||||
}
|
||||
} else if (e.type == SDL_MOUSEWHEEL) {
|
||||
wheel = e.wheel.y;
|
||||
}
|
||||
}
|
||||
|
||||
int mouseX, mouseY;
|
||||
const int buttons = SDL_GetMouseState(&mouseX, &mouseY);
|
||||
|
||||
// Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
|
||||
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
|
||||
io.MouseDown[0] = buttons & SDL_BUTTON(SDL_BUTTON_LEFT);
|
||||
io.MouseDown[1] = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
|
||||
io.MouseWheel = static_cast<float>(wheel);
|
||||
|
||||
// Bytepusher code
|
||||
if (!paused && memory->ROMLoaded) {
|
||||
cpu->Reset();
|
||||
size_t i = 65536;
|
||||
do {
|
||||
cpu->Step();
|
||||
} while (i--);
|
||||
audio->Play();
|
||||
display->UpdateTexture();
|
||||
}
|
||||
|
||||
// ImGui code
|
||||
|
||||
ImGui::NewFrame();
|
||||
// window minimizers
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open")) {
|
||||
ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Choose BytePusher ROM", ".bytepusher,.bp", "", 1);
|
||||
}
|
||||
if (ImGui::MenuItem("Close ROM")) {
|
||||
memory->Reset();
|
||||
display->Reset();
|
||||
display->UpdateTexture();
|
||||
}
|
||||
if (ImGui::MenuItem("Quit")) {
|
||||
run = false;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Debug")) {
|
||||
ImGui::Checkbox("Show debug window", &showDebug);
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem(paused? "Resume emulation###pausebtn" : "Pause emulation###pausebtn")) {
|
||||
paused = !paused;
|
||||
}
|
||||
if (ImGui::MenuItem("Snapshot RAM")) {
|
||||
// candidate for ugliest piece of code in history?
|
||||
std::string filepath = std::filesystem::path(argv[0])
|
||||
.parent_path()
|
||||
.parent_path()
|
||||
.string()
|
||||
+ "/snapshots/"
|
||||
+ date
|
||||
+ ": "
|
||||
+ std::to_string(snapshotIncrement)
|
||||
+ ".bytepusher";
|
||||
|
||||
if (!memory->SnapshotRAM(filepath)) {
|
||||
if (ImGui::BeginPopupModal("RAM snapshotting error")) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "%s", memory->snapshotError.c_str());
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
snapshotIncrement++;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) {
|
||||
if (ImGuiFileDialog::Instance()->IsOk()) {
|
||||
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
|
||||
ImGuiFileDialog::Instance()->Close();
|
||||
if (!memory->LoadROM(filePathName)) {
|
||||
if (ImGui::BeginPopupModal("ROM loading error")) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "%s", memory->ROMLoadError.c_str());
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showDebug) {
|
||||
ImGui::Begin("Debug", &showDebug, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
|
||||
ImGui::Text("-- ROM info --");
|
||||
if (ImGui::BeginTable("ROM info", 2)) {
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Has loaded ROM");
|
||||
ImGui::TableNextColumn(); ImGui::Text(memory->ROMLoaded? "Yes" : "No");
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "ROM name");
|
||||
ImGui::TableNextColumn(); ImGui::Text("%s", std::filesystem::path(memory->ROMFilepath).filename().c_str());
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "ROM size");
|
||||
ImGui::TableNextColumn(); ImGui::Text("%zu B", memory->ROMSize);
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Is paused");
|
||||
ImGui::TableNextColumn(); ImGui::Text(paused? "Yes" : "No");
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::Text("-- Emulation info --");
|
||||
if (ImGui::BeginTable("Emulation info", 2)) {
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Keyboard state");
|
||||
ImGui::TableNextColumn(); ImGui::Text("%s", std::bitset<16>((uint32_t)memory->mem[0] << 8 | memory->mem[1]).to_string().c_str());
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "GFX block location");
|
||||
ImGui::TableNextColumn(); ImGui::Text("0x%02x", memory->mem[5]);
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Sound block location");
|
||||
ImGui::TableNextColumn(); ImGui::Text("0x%06x", (uint32_t)memory->mem[6] << 16 | memory->mem[7] << 8);
|
||||
ImGui::TableNextColumn(); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Memory errors");
|
||||
ImGui::TableNextColumn(); ImGui::Text("%s\n%s", memory->ROMLoadError.c_str(), memory->snapshotError.c_str());
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
ImGui::Begin(paused? "[PAUSED] Bytepusher###bptitle" : "Bytepusher###bptitle", &showBytepusher, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
|
||||
ImGui::Image(display->displayTexture, ImVec2(512, 512));
|
||||
ImGui::End();
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 114, 144, 154, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
ImGui::Render();
|
||||
ImGuiSDL::Render(ImGui::GetDrawData());
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
size_t length = SDL_GetTicks() - begin;
|
||||
if (length < FRAMELENGTH) {
|
||||
SDL_Delay(FRAMELENGTH - length);
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiSDL::Deinitialize();
|
||||
|
||||
SDL_DestroyTexture(clear);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
delete cpu;
|
||||
delete memory;
|
||||
delete display;
|
||||
delete audio;
|
||||
|
||||
delete bus;
|
||||
ImGui::DestroyContext();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
68
src/memory.cpp
Normal file
68
src/memory.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <ctime>
|
||||
#include "memory.hpp"
|
||||
#include "bus.hpp"
|
||||
|
||||
Memory::Memory(Bus* bus): bus(bus)
|
||||
{
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
Memory::~Memory()
|
||||
{
|
||||
this->bus = nullptr;
|
||||
}
|
||||
|
||||
void Memory::Reset()
|
||||
{
|
||||
this->ROMLoaded = false;
|
||||
this->ROMFilepath = "";
|
||||
this->ROMSize = 0;
|
||||
this->ROMLoadError = "";
|
||||
this->snapshotError = "";
|
||||
this->snapshotLast = "";
|
||||
for (auto& el: this->mem) el = 0;
|
||||
}
|
||||
|
||||
bool Memory::LoadROM(std::string filepath)
|
||||
{
|
||||
std::fstream stream(filepath, std::ios::in|std::ios::binary);
|
||||
if (stream) {
|
||||
size_t filesize = std::filesystem::file_size(filepath);
|
||||
if (filesize > MEMORY_SIZE) {
|
||||
std::cerr << "Error: chosen ROM is larger than RAM" << std::endl;
|
||||
this->ROMLoadError = "Error: chosen ROM is larger than RAM";
|
||||
return 0;
|
||||
}
|
||||
stream.read((char*)this->mem, filesize);
|
||||
this->ROMLoaded = true;
|
||||
this->ROMFilepath = filepath;
|
||||
this->ROMSize = filesize;
|
||||
this->ROMLoadError = "";
|
||||
stream.close();
|
||||
return 1;
|
||||
} else {
|
||||
std::cerr << "Error: ROM could not be found or opened" << std::endl;
|
||||
this->ROMLoadError = "Error: ROM could not be found or opened";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Memory::SnapshotRAM(std::string filepath)
|
||||
{
|
||||
std::fstream stream(filepath, std::ios::out|std::ios::binary);
|
||||
if (stream) {
|
||||
stream.write((char*)this->mem, MEMORY_SIZE);
|
||||
this->snapshotError = "";
|
||||
std::time_t res = std::time(nullptr);
|
||||
this->snapshotLast = std::ctime(&res);
|
||||
stream.close();
|
||||
return 1;
|
||||
} else {
|
||||
std::cerr << "Error: could not write RAM contents to filepath " << filepath << std::endl;
|
||||
this->snapshotError = "Error: could not write RAM contents to filepath " + filepath;
|
||||
return 0;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue