shithub: zelda3

Download patch

ref: 9c27ead94bfb768319d667d90a0e4ee41ecb4cb5
parent: 4a1b6ea93ac72c1abd6890f59c6b5d5c5a32f0af
author: Nutzzz <[email protected]>
date: Sat Sep 10 03:22:20 EDT 2022

Add additional options to .ini file (#39)

Config: autosave
Graphics: fullscreen, zoom
Sound: frequency, channels, samples

Co-authored-by: snesrev <[email protected]>

--- a/config.c
+++ b/config.c
@@ -190,6 +190,10 @@
     return 0;
   if (StringEqualsNoCase(s, "[Graphics]"))
     return 1;
+  if (StringEqualsNoCase(s, "[Sound]"))
+    return 2;
+  if (StringEqualsNoCase(s, "[Config]"))
+    return 3;
   return -1;
 }
 
@@ -204,15 +208,37 @@
     }
   } else if (section == 1) {
     if (StringEqualsNoCase(key, "EnhancedMode7")) {
-      g_config.enhanced_mode7 = atoi(value);
+      g_config.enhanced_mode7 = (bool)strtol(value, (char**)NULL, 10);
       return true;
     } else if (StringEqualsNoCase(key, "NewRenderer")) {
-      g_config.new_renderer = atoi(value);
+      g_config.new_renderer = (bool)strtol(value, (char**)NULL, 10);
       return true;
     } else if (StringEqualsNoCase(key, "IgnoreAspectRatio")) {
-      g_config.ignore_aspect_ratio = atoi(value);
+      g_config.ignore_aspect_ratio = (bool)strtol(value, (char**)NULL, 10);
       return true;
+    } else if (StringEqualsNoCase(key, "Fullscreen")) {
+      g_config.fullscreen = (uint8)strtol(value, (char**)NULL, 10);
+      return true;
+    } else if (StringEqualsNoCase(key, "Zoom")) {
+      g_config.zoom = (uint8)strtol(value, (char**)NULL, 10);
+      return true;
     }
+  } else if (section == 2) {
+    if (StringEqualsNoCase(key, "AudioFreq")) {
+      g_config.audio_freq = (uint16)strtol(value, (char**)NULL, 10);
+      return true;
+    } else if (StringEqualsNoCase(key, "AudioChannels")) {
+      g_config.audio_channels = (uint8)strtol(value, (char**)NULL, 10);
+      return true;
+    } else if (StringEqualsNoCase(key, "AudioSamples")) {
+      g_config.audio_samples = (uint16)strtol(value, (char**)NULL, 10);
+      return true;
+    }
+  } else if (section == 3) {
+    if (StringEqualsNoCase(key, "Autosave")) {
+      g_config.autosave = (bool)strtol(value, (char**)NULL, 10);
+      return true;
+    }
 
   }
   return false;
@@ -236,6 +262,23 @@
   if (length) *length = size;
   return buffer;
 }
+
+/*
+uint8 *WriteFile(const char *name) {
+  FILE *f = fopen(name, "w");
+  if (f == NULL)
+    return NULL;
+}
+
+void SaveConfigFile() {
+  uint8* file = ReadFile("zelda3.user.ini", NULL);
+  if (!file) {
+    file = ReadFile("zelda3.ini", NULL);
+    if (!file)
+      return;
+  }
+}
+*/
 
 void ParseConfigFile() {
   uint8 *file = ReadFile("zelda3.user.ini", NULL);
--- a/config.h
+++ b/config.h
@@ -36,6 +36,12 @@
   bool enhanced_mode7;
   bool new_renderer;
   bool ignore_aspect_ratio;
+  uint8 fullscreen;
+  uint8 zoom;
+  uint16 audio_freq;
+  uint8 audio_channels;
+  uint16 audio_samples;
+  bool autosave;
 } Config;
 
 extern Config g_config;
--- a/main.c
+++ b/main.c
@@ -50,7 +50,12 @@
 enum {
   kRenderWidth = 256 * 2,
   kRenderHeight = 224 * 2,
+  kDefaultFullscreen = 0,
   kDefaultZoom = 2,
+  kMaxZoom = 10,
+  kDefaultFreq = 44100,
+  kDefaultChannels = 2,
+  kDefaultSamples = 2048,
 };
 
 
@@ -58,7 +63,8 @@
 static SDL_Window *g_window;
 static SDL_Renderer *g_renderer;
 static uint8 g_paused, g_turbo = true, g_cursor = true;
-static int current_zoom = kDefaultZoom;
+static uint8 g_current_zoom;
+static uint8 g_samples_per_block;
 static uint8 g_gamepad_buttons;
 
 void NORETURN Die(const char *error) {
@@ -79,7 +85,7 @@
 void DoZoom(int zoom_step) {
   int screen = SDL_GetWindowDisplayIndex(g_window);
   if (screen < 0) screen = 0;
-  int max_zoom = kDefaultZoom * 5;
+  int max_zoom = kMaxZoom;
   SDL_Rect bounds;
   int bt = -1, bl, bb, br;
   // note this takes into effect Windows display scaling, i.e., resolution is divided by scale factor
@@ -95,8 +101,8 @@
     int mh = (bounds.h - bt - bb + (kRenderHeight / kDefaultZoom) / 4) / (kRenderHeight / kDefaultZoom);
     max_zoom = IntMin(mw, mh);
   }
-  int new_zoom = IntMax(IntMin(current_zoom + zoom_step, max_zoom), 1);
-  current_zoom = new_zoom;
+  int new_zoom = IntMax(IntMin(g_current_zoom + zoom_step, max_zoom), 1);
+  g_current_zoom = new_zoom;
   int w = new_zoom * (kRenderWidth / kDefaultZoom);
   int h = new_zoom * (kRenderHeight / kDefaultZoom);
   
@@ -116,15 +122,10 @@
 
 static SDL_HitTestResult HitTestCallback(SDL_Window *win, const SDL_Point *area, void *data) {
   uint32 flags = SDL_GetWindowFlags(win);
-  return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 && 
+  return ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 || (flags & SDL_WINDOW_FULLSCREEN) == 0) && 
          (SDL_GetModState() & KMOD_CTRL) != 0 ? SDL_HITTEST_DRAGGABLE : SDL_HITTEST_NORMAL;
 }
 
-enum {
-  kSampleRate = 44100,
-  kSnesSamplesPerBlock = (534 * kSampleRate) / 32000,
-};
-
 static bool RenderScreenWithPerf(uint8 *pixel_buffer, size_t pitch, uint32 render_flags) {
   bool rv;
   if (g_display_perf) {
@@ -151,6 +152,37 @@
   AfterConfigParse();
 
   g_ppu_render_flags = g_config.new_renderer * kPpuRenderFlags_NewRenderer | g_config.enhanced_mode7 * kPpuRenderFlags_4x4Mode7;
+  
+  if (g_config.fullscreen == 1)
+    g_win_flags ^= SDL_WINDOW_FULLSCREEN_DESKTOP;
+  else if (g_config.fullscreen == 2)
+    g_win_flags ^= SDL_WINDOW_FULLSCREEN;
+  uint8 z = g_config.zoom;
+  g_current_zoom = z > kMaxZoom ? kMaxZoom : z;
+  uint16 h = kRenderHeight;
+  uint16 w = kRenderWidth;
+  if (g_current_zoom > 0) {
+      w = kRenderWidth * g_current_zoom;
+      h = kRenderHeight * g_current_zoom;
+  } else {
+      w = kRenderWidth / 2;
+      h = kRenderHeight / 2;
+  }
+  
+  // audio_freq: power of 2 [Values higher than 48000 generally should not be used]
+  uint16 f = g_config.audio_freq;
+  if (f == 0 || f > 48000 || ((f & (f - 1)) != 0))
+      g_config.audio_freq = kDefaultFreq;
+  
+  // audio_channels: As of SDL 2.0, supported values are 1 (mono), 2 (stereo), 4 (quad), and 6 (5.1).
+  uint8 c = g_config.audio_channels;
+  if (c == 0 || c == 3 || c == 5 || c > 6)
+      g_config.audio_channels = kDefaultChannels;
+  
+  // audio_samples: power of 2
+  uint16 s = g_config.audio_samples;
+  if (s == 0 || ((s & (s - 1)) != 0))
+      g_config.audio_samples = kDefaultSamples;
 
   // set up SDL
   if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) != 0) {
@@ -178,14 +210,17 @@
     return 1;
   }
   SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
+  
+  SDL_SetWindowSize(window, w, h);
+  SDL_SetWindowPosition(g_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
 
   SDL_AudioSpec want, have;
   SDL_AudioDeviceID device;
   SDL_memset(&want, 0, sizeof(want));
-  want.freq = kSampleRate;
+  want.freq = g_config.audio_freq;
   want.format = AUDIO_S16;
-  want.channels = 2;
-  want.samples = 2048;
+  want.channels = g_config.audio_channels;
+  want.samples = g_config.audio_samples;
   want.callback = NULL; // use queue
   device = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
   if(device == 0) {
@@ -192,7 +227,8 @@
     printf("Failed to open audio device: %s\n", SDL_GetError());
     return 1;
   }
-  int16_t* audioBuffer = (int16_t * )malloc(kSnesSamplesPerBlock * 2 * sizeof(int16));
+  g_samples_per_block = (534 * g_config.audio_freq) / 32000;
+  int16_t* audioBuffer = (int16_t * )malloc(g_samples_per_block * 2 * sizeof(int16));
   SDL_PauseAudioDevice(device, 0);
 
   Snes *snes = snes_init(g_emulated_ram), *snes_run = NULL;
@@ -227,6 +263,9 @@
   uint32 curTick = 0;
   uint32 frameCtr = 0;
 
+  if (g_config.autosave)
+    SaveLoadSlot(kSaveLoad_Load, 0);
+
   while(running) {
     while(SDL_PollEvent(&event)) {
       switch(event.type) {
@@ -243,12 +282,12 @@
         HandleGamepadInput(event.cbutton.button, event.cbutton.state == SDL_PRESSED);
         break;
       case SDL_MOUSEWHEEL:
-        if ((g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 && event.wheel.y != 0 && SDL_GetModState() & KMOD_CTRL)
+        if (((g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 || (g_win_flags & SDL_WINDOW_FULLSCREEN) == 0) && event.wheel.y != 0 && SDL_GetModState() & KMOD_CTRL)
           DoZoom(event.wheel.y > 0 ? 1 : -1);
         break;
       case SDL_MOUSEBUTTONDOWN:
         if (event.button.button == SDL_BUTTON_LEFT && event.button.state == SDL_PRESSED && event.button.clicks == 2) {
-          if ((g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 && SDL_GetModState() & KMOD_SHIFT) {
+          if (((g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 || (g_win_flags & SDL_WINDOW_FULLSCREEN) == 0) && SDL_GetModState() & KMOD_SHIFT) {
             g_win_flags ^= SDL_WINDOW_BORDERLESS;
             SDL_SetWindowBordered(g_window, (g_win_flags & SDL_WINDOW_BORDERLESS) == 0);
           }
@@ -304,6 +343,8 @@
     }
 #endif
   }
+  if (g_config.autosave)
+    SaveLoadSlot(kSaveLoad_Save, 0);
   // clean snes
   snes_free(snes);
   // clean sdl
@@ -314,6 +355,7 @@
   SDL_DestroyRenderer(renderer);
   SDL_DestroyWindow(window);
   SDL_Quit();
+  //SaveConfigFile();
   return 0;
 }
 
@@ -325,12 +367,12 @@
     snes->apu->dsp->sampleOffset = 0;
   }
 
-  dsp_getSamples(GetDspForRendering(), audioBuffer, kSnesSamplesPerBlock);
+  dsp_getSamples(GetDspForRendering(), audioBuffer, g_samples_per_block);
 
   for (int i = 0; i < 10; i++) {
-    if (SDL_GetQueuedAudioSize(device) <= kSnesSamplesPerBlock * 4 * 6) {
+    if (SDL_GetQueuedAudioSize(device) <= g_samples_per_block * 4 * 6) {
       // don't queue audio if buffer is still filled
-      SDL_QueueAudio(device, audioBuffer, kSnesSamplesPerBlock * 4);
+      SDL_QueueAudio(device, audioBuffer, g_samples_per_block * 4);
       return;
     }
     SDL_Delay(1);
--- a/zelda3.ini
+++ b/zelda3.ini
@@ -1,7 +1,25 @@
+[Config]
+# Automatically save state on quit and reload on start
+Autosave = 0
+
+
 [Graphics]
+# Fullscreen mode (0=windowed, 1=desktop fullscreen, 2=fullscreen w/mode change)
+Fullscreen = 0
+# Window zoom (0=50%, 1=100%, 2=200%, 3=300%, etc.)
+Zoom = 2
 NewRenderer = 1
 EnhancedMode7 = 1
 IgnoreAspectRatio = 0
+
+
+[Sound]
+# DSP frequency in samples per second (power of 2; e.g., 48000, 44100, 22050, 11025)
+AudioFreq = 44100
+# number of separate sound channels (1=mono, 2=stereo)
+AudioChannels = 2
+# Audio buffer size in samples (power of 2; e.g., 4096, 2048, 1024) [try 1024 if sound is crackly]
+AudioSamples = 2048
 
 
 [KeyMap]