shithub: zelda3

Download patch

ref: f9ad22ef4a202c657b97e39c04223cae7622dbb8
parent: 3ff9bf7d5d62220a7c8dbe3067dd613b0df56e78
author: KiritoDev <36680385+KiritoDv@users.noreply.github.com>
date: Sun Oct 2 13:29:41 EDT 2022

Added switch support (#133)


--- a/.gitignore
+++ b/.gitignore
@@ -27,4 +27,4 @@
 /tables/zelda3_assets.dat
 /third_party/tcc/
 /third_party/SDL2-2.24.0/
-/SDL2.dll
+/SDL2.dll
\ No newline at end of file
--- a/config.c
+++ b/config.c
@@ -71,7 +71,7 @@
 
 bool KeyMapHash_Add(uint16 key, uint16 cmd) {
   if ((keymap_hash_size & 0xff) == 0) {
-    if (keymap_hash_size > 10000) 
+    if (keymap_hash_size > 10000)
       Die("Too many keys");
     keymap_hash = realloc(keymap_hash, sizeof(KeyMapHashEnt) * (keymap_hash_size + 256));
   }
@@ -232,7 +232,22 @@
       }
     }
   } else if (section == 1) {
-    if (StringEqualsNoCase(key, "EnhancedMode7")) {
+    if (StringEqualsNoCase(key, "WindowSize")) {
+      char *s;
+      if (StringEqualsNoCase(value, "Auto")){
+        g_config.window_width  = 0;
+        g_config.window_height = 0;
+        return true;
+      }
+      while ((s = NextDelim(&value, 'x')) != NULL) {
+        if(g_config.window_width == 0) {
+          g_config.window_width = atoi(s);
+        } else {
+          g_config.window_height = atoi(s);
+          return true;
+        }
+      }
+    } else if (StringEqualsNoCase(key, "EnhancedMode7")) {
       return ParseBool(value, &g_config.enhanced_mode7);
     } else if (StringEqualsNoCase(key, "NewRenderer")) {
       return ParseBool(value, &g_config.new_renderer);
--- a/config.h
+++ b/config.h
@@ -35,6 +35,8 @@
 };
 
 typedef struct Config {
+  int window_width;
+  int window_height;
   bool enhanced_mode7;
   bool new_renderer;
   bool ignore_aspect_ratio;
--- a/main.c
+++ b/main.c
@@ -98,7 +98,7 @@
   g_current_window_scale = new_scale;
   int w = new_scale * (g_snes_width / kDefaultWindowScale);
   int h = new_scale * (g_snes_height / kDefaultWindowScale);
-  
+
   //SDL_RenderSetLogicalSize(g_renderer, w, h);
   SDL_SetWindowSize(g_window, w, h);
   if (bt >= 0) {
@@ -115,7 +115,7 @@
 
 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 || (flags & SDL_WINDOW_FULLSCREEN) == 0) && 
+  return ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 || (flags & SDL_WINDOW_FULLSCREEN) == 0) &&
          (SDL_GetModState() & KMOD_CTRL) != 0 ? SDL_HITTEST_DRAGGABLE : SDL_HITTEST_NORMAL;
 }
 
@@ -197,7 +197,6 @@
   LoadAssets();
   LoadLinkGraphics();
 
-
   ZeldaInitialize();
   g_zenv.ppu->extraLeftRight = UintMin(g_config.extended_aspect_ratio, kPpuExtraLeftRight);
   g_snes_width = 2 * (g_config.extended_aspect_ratio * 2 + 256);
@@ -224,11 +223,11 @@
   // audio_freq: Use common sampling rates (see user config file. values higher than 48000 are not supported.)
   if (g_config.audio_freq < 11025 || g_config.audio_freq > 48000)
     g_config.audio_freq = kDefaultFreq;
-  
-  // Currently, the SPC/DSP implementation �only supports up to stereo.
+
+  // Currently, the SPC/DSP implementation only supports up to stereo.
   if (g_config.audio_channels < 1 || g_config.audio_channels > 2)
     g_config.audio_channels = kDefaultChannels;
-  
+
   // audio_samples: power of 2
   if (g_config.audio_samples <= 0 || ((g_config.audio_samples & (g_config.audio_samples - 1)) != 0))
     g_config.audio_samples = kDefaultSamples;
@@ -239,8 +238,10 @@
     return 1;
   }
 
-  int window_width = g_current_window_scale * (g_snes_width / kDefaultWindowScale);
-  int window_height = g_current_window_scale * (g_snes_height / kDefaultWindowScale);
+  bool custom_size  = g_config.window_width != 0 && g_config.window_height != 0;
+  int window_width  = custom_size ? g_config.window_width  : g_current_window_scale * (g_snes_width / kDefaultWindowScale);
+  int window_height = custom_size ? g_config.window_height : g_current_window_scale * (g_snes_height / kDefaultWindowScale);
+
   SDL_Window* window = SDL_CreateWindow(kWindowTitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, g_win_flags);
   if(window == NULL) {
     printf("Failed to create window: %s\n", SDL_GetError());
@@ -544,7 +545,7 @@
       ZeldaReset(true);
       break;
     case kKeys_Pause: g_paused = !g_paused; break;
-    case kKeys_PauseDimmed: 
+    case kKeys_PauseDimmed:
       g_paused = !g_paused;
       if (g_paused) {
         SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_BLEND);
@@ -719,4 +720,3 @@
     offset += size;
   }
 }
-
--- /dev/null
+++ b/platform/switch/.gitignore
@@ -1,0 +1,4 @@
+/bin
+/*.nacp
+/*.nro
+/*.elf
\ No newline at end of file
--- /dev/null
+++ b/platform/switch/Makefile
@@ -1,0 +1,218 @@
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+
+ifeq ($(strip $(DEVKITPRO)),)
+$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
+endif
+
+TOPDIR ?= $(CURDIR)
+include $(DEVKITPRO)/libnx/switch_rules
+
+#---------------------------------------------------------------------------------
+# TARGET is the name of the output
+# BUILD is the directory where object files & intermediate files will be placed
+# SOURCES is a list of directories containing source code
+# DATA is a list of directories containing data files
+# INCLUDES is a list of directories containing header files
+# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
+#
+# NO_ICON: if set to anything, do not use icon.
+# NO_NACP: if set to anything, no .nacp file is generated.
+# APP_TITLE is the name of the app stored in the .nacp file (Optional)
+# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
+# APP_VERSION is the version of the app stored in the .nacp file (Optional)
+# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
+# ICON is the filename of the icon (.jpg), relative to the project folder.
+#   If not set, it attempts to use one of the following (in this order):
+#     - <Project name>.jpg
+#     - icon.jpg
+#     - <libnx folder>/default_icon.jpg
+#
+# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder.
+#   If not set, it attempts to use one of the following (in this order):
+#     - <Project name>.json
+#     - config.json
+#   If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead
+#   of a homebrew executable (.nro). This is intended to be used for sysmodules.
+#   NACP building is skipped as well.
+#---------------------------------------------------------------------------------
+SRC_DIR     := ../..
+TARGET		:=	$(notdir $(CURDIR))
+BUILD		:=	bin
+SOURCES		:=  $(SRC_DIR) $(SRC_DIR)/snes
+INCLUDES	:=	include
+APP_TITLE   :=  The Legend of Zelda: A Link to the Past
+APP_AUTHOR  :=  snesrev & Lywx
+APP_VERSION :=  $(shell git rev-parse --short HEAD) $(shell git rev-parse --abbrev-ref HEAD)
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH	:=	-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
+
+CFLAGS	:=	-g -Wall -O2 -ffunction-sections \
+			$(ARCH) $(DEFINES)
+
+CFLAGS	+=	-D__SWITCH__ $(INCLUDE) -DSTBI_NO_THREAD_LOCALS `sdl2-config --cflags`
+
+CXXFLAGS	:= $(CFLAGS) -fno-rtti -fno-exceptions
+CFLAGS += -std=gnu11
+
+ASFLAGS	:=	-g $(ARCH)
+LDFLAGS	=	-specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
+
+LIBS :=  `$(PREFIX)pkg-config --libs sdl2` -lnx -lm
+
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS	:= $(PORTLIBS) $(LIBNX)
+
+#---------------------------------------------------------------------------------
+# no real need to edit anything past this point unless you need to add additional
+# rules for different file extensions
+#---------------------------------------------------------------------------------
+ifneq ($(BUILD),$(notdir $(CURDIR)))
+#---------------------------------------------------------------------------------
+
+export OUTPUT	:=	$(CURDIR)/$(TARGET)
+export TOPDIR	:=	$(CURDIR)
+
+export VPATH	:=	$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+			$(foreach dir,$(DATA),$(CURDIR)/$(dir))
+
+export DEPSDIR	:=	$(CURDIR)/$(BUILD)
+
+CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+export LD	:=	$(CXX)
+#---------------------------------------------------------------------------------
+
+export OFILES_BIN	:=	$(addsuffix .o,$(BINFILES))
+export OFILES_SRC	:=	$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+export OFILES 		:=	$(OFILES_BIN) $(OFILES_SRC)
+export HFILES_BIN	:=	$(addsuffix .h,$(subst .,_,$(BINFILES)))
+
+export INCLUDE	:=	$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+			$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+			-I$(CURDIR)/$(BUILD)
+
+export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+
+$(info $(OFILES))
+
+ifeq ($(strip $(CONFIG_JSON)),)
+	jsons := $(wildcard *.json)
+	ifneq (,$(findstring $(TARGET).json,$(jsons)))
+		export APP_JSON := $(TOPDIR)/$(TARGET).json
+	else
+		ifneq (,$(findstring config.json,$(jsons)))
+			export APP_JSON := $(TOPDIR)/config.json
+		endif
+	endif
+else
+	export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
+endif
+
+ifeq ($(strip $(ICON)),)
+	icons := $(wildcard *.jpg)
+	ifneq (,$(findstring $(TARGET).jpg,$(icons)))
+		export APP_ICON := $(TOPDIR)/$(TARGET).jpg
+	else
+		ifneq (,$(findstring icon.jpg,$(icons)))
+			export APP_ICON := $(TOPDIR)/icon.jpg
+		endif
+	endif
+else
+	export APP_ICON := $(TOPDIR)/$(ICON)
+endif
+
+ifeq ($(strip $(NO_ICON)),)
+	export NROFLAGS += --icon=$(APP_ICON)
+endif
+
+ifeq ($(strip $(NO_NACP)),)
+	export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
+endif
+
+ifneq ($(APP_TITLEID),)
+	export NACPFLAGS += --titleid=$(APP_TITLEID)
+endif
+
+ifneq ($(ROMFS),)
+	export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
+endif
+
+.PHONY: $(BUILD) clean all
+
+#---------------------------------------------------------------------------------
+all: $(BUILD)
+
+$(BUILD):
+	@[ -d $@ ] || mkdir -p $@
+	@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+
+#---------------------------------------------------------------------------------
+clean:
+	@echo clean ...
+ifeq ($(strip $(APP_JSON)),)
+	@rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
+else
+	@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
+endif
+
+
+#---------------------------------------------------------------------------------
+else
+.PHONY:	all
+
+DEPENDS	:=	$(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(APP_JSON)),)
+
+all	:	$(OUTPUT).nro
+
+ifeq ($(strip $(NO_NACP)),)
+$(OUTPUT).nro	:	$(OUTPUT).elf $(OUTPUT).nacp
+else
+$(OUTPUT).nro	:	$(OUTPUT).elf
+endif
+
+else
+
+all	:	$(OUTPUT).nsp
+
+$(OUTPUT).nsp	:	$(OUTPUT).nso $(OUTPUT).npdm
+
+$(OUTPUT).nso	:	$(OUTPUT).elf
+
+endif
+
+$(OUTPUT).elf	:	$(OFILES)
+
+$(OFILES_SRC)	: $(HFILES_BIN)
+
+#---------------------------------------------------------------------------------
+# you need a rule like this for each extension you use as binary data
+#---------------------------------------------------------------------------------
+%.bin.o	%_bin.h :	%.bin
+#---------------------------------------------------------------------------------
+	@echo $(notdir $<)
+	@$(bin2o)
+
+-include $(DEPENDS)
+
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
\ No newline at end of file
binary files /dev/null b/platform/switch/icon.jpg differ
--- /dev/null
+++ b/platform/switch/zelda3.ini
@@ -1,0 +1,126 @@
+[General]
+# Automatically save state on quit and reload on start
+Autosave = 0
+DisplayPerfInTitle = 0
+
+# Extended aspect ratio, either 16:9, 16:10, or 18:9. 4:3 means normal aspect ratio.
+# Add ", unchanged_sprites" to avoid changing sprite spawn/die behavior. Without this
+# replays will be incompatible.
+# Add ", no_visual_fixes" to avoid fixing some graphics glitches (for example with Cape).
+# It won't affect replays/game behavior but the memory compare will not work.
+# Add "extend_y, " right before the aspect radio specifier to display 240 lines instead of 224.
+ExtendedAspectRatio = 16:9
+
+
+[Graphics]
+# Window size ( Auto or WidthxHeight )
+WindowSize = 1280x720
+# Fullscreen mode (0=windowed, 1=desktop fullscreen, 2=fullscreen w/mode change)
+Fullscreen = 0
+# Window scale (1=100%, 2=200%, 3=300%, etc.)
+WindowScale = 1
+NewRenderer = 1
+EnhancedMode7 = 1
+IgnoreAspectRatio = 0
+
+# Enable this option to remove the sprite limits per scan line
+NoSpriteLimits = 1
+
+# Change the appearance of Link by loading a ZSPR file
+# See all sprites here: https://snesrev.github.io/sprites-gfx/snes/zelda3/link/
+# Download the files with "git clone https://github.com/snesrev/sprites-gfx.git"
+# LinkGraphics = sprites-gfx/snes/zelda3/link/sheets/megaman-x.2.zspr
+
+
+[Sound]
+EnableAudio = 1
+
+# DSP frequency in samples per second (e.g. 48000, 44100, 32000, 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]. The higher the more lag before you hear sounds.
+AudioSamples = 1024
+
+# Enable MSU support for audio. Files need to be in a subfolder, msu/alttp_msu-*.pcm
+# Only works with 44100 hz and 2 channels
+EnableMSU = 0
+
+
+[Features]
+# Item switch on L/R. Also allows reordering of items in inventory by pressing Y+direction
+# Hold X inside of the item selection screen to reassign the X key into a separate item slot.
+# When X is assigned to an item, the Select key is used to enter the map. Press Select inside
+# of the Start menu to see the old select options.
+ItemSwitchLR = 0
+
+# Allow turning while dashing
+TurnWhileDashing = 0
+
+# Allow mirror to be used to warp to the Dark World
+MirrorToDarkworld = 0
+
+# Collect items (like hearts) with sword instead of having to touch them
+CollectItemsWithSword = 0
+
+# Level 2-4 sword can be used to break pots
+BreakPotsWithSword = 0
+
+# Disable the low health beep
+DisableLowHealthBeep = 0
+
+# Avoid waiting too much at the start
+SkipIntroOnKeypress = 0
+
+# Display max rupees/bombs/arrows with orange/yellow color
+ShowMaxItemsInYellow = 0
+
+# Allows up to four bombs active at a time instead of two.
+MoreActiveBombs = 0
+
+# Can carry 9999 rupees instead of 999
+CarryMoreRupees = 0
+
+# Enable various zelda bug fixes
+MiscBugFixes = 0
+
+# Enable some more advanced zelda bugfixes that change game behavior
+GameChangingBugFixes = 0
+
+# Allow bird travel to be cancelled by hitting the X key
+CancelBirdTravel = 0
+
+
+[KeyMap]
+# Change what keyboard keys map to the joypad
+# Order: Up, Down, Left, Right, Select, Start, A, B, X, Y, L, R
+
+# This default is suitable for QWERTY keyboards.
+Controls = Up, Down, Left, Right, Right Shift, Return, x, z, s, a, c, v
+
+# This default is suitable for QWERTZ keyboards.
+#Controls = Up, Down, Left, Right, Right Shift, Return, x, y, s, a, c, v
+
+# This one is suitable for AZERTY keyboards.
+#Controls = Up, Down, Left, Right, Right Shift, Return, x, w, s, q, c, v
+
+CheatLife = w
+CheatKeys = o
+CheatWalkThroughWalls = Ctrl+e
+ClearKeyLog = k
+StopReplay = l
+Fullscreen = Alt+Return
+Reset = Ctrl+r
+Pause = Shift+p
+PauseDimmed = p
+Turbo = Tab
+ReplayTurbo = t
+WindowBigger = Ctrl+Up
+WindowSmaller = Ctrl+Down
+
+Load =      F1,     F2,     F3,     F4,     F5,     F6,     F7,     F8,     F9,     F10
+Save = Shift+F1,Shift+F2,Shift+F3,Shift+F4,Shift+F5,Shift+F6,Shift+F7,Shift+F8,Shift+F9,Shift+F10
+Replay= Ctrl+F1,Ctrl+F2,Ctrl+F3,Ctrl+F4,Ctrl+F5,Ctrl+F6,Ctrl+F7,Ctrl+F8,Ctrl+F9,Ctrl+F10
+
+LoadRef = 1,2,3,4,5,6,7,8,9,0,-,=,Backspace
+ReplayRef = Ctrl+1,Ctrl+2,Ctrl+3,Ctrl+4,Ctrl+5,Ctrl+6,Ctrl+7,Ctrl+8,Ctrl+9,Ctrl+0,Ctrl+-,Ctrl+=,Ctrl+Backspace
--- a/zelda3.ini
+++ b/zelda3.ini
@@ -13,6 +13,8 @@
 
 
 [Graphics]
+# Window size ( Auto or WidthxHeight )
+WindowSize = Auto
 # Fullscreen mode (0=windowed, 1=desktop fullscreen, 2=fullscreen w/mode change)
 Fullscreen = 0
 # Window scale (1=100%, 2=200%, 3=300%, etc.)