Initial commit for 0.1 version

This commit is contained in:
suloku
2015-10-14 16:56:21 +02:00
parent 1a94106381
commit 870a91f72e
12 changed files with 937 additions and 2 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
build/
*.3dsx
*.exe
*.elf
*~

179
Makefile Normal file
View File

@@ -0,0 +1,179 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>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):
# - <Project name>.png
# - icon.png
# - <libctru folder>/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
#---------------------------------------------------------------------------------------

View File

@@ -1,2 +1,32 @@
# pdrpse
Pokémon Dream Radar Savegame Editor for 3DS
# Pok<EFBFBD>mon Dream Radar Pocket Save Editor
by suloku 2015
This is a very simple save editor for Pok<6F>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

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
icon.psd Normal file

Binary file not shown.

BIN
pdrpse.smdh Normal file

Binary file not shown.

3
pdrpse.xml Normal file
View File

@@ -0,0 +1,3 @@
<targets selectable="false">
<title mediatype="1">00040000000ae100</title>
</targets>

310
source/filesystem.c Normal file
View File

@@ -0,0 +1,310 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#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<size){ret=-3; goto loadFileExit;}
loadFileExit:
FSFILE_Close(fileHandle);
return ret;
}
// oh and let's add in a writeFile, because we kind of need that
Result writeFile(char* path, u8* data, u32 size, FS_archive* archive, Handle* fsHandle)
{
if(!path || !data)return -1;
Handle outFileHandle;
u32 bytesWritten;
Result ret = 0;
ret = FSUSER_OpenFile(fsHandle, &outFileHandle, *archive, FS_makePath(PATH_CHAR, path), FS_OPEN_CREATE | FS_OPEN_WRITE, FS_ATTRIBUTE_NONE);
if(ret!=0)return ret;
ret = FSFILE_Write(outFileHandle, &bytesWritten, 0x0, data, size, 0x10001);
if(ret!=0)return ret;
ret = FSFILE_Close(outFileHandle);
if(ret!=0)return ret;
if(archive==&saveGameArchive)
{
//printf("calling ControlArchive\n");
ret = FSUSER_ControlArchive(saveGameFsHandle, saveGameArchive);
}
return ret;
}
// I'll try deleting! that's a good trick!
Result deleteFile(char* path, FS_archive* archive, Handle* fsHandle)
{
if(!path || !archive)return -1;
Result ret = FSUSER_DeleteFile(fsHandle, *archive, FS_makePath(PATH_CHAR, path));
if(ret!=0)return ret;
if(archive==&saveGameArchive)
{
//printf("\ncalling ControlArchive\n");
ret = FSUSER_ControlArchive(saveGameFsHandle, saveGameArchive);
}
return ret;
}
u64 sizeFile(char* path, FS_archive* archive, Handle* fsHandle)
{
if(!path || !archive)return -1;
u64 size = -1;
Handle fileHandle;
Result ret=FSUSER_OpenFile(fsHandle, &fileHandle, *archive, FS_makePath(PATH_CHAR, path), FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret!=0)return -1;
ret=FSFILE_GetSize(fileHandle, &size);
if(ret!=0)return -1;
FSFILE_Close(fileHandle);
return size;
}
Result readBytesFromSaveFile(const char* filename, u64 offset, u8* buffer, u32 size)
{
Result ret;
Handle fileHandle;
ret=FSUSER_OpenFile(&saveGameFsHandle, &fileHandle, saveGameArchive, FS_makePath(PATH_CHAR, filename), FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret!=0)return ret;
ret=FSFILE_Read(fileHandle, NULL, offset, buffer, size);
if(ret!=0)return ret;
FSFILE_Close(fileHandle);
return ret;
}
Result writeBytesToSaveFile(const char* filename, u64 offset, u8* buffer, u32 size)
{
Result ret;
Handle fileHandle;
ret=FSUSER_OpenFile(&saveGameFsHandle, &fileHandle, saveGameArchive, FS_makePath(PATH_CHAR, filename), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
if(ret!=0)
return ret;
ret=FSFILE_Write(fileHandle, NULL, offset, buffer, size, 0x10001);
if(ret!=0)
return ret;
FSFILE_Close(fileHandle);
ret = FSUSER_ControlArchive(saveGameFsHandle, saveGameArchive);
return ret;
}
Result getSaveGameFileSize(const char* filename, u64* size)
{
Result ret;
Handle fileHandle;
ret=FSUSER_OpenFile(&saveGameFsHandle, &fileHandle, saveGameArchive, FS_makePath(PATH_CHAR, filename), FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret!=0)return ret;
ret=FSFILE_GetSize(fileHandle, size);
if(ret!=0)return ret;
FSFILE_Close(fileHandle);
if(*size)
return ret;
else
return -1;
}
Result doesFileNotExist(const char* filename, Handle* fsHandle, FS_archive archive)
{
Result ret;
Handle fileHandle;
u64 size;
ret=FSUSER_OpenFile(fsHandle, &fileHandle, archive, FS_makePath(PATH_CHAR, filename), FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret!=0)return ret;
ret=FSFILE_GetSize(fileHandle, &size);
if(ret!=0)return ret;
FSFILE_Close(fileHandle);
if(size)
return ret;
else
return -1;
}
int file_exist(const char * filename)
{
FILE * pFile;
long lSize;
char * buffer;
size_t result;
pFile = fopen ( filename , "rb" );
if (pFile==NULL) return 0;
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL) return 0;
result = fread (buffer,1,lSize,pFile);
if (result != lSize) return 0;
fclose (pFile);
free (buffer);
if (lSize > 0) return 1;
return 0;
}

21
source/filesystem.h Normal file
View File

@@ -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

295
source/main.c Normal file
View File

@@ -0,0 +1,295 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

77
source/text.c Normal file
View File

@@ -0,0 +1,77 @@
// some text routines from 3dsfindskitten
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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)<width)
{
printf(buffer);
putchar(' ');
break;
}
if(towrap[idx+width]==' ')
{
printf(buffer);
idx = idx + width;
} else {
lastSpc = lastSpace(buffer);
if (lastSpc>0)
{
for(i=0;i<lastSpc;i++)
{
putchar(buffer[i]);
idx++;
}
putchar('\n');
} else {
for(i=0;i<width-1;i++)
{
putchar(buffer[i]);
}
printf("- ");
idx = idx + width - 1;
}
}
}while (strlen(buffer)==width);
}

15
source/text.h Normal file
View File

@@ -0,0 +1,15 @@
#define TOP_WIDTH 50 // text columns
#define BOTTOM_WIDTH 40 // text columns
#define WIDTH BOTTOM_WIDTH
#define HEIGHT 30 // text rows
enum colour
{
BLACK, RED, GREEN, BROWN, INDIGO, PURPLE, TEAL, GREY,
DARKGREY, SALMON, NEONGREEN,YELLOW, BLUE, MAGENTA, CYAN, WHITE
}; // notice that 0-7 are normal intensity, 8-15 are bold intensity
void gotoxy(int x, int y);
void textcolour(enum colour c);
int lastSpace(char *tocut);
void wordwrap(char *towrap, int width);