diff --git a/file.cpp b/file.cpp new file mode 100644 index 0000000..4fbbdc7 --- /dev/null +++ b/file.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include "file.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#define DEFAULT_FILENAME "data.jf2" +#define DEFAULT_FOLDER "data/" +#define CONFIG_FILENAME "config.txt" + +namespace file +{ + struct file_t + { + std::string path; + uint32_t size; + uint32_t offset; + }; + + std::vector toc; + + /* El std::map me fa coses rares, vaig a usar un good old std::vector amb una estructura key,value propia i au, que sempre funciona */ + struct keyvalue_t { + std::string key, value; + }; + + char *resource_filename = NULL; + char *resource_folder = NULL; + int file_source = SOURCE_FILE; + char scratch[255]; + static std::string config_folder; + std::vector config; + + void setResourceFilename(const char *str) { + if (resource_filename != NULL) free(resource_filename); + resource_filename = (char*)malloc(strlen(str)+1); + strcpy(resource_filename, str); + } + + void setResourceFolder(const char *str) { + if (resource_folder != NULL) free(resource_folder); + resource_folder = (char*)malloc(strlen(str)+1); + strcpy(resource_folder, str); + } + + void setSource(const int src) { + file_source = src%2; // mod 2 so it always is a valid value, 0 (file) or 1 (folder) + if (src==SOURCE_FOLDER && resource_folder==NULL) setResourceFolder(DEFAULT_FOLDER); + } + + bool getDictionary() { + if (resource_filename == NULL) setResourceFilename(DEFAULT_FILENAME); + + std::ifstream fi (resource_filename, std::ios::binary); + if (!fi.is_open()) return false; + char header[4]; + fi.read(header, 4); + uint32_t num_files, toc_offset; + fi.read((char*)&num_files, 4); + fi.read((char*)&toc_offset, 4); + fi.seekg(toc_offset); + + for (uint i=0; ipw_dir; + config_folder = std::string(homedir) + "/Library/Application Support/" + foldername; + #elif __linux__ + struct passwd *pw = getpwuid(getuid()); + const char *homedir = pw->pw_dir; + config_folder = std::string(homedir) + "/." + foldername; + #endif + + struct stat st = {0}; + if (stat(config_folder.c_str(), &st) == -1) + { + #ifdef _WIN32 + int ret = mkdir(config_folder.c_str()); + #else + int ret = mkdir(config_folder.c_str(), S_IRWXU); + #endif + + if (ret == -1) + { + printf("ERROR CREATING CONFIG FOLDER."); + exit(EXIT_FAILURE); + } + } + } + + const char *getConfigFolder() { + std::string folder = config_folder + "/"; + return folder.c_str(); + } + + void loadConfigValues() { + config.clear(); + std::string config_file = config_folder + "/config.txt"; + FILE *f = fopen(config_file.c_str(), "r"); + if (!f) return; + + char line[1024]; + while (fgets(line, sizeof(line), f)) { + char *value = strchr(line, '='); + if (value) { + *value='\0'; value++; + value[strlen(value)-1] = '\0'; + config.push_back({line, value}); + } + } + fclose(f); + } + + void saveConfigValues() { + std::string config_file = config_folder + "/config.txt"; + FILE *f = fopen(config_file.c_str(), "w"); + if (f) { + for (auto pair : config) { + fprintf(f, "%s=%s\n", pair.key.c_str(), pair.value.c_str()); + } + fclose(f); + } + } + + const char* getConfigValueString(const char *key) { + if (config.empty()) loadConfigValues(); + for (auto pair : config) { + if (pair.key == std::string(key)) { + strcpy(scratch, pair.value.c_str()); + return scratch; + } + } + return NULL; + } + + const int getConfigValueInteger(const char *key, const int default_value) + { + const char* value = getConfigValueString(key); + if (!value) return default_value; + return atoi(value); + } + + const float getConfigValueFloat(const char *key, const float default_value) + { + const char* value = getConfigValueString(key); + if (!value) return default_value; + return atof(value); + } + + const bool getConfigValueBool(const char *key, const bool default_value) + { + const char* value = getConfigValueString(key); + if (!value) return default_value; + return strcmp(value, "true")==0?true:false; + } + + void setConfigValueString(const char* key, const char* value) { + if (config.empty()) loadConfigValues(); + for (auto &pair : config) { + if (pair.key == std::string(key)) { + pair.value = value; + saveConfigValues(); + return; + } + } + config.push_back({key, value}); + saveConfigValues(); + return; + } + + void setConfigValueInteger(const char* key, const int value) + { + char tmp[256]; + sprintf(tmp, "%i", value); + setConfigValueString(key, tmp); + } + + void setConfigValueFloat(const char* key, const float value) + { + char tmp[256]; + sprintf(tmp, "%.2f", value); + setConfigValueString(key, tmp); + } + + void setConfigValueBool(const char* key, const bool value) + { + setConfigValueString(key, value?"true":"false"); + } + +} diff --git a/file.h b/file.h new file mode 100644 index 0000000..863254a --- /dev/null +++ b/file.h @@ -0,0 +1,27 @@ +#pragma once +#include + +#define SOURCE_FILE 0 +#define SOURCE_FOLDER 1 + +namespace file +{ + void setConfigFolder(const char *foldername); + const char *getConfigFolder(); + + void setResourceFilename(const char *str); + void setResourceFolder(const char *str); + void setSource(const int src); + + FILE *getFilePointer(const char *resourcename, int& filesize, const bool binary=false); + char *getFileBuffer(const char *resourcename, int& filesize, const bool zero_terminate=false); + + const char* getConfigValueString(const char *key); + const int getConfigValueInteger(const char *key, const int default_value=0); + const float getConfigValueFloat(const char *key, const float default_value=0.0f); + const bool getConfigValueBool(const char *key, const bool default_value=false); + void setConfigValueString(const char* key, const char* value); + void setConfigValueInteger(const char* key, const int value); + void setConfigValueFloat(const char* key, const float value); + void setConfigValueBool(const char* key, const bool value); +} diff --git a/main.cpp b/main.cpp index 0ba403d..304aaed 100644 --- a/main.cpp +++ b/main.cpp @@ -21,6 +21,7 @@ //#include "zx_128pageviewer.h" #include "ay-3-8912.h" #include "ay_viewer.h" +#include "file.h" //uint8_t memory[65536]; uint32_t time = 0; @@ -84,6 +85,8 @@ int main(int argc, char *argv[]) const uint32_t clock = 3546900; const uint32_t update_freq = clock / 10; + file::setConfigFolder("z80"); + //new zx_48mem(); //new zx_128mem(); mem::init(ZX_128K); diff --git a/z80debug.cpp b/z80debug.cpp index 4b0b419..cafacd8 100644 --- a/z80debug.cpp +++ b/z80debug.cpp @@ -11,6 +11,7 @@ #include "ui_window.h" #include "zx_screen.h" #include "ay-3-8912.h" +#include "file.h" #define RESIZING_NONE 0 #define RESIZING_MEMORY 1 @@ -28,7 +29,7 @@ namespace z80debug int mem_h = 8; int con_h = 6; int sym_h = 14; - + int zoom = 1; int resizing_type = RESIZING_MEMORY; bool resizing = false; @@ -94,6 +95,15 @@ namespace z80debug return temp; } + void saveWindowConfiguration() + { + file::setConfigValueInteger("debug_zoom", zoom); + int x, y; + SDL_GetWindowPosition(win, &x, &y); + file::setConfigValueInteger("debug_x", x); + file::setConfigValueInteger("debug_y", y); + } + bool eventHandler(SDL_Event *e) { if (e->type == SDL_MOUSEMOTION) { @@ -104,7 +114,7 @@ namespace z80debug if ((e->window.event==SDL_WINDOWEVENT_SHOWN) || (e->window.event==SDL_WINDOWEVENT_EXPOSED)) { int w; int h; SDL_GetWindowSize(win, &w, &h); - w/=2; h/=2; + w/=zoom; h/=zoom; midx = (w/CHR_W) - 25; win_h = (h/CHR_H); mem_y = win_h - mem_h - con_h; @@ -115,6 +125,8 @@ namespace z80debug } else if (e->window.event == SDL_WINDOWEVENT_CLOSE) { hide(); zxscreen::focus(); + } else if (e->window.event == SDL_WINDOWEVENT_FOCUS_LOST) { + saveWindowConfiguration(); } } if (e->type == SDL_MOUSEWHEEL) { @@ -144,9 +156,15 @@ namespace z80debug z80debug::refresh(); z80analyze::refresh(); } else if (e->key.keysym.scancode==SDL_SCANCODE_F2) { - z80debug::history::goback(); - z80debug::refresh(); - z80analyze::refresh(); + if (e->key.keysym.mod & KMOD_CTRL) { + zoom = zoom==1?2:1; + hide(); + show(); + } else { + z80debug::history::goback(); + z80debug::refresh(); + z80analyze::refresh(); + } } else if (e->key.keysym.scancode==SDL_SCANCODE_F3) { z80debug::history::goforward(); z80debug::refresh(); @@ -333,7 +351,10 @@ namespace z80debug void show() { if (!win) { - win = SDL_CreateWindow("Z80 Debugger", 10, 50, 98*CHR_W*2, 44*CHR_H*2, SDL_WINDOW_SHOWN); + zoom = file::getConfigValueInteger("debug_zoom", 1); + const int x = file::getConfigValueInteger("debug_x", SDL_WINDOWPOS_UNDEFINED); + const int y = file::getConfigValueInteger("debug_y", SDL_WINDOWPOS_UNDEFINED); + win = SDL_CreateWindow("Z80 Debugger", x, y, 98*CHR_W*zoom, 44*CHR_H*zoom, SDL_WINDOW_SHOWN); ren = SDL_CreateRenderer(win, -1, 0); SDL_RenderSetLogicalSize(ren, 98*CHR_W, 44*CHR_H); ui::window::registerWindow(SDL_GetWindowID(win), eventHandler); @@ -353,6 +374,7 @@ namespace z80debug void hide() { + saveWindowConfiguration(); ui::window::unregisterWindow(SDL_GetWindowID(win)); if (tex) SDL_DestroyTexture(tex); if (ren) SDL_DestroyRenderer(ren); diff --git a/zx_screen.cpp b/zx_screen.cpp index 7f23c8d..b436408 100644 --- a/zx_screen.cpp +++ b/zx_screen.cpp @@ -7,6 +7,7 @@ #include "ui_window.h" #include "z80debug.h" #include "ui.h" +#include "file.h" //#include "zx_128mem.h" namespace zxscreen @@ -51,6 +52,15 @@ namespace zxscreen #define SCREEN_SYNC 0xFFFF #define SCREEN_BORDER 0xFFFE + void saveWindowConfiguration() + { + file::setConfigValueInteger("screen_zoom", zoom); + int x, y; + SDL_GetWindowPosition(win, &x, &y); + file::setConfigValueInteger("screen_x", x); + file::setConfigValueInteger("screen_y", y); + } + void create_tables() { uint32_t count = 0; @@ -119,7 +129,10 @@ namespace zxscreen //sprintf(tmp, " %ix%i", x, y); //setTitle(tmp); if (e->window.event==SDL_WINDOWEVENT_CLOSE) { + saveWindowConfiguration(); return false; + } else if (e->window.event==SDL_WINDOWEVENT_FOCUS_LOST || e->window.event==SDL_WINDOWEVENT_MOVED) { + saveWindowConfiguration(); } else if ((e->window.event==SDL_WINDOWEVENT_SHOWN) || (e->window.event==SDL_WINDOWEVENT_EXPOSED)) { redraw(); } @@ -160,6 +173,7 @@ namespace zxscreen void reinit() { + saveWindowConfiguration(); if (win) ui::window::unregisterWindow(SDL_GetWindowID(win)); if (tex) SDL_DestroyTexture(tex); @@ -167,8 +181,12 @@ namespace zxscreen if (ren) SDL_DestroyRenderer(ren); if (win) SDL_DestroyWindow(win); + zoom = file::getConfigValueInteger("screen_zoom", 1); + const int x = file::getConfigValueInteger("screen_x", SDL_WINDOWPOS_UNDEFINED); + const int y = file::getConfigValueInteger("screen_y", SDL_WINDOWPOS_UNDEFINED); + const int z = fullscreen ? 1 : zoom; - win = SDL_CreateWindow("ZX Spectrum Screen", 1216, 565, 352*z, 296*z, fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_ALLOW_HIGHDPI); + win = SDL_CreateWindow("ZX Spectrum Screen", x, y, 352*z, 296*z, fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_ALLOW_HIGHDPI); ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 352, 296); uitex = ui::createtexture(ren);