diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85d966e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/ +*.3dsx +*.exe +*.elf +*~ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd3d0f6 --- /dev/null +++ b/Makefile @@ -0,0 +1,179 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/3ds_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 +# +# NO_SMDH: if set to anything, no SMDH file is generated. +# APP_TITLE is the name of the app stored in the SMDH file (Optional) +# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) +# APP_AUTHOR is the author of the app stored in the SMDH file (Optional) +# ICON is the filename of the icon (.png), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .png +# - icon.png +# - /default_icon.png +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include + +APP_TITLE := PDR Pocket Save Editor +APP_DESCRIPTION := A save editor for Pokemon Dream Radar +APP_AUTHOR := suloku +ICON := +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard + +CFLAGS := -g -Wall -O2 -mword-relocations \ + -fomit-frame-pointer -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM11 -D_3DS + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lctru -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CTRULIB) + + +#--------------------------------------------------------------------------------- +# 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 +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +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 $(ICON)),) + icons := $(wildcard *.png) + ifneq (,$(findstring $(TARGET).png,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).png + else + ifneq (,$(findstring icon.png,$(icons))) + export APP_ICON := $(TOPDIR)/icon.png + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_SMDH)),) + export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +ifeq ($(strip $(NO_SMDH)),) +$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh +else +$(OUTPUT).3dsx : $(OUTPUT).elf +endif + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +# WARNING: This is not the right way to do this! TODO: Do it right! +#--------------------------------------------------------------------------------- +%.vsh.o : %.vsh +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin + @bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@ + @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h + @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h + @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h + @rm ../$(notdir $<).shbin + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/README.md b/README.md index 67d1728..c145f05 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# pdrpse -PokĂ©mon Dream Radar Savegame Editor for 3DS +# Pokémon Dream Radar Pocket Save Editor +by suloku 2015 + +This is a very simple save editor for Pokémon Dream Radar, based on fylesystem.c and filesystem.h from meladroit's svdt, which is in turn based on ironhax installer by smea (aka sploit_installer). + +This editor allows to modify current orbs (the that can be used to buy), total collected orbs (shown in the records screen). +Also allows to modify the "current orb count for reward", which is the value that stores how many orbs were gathered since the last reward was received: + +Retrieval Extension: Obtain a total of 200 Dream Orbs +Eureka Extension A (Tornadus): Obtain a total of 400 Dream Orbs + +Dowsing Extension: Obtain a total of 700 Dream Orbs, catch Tornadus +Eureka Extension B (Thundurus): Obtain a total of 1500 Dream Orbs, catch Tornadus + +Eureka Extension G (Landorus): Obtain a total of 3000 Dream Orbs, catch Thundurus + +After the player catches Tornadus, Thundurs or Landorus, the "current orb count for reward" is reset to 0. This means that currently, to unlock all game content, one has to do the following: +1.- Set "current orb count for reward" to at least 400 +2.- Enter the game, Retrieval and Eureka A extensions are received +3.- Catch Tornadus, "current orb count for reward" is reset to 0. + +4.- Set "current orb count for reward" to at least 1500 +5.- Enter the game, Dowsing and Eureka B extensions are received +6.- Catch Thundurus, "current orb count for reward" is reset to 0. + +7.- Set "current orb count for reward" to at least 3000 +8.- Enter the game, Eureka G extensions is received +9.- After catching Landorus, the credits will roll and all left game content will be unlocked (simulator A, B and G will be received and gen IV extensions, if unlocked, will be available). + +It also allows to unlock the geneartion IV extensions, which can normally only be unlocked by inserting a gen IV DS cartridge in the 3DS console, and to re-catch those legendaries so they can be transfered to another Black2/White2 cartridge. + +See more information about the game at: http://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_Dream_Radar diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..5aa3b30 Binary files /dev/null and b/icon.png differ diff --git a/icon.psd b/icon.psd new file mode 100644 index 0000000..0afb8be Binary files /dev/null and b/icon.psd differ diff --git a/pdrpse.smdh b/pdrpse.smdh new file mode 100644 index 0000000..f83a337 Binary files /dev/null and b/pdrpse.smdh differ diff --git a/pdrpse.xml b/pdrpse.xml new file mode 100644 index 0000000..342a96a --- /dev/null +++ b/pdrpse.xml @@ -0,0 +1,3 @@ + + 00040000000ae100 + diff --git a/source/filesystem.c b/source/filesystem.c new file mode 100644 index 0000000..d070b9d --- /dev/null +++ b/source/filesystem.c @@ -0,0 +1,310 @@ +#include +#include +#include + +#include <3ds.h> + +#include "filesystem.h" + +Handle saveGameFsHandle, sdmcFsHandle; +FS_archive saveGameArchive, sdmcArchive; + +typedef struct lsLine +{ + FS_dirent thisLine; + struct lsLine* nextLine; +} lsLine; + +typedef struct lsDir +{ + struct lsLine* firstLine; + struct lsDir* parentDir; +} lsDir; + + +// bypass handle list +Result _srvGetServiceHandle(Handle* out, const char* name) +{ + Result rc = 0; + + u32* cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = 0x50100; + strcpy((char*) &cmdbuf[1], name); + cmdbuf[3] = strlen(name); + cmdbuf[4] = 0x0; + + if((rc = svcSendSyncRequest(*srvGetSessionHandle())))return rc; + + *out = cmdbuf[3]; + return cmdbuf[1]; +} + +Result filesystemInit() +{ + Result ret; + + ret = _srvGetServiceHandle(&saveGameFsHandle, "fs:USER"); + if(ret)return ret; + + ret = FSUSER_Initialize(&saveGameFsHandle); + if(ret)return ret; + + ret = srvGetServiceHandle(&sdmcFsHandle, "fs:USER"); + if(ret)return ret; + + saveGameArchive = (FS_archive){0x00000004, (FS_path){PATH_EMPTY, 1, (u8*)""}}; + ret = FSUSER_OpenArchive(&saveGameFsHandle, &saveGameArchive); + + sdmcArchive = (FS_archive){0x00000009, (FS_path){PATH_EMPTY, 1, (u8*)""}}; + ret = FSUSER_OpenArchive(&sdmcFsHandle, &sdmcArchive); + + return ret; +} + +Result filesystemExit() +{ + Result ret; + + ret = FSUSER_CloseArchive(&saveGameFsHandle, &saveGameArchive); + ret = FSUSER_CloseArchive(&sdmcFsHandle, &sdmcArchive); + ret = svcCloseHandle(saveGameFsHandle); + ret = svcCloseHandle(sdmcFsHandle); + + return ret; +} + +Result filesystemSoftReset() +{ + // exit and reinit without giving up those handles + Result ret; + + ret = FSUSER_CloseArchive(&saveGameFsHandle, &saveGameArchive); + ret = FSUSER_CloseArchive(&sdmcFsHandle, &sdmcArchive); + + saveGameArchive = (FS_archive){0x00000004, (FS_path){PATH_EMPTY, 1, (u8*)""}}; + ret = FSUSER_OpenArchive(&saveGameFsHandle, &saveGameArchive); + + sdmcArchive = (FS_archive){0x00000009, (FS_path){PATH_EMPTY, 1, (u8*)""}}; + ret = FSUSER_OpenArchive(&sdmcFsHandle, &sdmcArchive); + + return ret; +} + +Result FSUSER_ControlArchive(Handle handle, FS_archive archive) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + u32 b1 = 0, b2 = 0; + + cmdbuf[0]=0x080d0144; + cmdbuf[1]=archive.handleLow; + cmdbuf[2]=archive.handleHigh; + cmdbuf[3]=0x0; + cmdbuf[4]=0x1; //buffer1 size + cmdbuf[5]=0x1; //buffer1 size + cmdbuf[6]=0x1a; + cmdbuf[7]=(u32)&b1; + cmdbuf[8]=0x1c; + cmdbuf[9]=(u32)&b2; + + Result ret=0; + if((ret=svcSendSyncRequest(handle)))return ret; + + return cmdbuf[1]; +} + +/*Result FSUSER_GetMediaType(Handle handle, u8* mediatype) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=0x08680000; + + Result ret=0; + if((ret=svcSendSyncRequest(handle)))return ret; + + if(mediatype) + *mediatype = (u8)cmdbuf[2]; + + return cmdbuf[1]; +}*/ + +// let's add stuff from 3ds_hb_menu, just because +Result loadFile(char* path, void* dst, FS_archive* archive, Handle* fsHandle, u64 maxSize) +{ + // must malloc first! (and memset, if you'd like) + if(!path || !dst || !archive)return -1; + + u64 size; + u32 bytesRead; + Result ret; + Handle fileHandle; + + ret=FSUSER_OpenFile(fsHandle, &fileHandle, *archive, FS_makePath(PATH_CHAR, path), FS_OPEN_READ, FS_ATTRIBUTE_NONE); + if(ret!=0)return ret; + + ret=FSFILE_GetSize(fileHandle, &size); + if(ret!=0)goto loadFileExit; + if(size>maxSize){ret=-2; goto loadFileExit;} + + ret=FSFILE_Read(fileHandle, &bytesRead, 0x0, dst, size); + if(ret!=0)goto loadFileExit; + if(bytesRead 0) return 1; + return 0; +} diff --git a/source/filesystem.h b/source/filesystem.h new file mode 100644 index 0000000..326d898 --- /dev/null +++ b/source/filesystem.h @@ -0,0 +1,21 @@ +#ifndef FILESYSTEM_H +#define FILESYSTEM_H + +extern Handle saveGameFsHandle, sdmcFsHandle; +extern FS_archive saveGameArchive, sdmcArchive; + +Result filesystemInit(); +Result filesystemExit(); +Result filesystemSoftReset(); +Result FSUSER_ControlArchive(Handle handle, FS_archive archive); +//Result FSUSER_GetMediaType(Handle handle, u8* mediatype); +Result loadFile(char* path, void* dst, FS_archive* archive, Handle* fsHandle, u64 maxSize); +Result writeFile(char* path, u8* data, u32 size, FS_archive* archive, Handle* fsHandle); +Result deleteFile(char* path, FS_archive* archive, Handle* fsHandle); +u64 sizeFile(char* path, FS_archive* archive, Handle* fsHandle); +Result readBytesFromSaveFile(const char* filename, u64 offset, u8* buffer, u32 size); +Result writeBytesToSaveFile(const char* filename, u64 offset, u8* buffer, u32 size); +Result getSaveGameFileSize(const char* filename, u64* size); +Result doesFileNotExist(const char* filename, Handle* fsHandle, FS_archive archive); +int file_exist (const char *filename); +#endif diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..a1e7662 --- /dev/null +++ b/source/main.c @@ -0,0 +1,295 @@ +#include +#include +#include + +#include <3ds.h> + +#include "filesystem.h" +#include "text.h" + +#define bitcheck(x) (number >> x) & 1 + +int main(int argc, char**argv) +{ + + amInit(); + filesystemInit(); + + gfxInitDefault(); + //gfxSet3D(true); // uncomment if using stereoscopic 3D + consoleInit(GFX_TOP, NULL); +/* + //u8 mediatype; + u64 TID; + //FSUSER_GetMediaType(&saveGameFsHandle,&mediatype); + aptOpenSession(); + APT_GetProgramID(NULL, &TID); + aptCloseSession(); +*/ + printf("Pokemon Dream Radar Pocket Save Editor v0.1\n"); + printf("------------------------------by suloku '15\n\n"); + + int exitnow = 0; + + // Load savegame + u64 size; + u8* buffer = NULL; + //Try to open savefile + Result res = getSaveGameFileSize("/cygsavedata.dat",&size); + if (res != 0 ){ + printf ("Can't open cygsavedata.dat\n"); + exitnow = 1; + } else{ + buffer = (u8*)malloc(size); + res = readBytesFromSaveFile("/cygsavedata.dat",0,buffer,size); + if (res != 0 ){ + printf ("Failed to read cygsavedata.dat\n\n"); + exitnow = 1; + } + } + + //Save is loaded in buffer + + //Variables we'll modify + u32 orbs_cash; + u32 orbs_totalcol; + u32 orbs_reward; + u8 gen4ext; + u16 gen4catch; + + int save = 0; + + // Main loop + if (!exitnow){ + //Copy Data + memcpy (&orbs_cash, buffer+0x68, sizeof(u32)); + memcpy (&orbs_totalcol, buffer+0x6C, sizeof(u32)); + memcpy (&orbs_reward, buffer+0x288, sizeof(u32)); + memcpy (&gen4ext, buffer+0x26E, sizeof(u8)); + memcpy (&gen4catch, buffer+0x272, sizeof(u16)); + int cursor = 0; + while (aptMainLoop()) + { + gspWaitForVBlank(); + hidScanInput(); + gotoxy(0,0); + + printf("Pokemon Dream Radar Pocket Save Editor v0.1\n"); + printf("------------------------------by suloku '15\n\n"); + + printf ("\tOrbs Cash: %06lu \n", orbs_cash); + printf ("\tTotal Collected Orbs: %06lu \n", orbs_totalcol); + printf ("\tOrb count for next reward: %06lu \n", orbs_reward); + + printf ("\nGen IV Extension: 0x%02X - 0x%04X\n", gen4ext, gen4catch); + printf ("\tTemoral (Dialga): "); + if ((gen4ext & 0x4) >1) printf("unlocked - "); + else printf ("locked - "); + if ((gen4catch & 0x10) >1) printf("catched \n"); + else printf ("uncatched\n"); + printf ("\tSpatial (Palkia): "); + if ((gen4ext & 0x8) >1) printf("unlocked - "); + else printf ("locked - "); + if ((gen4catch & 0x20) >1) printf("catched \n"); + else printf ("uncatched\n"); + printf ("\tRenegade (Giratina): "); + if ((gen4ext & 0x10) >1) printf("unlocked - "); + else printf ("locked - "); + if ((gen4catch & 0x40) >1) printf("catched \n"); + else printf ("uncatched\n"); + printf ("\tRainbow (Ho-Oh): "); + if ((gen4ext & 0x20) >1) printf("unlocked - "); + else printf ("locked - "); + if ((gen4catch & 0x80) >1) printf("catched \n"); + else printf ("uncatched\n"); + printf ("\tDiving (Lugia): "); + if ((gen4ext & 0x40) >1) printf("unlocked - "); + else printf ("locked - "); + if ((gen4catch & 0x100) >1) printf("catched \n"); + else printf ("uncatched\n"); + + printf("\n\n\nControls:\n"); + if (cursor < 3){ + printf("\tLEFT/RIGHT: +-100 \n"); + printf("\tLEFT/RIGHT (hold R): +-1 \n"); + printf("\tLEFT/RIGHT (hold L): +-1000 \n"); + }else{ + printf("\tA: toogle all gen IV extensions \n"); + printf("\tY: toogle gen IV extensions \n"); + printf("\tB: toogle gen IV as catched/uncatched\n"); + } + + printf("\n\tX: unlock next reward\n"); + printf("\n\nPress START to exit\n"); + printf("Press SELECT to save & exit\n"); + + u32 kDown = hidKeysDown(); + u32 kHeld = hidKeysHeld(); + if (kDown & KEY_START) + break; // break in order to return to hbmenu + + if (kDown & KEY_SELECT){ + save = 1; + break; // save and exit + } + + if (kDown & KEY_DOWN){ + cursor++; + if (cursor > 7) cursor = 7; + } + if (kDown & KEY_UP){ + cursor--; + if (cursor < 1) cursor = 0; + } + + switch (cursor){ + case 0: + if (kDown & KEY_RIGHT && kHeld & KEY_R){ + orbs_cash++; + } else if (kHeld & KEY_RIGHT && !(kHeld & (KEY_R|KEY_L))){ + orbs_cash+=100; + } else if (kHeld & KEY_RIGHT && (kHeld & KEY_L)){ + orbs_cash+=1000; + } + if (orbs_cash > 999998) orbs_cash = 999999; + if (kDown & KEY_LEFT && kHeld & KEY_R){ + orbs_cash--; + } else if (kHeld & KEY_LEFT && !(kHeld & (KEY_R|KEY_L))){ + orbs_cash-=100; + } else if (kHeld & KEY_LEFT && (kHeld & KEY_L)){ + orbs_cash-=1000; + } + if (orbs_cash < 1 || orbs_cash > 999999) orbs_cash = 0; + break; + + case 1: + if (kDown & KEY_RIGHT && kHeld & KEY_R){ + orbs_totalcol++; + } else if (kHeld & KEY_RIGHT && !(kHeld & (KEY_R|KEY_L))){ + orbs_totalcol+=100; + } else if (kHeld & KEY_RIGHT && (kHeld & KEY_L)){ + orbs_totalcol+=1000; + } + if (orbs_totalcol > 999998) orbs_totalcol = 999999; + if (kDown & KEY_LEFT && kHeld & KEY_R){ + orbs_totalcol--; + } else if (kHeld & KEY_LEFT && !(kHeld & (KEY_R|KEY_L))){ + orbs_totalcol-=100; + } else if (kHeld & KEY_LEFT && (kHeld & KEY_L)){ + orbs_totalcol-=1000; + } + if (orbs_totalcol < 1 || orbs_totalcol > 999999) orbs_totalcol = 0; + break; + + case 2: + if (kDown & KEY_RIGHT && kHeld & KEY_R){ + orbs_reward++; + } else if (kHeld & KEY_RIGHT && !(kHeld & (KEY_R|KEY_L))){ + orbs_reward+=100; + } else if (kHeld & KEY_RIGHT && (kHeld & KEY_L)){ + orbs_reward+=1000; + } + if (orbs_reward > 999998) orbs_reward = 999999; + if (kDown & KEY_LEFT && kHeld & KEY_R){ + orbs_reward--; + } else if (kHeld & KEY_LEFT && !(kHeld & (KEY_R|KEY_L))){ + orbs_reward-=100; + } else if (kHeld & KEY_LEFT && (kHeld & KEY_L)){ + orbs_reward-=1000; + } + if (orbs_reward < 1 || orbs_reward > 999999) orbs_reward = 0; + break; + } + + if (kDown & KEY_X){ + orbs_reward = 3000; + } + if (kDown & KEY_A){ + //Disable if there's one enabled + if (gen4ext & 0x7C){ + gen4ext &= ~0x7C; + //And disable catched flags + gen4catch &= ~0x10; + gen4catch &= ~0x20; + gen4catch &= ~0x40; + gen4catch &= ~0x80; + gen4catch &= ~0x100; + }else //enable all + gen4ext |= 0x7C; + } + if (kDown & KEY_Y){ + if (cursor == 3) gen4ext ^= 0x4; + if (cursor == 4) gen4ext ^= 0x8; + if (cursor == 5) gen4ext ^= 0x10; + if (cursor == 6) gen4ext ^= 0x20; + if (cursor == 7) gen4ext ^= 0x40; + //Disable catched if unlocked + if (!(gen4ext & 0x4)) gen4catch &= ~0x10; + if (!(gen4ext & 0x8)) gen4catch &= ~0x20; + if (!(gen4ext & 0x10)) gen4catch &= ~0x40; + if (!(gen4ext & 0x20)) gen4catch &= ~0x80; + if (!(gen4ext & 0x40)) gen4catch &= ~0x100; + + } + if (kDown & KEY_B){ + if (gen4ext & 0x4 && cursor == 3) gen4catch ^= 0x10; + if (gen4ext & 0x8 && cursor == 4) gen4catch ^= 0x20; + if (gen4ext & 0x10 && cursor == 5) gen4catch ^= 0x40; + if (gen4ext & 0x20 && cursor == 6) gen4catch ^= 0x80; + if (gen4ext & 0x40 && cursor == 7) gen4catch ^= 0x100; + } + + gotoxy(0, 3); printf (" "); + gotoxy(0, 4); printf (" "); + gotoxy(0, 5); printf (" "); + gotoxy(0, 8); printf (" "); + gotoxy(0, 9); printf (" "); + gotoxy(0, 10); printf (" "); + gotoxy(0, 11); printf (" "); + gotoxy(0, 12); printf (" "); + if (cursor < 3) + gotoxy(0, 3+cursor); + else if (cursor > 2) + gotoxy(0, 3+cursor+2); + printf(">>"); + + //if (kHeld || kDown) consoleClear(); + // Flush and swap framebuffers + gfxFlushBuffers(); + gfxSwapBuffers(); + } + }else{ + printf("\nPress START to exit.\n"); + while(aptMainLoop()){ + gspWaitForVBlank(); + hidScanInput(); + + u32 kDown = hidKeysDown(); + if (kDown & KEY_START) + break; // break in order to return to hbmenu + + // Flush and swap framebuffers + gfxFlushBuffers(); + gfxSwapBuffers(); + } + } + + if (save){ + //set data to buffer + memcpy (buffer+0x68, &orbs_cash, sizeof(u32)); + memcpy (buffer+0x6C, &orbs_totalcol, sizeof(u32)); + memcpy (buffer+0x288, &orbs_reward, sizeof(u32)); + memcpy (buffer+0x26E, &gen4ext, sizeof(u8)); + memcpy (buffer+0x272, &gen4catch, sizeof(u16)); + // Save savegame + res = writeBytesToSaveFile("/cygsavedata.dat", 0, buffer, size); + } + + if (buffer != NULL) free(buffer); + + filesystemExit(); + amExit(); + gfxExit(); + + return 0; +} diff --git a/source/text.c b/source/text.c new file mode 100644 index 0000000..e66f74e --- /dev/null +++ b/source/text.c @@ -0,0 +1,77 @@ +// some text routines from 3dsfindskitten +#include +#include +#include +#include "text.h" + +void gotoxy(int x, int y) +{ + // in other words, move to row y, column x + // (both zero-indexed!) + printf("\x1b[0m"); + printf("\x1b[%d;%dH",y,x); +} + +void textcolour(enum colour c) +{ + printf("\x1b[0m"); + if(c>>3) // i.e. if normal intensity + { + printf("\x1b[3%d;1m",c%8); + } + else + { + printf("\x1b[3%dm",c%8); + } +} + +int lastSpace(char *tocut) +{ + char *lastSpace; + lastSpace = strrchr(tocut,' '); + if(lastSpace) + { + return (int)(lastSpace-tocut); + } else { return -1; } +} + +void wordwrap(char *towrap, int width) +{ + int idx = 0; + int i, lastSpc; + char* buffer = (char*)malloc(width+1); + memset(buffer,0,width+1); + do + { + strncpy(buffer,towrap+idx,width); + if(strlen(buffer)0) + { + for(i=0;i