Initial Commit
This commit is contained in:
24
.github/workflows/build.yml
vendored
Normal file
24
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: Build NRO
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: devkitpro/devkita64:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Upload NRO
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: PatchExtractor-nro
|
||||||
|
path: "*.nro"
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 NiklasCFW
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
186
Makefile
Normal file
186
Makefile
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITPRO)/libnx/switch_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
APP_TITLE := PatchExtractor
|
||||||
|
APP_AUTHOR := NiklasCFW
|
||||||
|
APP_VERSION := 1.0.0
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 += $(INCLUDE) -D__SWITCH__
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS := -lminizip -lz -lnx
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS) $(LIBNX)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
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)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
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)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
28
README.md
Normal file
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# PatchExtractor
|
||||||
|
|
||||||
|
Nintendo Switch Homebrew App für [OmniNX OC](https://git.niklascfw.de/OmniNX/OmniNX) - entpackt SaltyNX/FPSLocker Patches automatisch auf die SD-Karte.
|
||||||
|
|
||||||
|
## Was macht die App?
|
||||||
|
|
||||||
|
1. Sucht nach `sd:/SaltySD/plugins/FPSLocker/patches.zip`
|
||||||
|
2. Entpackt alle Patches in das gleiche Verzeichnis (überschreibt existierende Dateien)
|
||||||
|
3. Löscht `patches.zip` nach erfolgreichem Entpacken
|
||||||
|
4. Löscht sich selbst (`sd:/switch/PatchExtractor.nro`)
|
||||||
|
|
||||||
|
## Nutzung
|
||||||
|
|
||||||
|
Die App ist bereits in OmniNX OC enthalten und kann direkt aus Sphaira (hbmenu) gestartet werden.
|
||||||
|
|
||||||
|
## Selber bauen
|
||||||
|
|
||||||
|
Benötigt [devkitPro](https://devkitpro.org/) mit libnx, zlib und minizip.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DEVKITPRO=/opt/devkitpro
|
||||||
|
export PATH=$DEVKITPRO/devkitA64/bin:$DEVKITPRO/tools/bin:$PATH
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lizenz
|
||||||
|
|
||||||
|
MIT
|
||||||
199
source/main.c
Normal file
199
source/main.c
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <switch.h>
|
||||||
|
#include <minizip/unzip.h>
|
||||||
|
|
||||||
|
#define PATCHES_ZIP "sdmc:/SaltySD/plugins/FPSLocker/patches.zip"
|
||||||
|
#define EXTRACT_DIR "sdmc:/SaltySD/plugins/FPSLocker/"
|
||||||
|
#define SELF_NRO "sdmc:/switch/PatchExtractor.nro"
|
||||||
|
#define READ_BUF_SIZE 8192
|
||||||
|
|
||||||
|
#define STATUS_ROW 11
|
||||||
|
|
||||||
|
static PrintConsole *con;
|
||||||
|
|
||||||
|
static void status(const char *fmt, ...) {
|
||||||
|
printf("\x1b[%d;0H\x1b[2K", STATUS_ROW);
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vprintf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mkdirs(const char *path) {
|
||||||
|
char tmp[512];
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s", path);
|
||||||
|
size_t len = strlen(tmp);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
if (tmp[len - 1] == '/') tmp[len - 1] = '\0';
|
||||||
|
|
||||||
|
for (char *p = tmp + 1; *p; p++) {
|
||||||
|
if (*p == '/') {
|
||||||
|
*p = '\0';
|
||||||
|
mkdir(tmp, 0755);
|
||||||
|
*p = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mkdir(tmp, 0755);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
con = consoleInit(NULL);
|
||||||
|
|
||||||
|
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
|
||||||
|
PadState pad;
|
||||||
|
padInitializeDefault(&pad);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf(" ========================================\n");
|
||||||
|
printf(" PatchExtractor - OmniNX OC\n");
|
||||||
|
printf(" SaltyNX / FPSLocker Patch Installer\n");
|
||||||
|
printf(" ========================================\n\n");
|
||||||
|
|
||||||
|
unzFile zip = unzOpen(PATCHES_ZIP);
|
||||||
|
if (!zip) {
|
||||||
|
printf(" \x1b[31mFEHLER:\x1b[0m patches.zip nicht gefunden!\n\n");
|
||||||
|
printf(" Pfad: %s\n\n", PATCHES_ZIP);
|
||||||
|
printf(" Bist du sicher, dass du OmniNX OC installiert hast?\n\n");
|
||||||
|
printf(" Die Datei patches.zip muss unter\n");
|
||||||
|
printf(" sd:/SaltySD/plugins/FPSLocker/ liegen.\n\n");
|
||||||
|
printf(" ----------------------------------------\n");
|
||||||
|
printf(" Druecke + zum Beenden.\n");
|
||||||
|
|
||||||
|
while (appletMainLoop()) {
|
||||||
|
padUpdate(&pad);
|
||||||
|
if (padGetButtonsDown(&pad) & HidNpadButton_Plus) break;
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
}
|
||||||
|
consoleExit(NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unz_global_info gi;
|
||||||
|
unzGetGlobalInfo(zip, &gi);
|
||||||
|
unsigned long total = gi.number_entry;
|
||||||
|
printf(" patches.zip gefunden! (%lu Eintraege)\n", total);
|
||||||
|
printf(" Druecke A zum Entpacken, + zum Abbrechen.\n\n");
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
|
while (appletMainLoop()) {
|
||||||
|
padUpdate(&pad);
|
||||||
|
u64 kDown = padGetButtonsDown(&pad);
|
||||||
|
if (kDown & HidNpadButton_A) break;
|
||||||
|
if (kDown & HidNpadButton_Plus) {
|
||||||
|
unzClose(zip);
|
||||||
|
consoleExit(NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\x1b[10;0H \x1b[93mBitte nicht beenden, bis der Vorgang abgeschlossen ist!\x1b[0m\n");
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
|
char filename[512];
|
||||||
|
char fullpath[1024];
|
||||||
|
unsigned char buf[READ_BUF_SIZE];
|
||||||
|
unsigned long extracted = 0;
|
||||||
|
unsigned long skipped = 0;
|
||||||
|
int err = unzGoToFirstFile(zip);
|
||||||
|
|
||||||
|
while (err == UNZ_OK) {
|
||||||
|
unz_file_info fi;
|
||||||
|
unzGetCurrentFileInfo(zip, &fi, filename, sizeof(filename), NULL, 0, NULL, 0);
|
||||||
|
|
||||||
|
snprintf(fullpath, sizeof(fullpath), "%s%s", EXTRACT_DIR, filename);
|
||||||
|
unsigned long progress = (unsigned long)((extracted * 100) / total);
|
||||||
|
|
||||||
|
size_t flen = strlen(filename);
|
||||||
|
if (flen > 0 && filename[flen - 1] == '/') {
|
||||||
|
mkdirs(fullpath);
|
||||||
|
status(" [%3lu%%] DIR %s", progress, filename);
|
||||||
|
} else {
|
||||||
|
char dirpart[1024];
|
||||||
|
snprintf(dirpart, sizeof(dirpart), "%s", fullpath);
|
||||||
|
char *last_slash = strrchr(dirpart, '/');
|
||||||
|
if (last_slash) {
|
||||||
|
*last_slash = '\0';
|
||||||
|
mkdirs(dirpart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unzOpenCurrentFile(zip) != UNZ_OK) {
|
||||||
|
status(" [%3lu%%] \x1b[31mERR\x1b[0m %s", progress, filename);
|
||||||
|
skipped++;
|
||||||
|
extracted++;
|
||||||
|
err = unzGoToNextFile(zip);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *out = fopen(fullpath, "wb");
|
||||||
|
if (!out) {
|
||||||
|
status(" [%3lu%%] \x1b[31mERR\x1b[0m %s", progress, filename);
|
||||||
|
unzCloseCurrentFile(zip);
|
||||||
|
skipped++;
|
||||||
|
extracted++;
|
||||||
|
err = unzGoToNextFile(zip);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytes;
|
||||||
|
while ((bytes = unzReadCurrentFile(zip, buf, READ_BUF_SIZE)) > 0) {
|
||||||
|
fwrite(buf, 1, bytes, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
unzCloseCurrentFile(zip);
|
||||||
|
status(" [%3lu%%] FILE %s", progress, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
extracted++;
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
err = unzGoToNextFile(zip);
|
||||||
|
}
|
||||||
|
|
||||||
|
unzClose(zip);
|
||||||
|
|
||||||
|
status(" [100%%] Fertig! %lu / %lu entpackt.", extracted - skipped, total);
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
|
int cleanup_ok = 1;
|
||||||
|
|
||||||
|
printf("\x1b[%d;0H", STATUS_ROW + 2);
|
||||||
|
if (remove(PATCHES_ZIP) == 0) {
|
||||||
|
printf(" patches.zip geloescht.\n");
|
||||||
|
} else {
|
||||||
|
printf(" \x1b[31mpatches.zip konnte nicht geloescht werden.\x1b[0m\n");
|
||||||
|
cleanup_ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove(SELF_NRO) == 0) {
|
||||||
|
printf(" PatchExtractor.nro geloescht (Selbstreinigung).\n");
|
||||||
|
} else {
|
||||||
|
printf(" \x1b[31mPatchExtractor.nro konnte nicht geloescht werden.\x1b[0m\n");
|
||||||
|
cleanup_ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n ========================================\n");
|
||||||
|
if (skipped == 0 && cleanup_ok) {
|
||||||
|
printf(" \x1b[32mAlles erledigt!\x1b[0m\n");
|
||||||
|
} else {
|
||||||
|
printf(" \x1b[32mEntpacken abgeschlossen.\x1b[0m\n");
|
||||||
|
if (skipped > 0)
|
||||||
|
printf(" \x1b[31m%lu Eintraege fehlgeschlagen.\x1b[0m\n", skipped);
|
||||||
|
}
|
||||||
|
printf(" ========================================\n\n");
|
||||||
|
printf(" Druecke + zum Beenden.\n");
|
||||||
|
|
||||||
|
while (appletMainLoop()) {
|
||||||
|
padUpdate(&pad);
|
||||||
|
if (padGetButtonsDown(&pad) & HidNpadButton_Plus) break;
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleExit(NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user