<commit_before>#include <nds.h>
#include <stdio.h>
#include <fat.h>
#include <vector>
#include <string>
#include "patches.h"
#include "drunkenlogo.h"

unsigned int rawDataOffset=0;

u8 workbuffer[1024] ALIGN(32);

#define SCREEN_COLS 32
#define ITEMS_PER_SCREEN 10
#define ITEMS_START_ROW 12
#define MAX_DATNAME_LEN 26

using namespace std;

struct patchEntry {
	string description;
	u32 fileoffset;
};

//---------------------------------------------------------------------------------
void halt() {
//---------------------------------------------------------------------------------
	int pressed;

	iprintf("      Press A to exit\n");

	while(1) {
		swiWaitForVBlank();
		scanKeys();
		pressed = keysDown();
		if (pressed & KEY_A) break;
	}
	exit(0);
}

//---------------------------------------------------------------------------------
void userSettingsCRC(void *buffer) {
//---------------------------------------------------------------------------------
	u16 *slot = (u16*)buffer;
	u16 CRC1 = swiCRC16(0xFFFF, slot, 0x70);
	u16 CRC2 = swiCRC16(0xFFFF, &slot[0x3a], 0x8A);
	slot[0x39] = CRC1; slot[0x7f] = CRC2;
}

/*
//---------------------------------------------------------------------------------
void saveFile(char *name, void *buffer, int size) {
//---------------------------------------------------------------------------------
	FILE *out = fopen(name,"wb");
	if (out) {
		fwrite(buffer, 1, 1024, out);
		fclose(out);
	} else {
		printf("couldn't open %s for writing\n",name);
	}
}
*/

//---------------------------------------------------------------------------------
void showPatchList (const vector<patchEntry>& patchList, const char* datName, int offset) {
//---------------------------------------------------------------------------------

	for (unsigned int i = 0; i < patchList.size() && i < ITEMS_PER_SCREEN; i++) {
		const patchEntry* patch = &patchList.at(i);

		// Set row
		iprintf ("\x1b[%d;5H", i + ITEMS_START_ROW + offset);
		iprintf ("%s", patch->description.c_str());
		iprintf (datName);
	}
}

void aread( void * ptr, size_t size, size_t count, int stream ){  // 'array read' drop in substitute for fread

	size=0;
	stream=0;
	memcpy(ptr,&rawData[rawDataOffset],count);
	rawDataOffset+=count;
}

int aseek( int stream, int offset, int origin ){                  // 'array seek' drop in substitute for fseek

	origin=0;
	stream=0;
	rawDataOffset=offset;
	return 0;
}

int aeof(int stream){

	stream=0;
	int result=0;
	if(rawDataOffset >= fSIZE)result=1;
	return result;
}

int atell(int stream){
	return rawDataOffset;
}

char * agets( char * str, int num, int stream ){

	stream=0;
	memcpy(str,&rawData[rawDataOffset],num);
	return str;
}

//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
	videoSetMode(MODE_5_2D);                         //shamlessly ripped from the libnds examples :p
	videoSetModeSub(MODE_0_2D);
	vramSetBankA(VRAM_A_MAIN_BG);
	bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0,0);
	decompress(drunkenlogoBitmap, BG_GFX,  LZ77Vram);

	consoleDemoInit();

	iprintf("\n\n\n\n\n\n");
	iprintf("   >> Cakes ROP Installer <<  \n");
	iprintf("\n\n");

	int patchfile = 0;
	int header;
	rawDataOffset=0;
	char datName[MAX_DATNAME_LEN]="YS:/" DATNAME;
	char custom[6][35];

	aread(&header,1,4,patchfile);

	if ( header != 'ROPP') {
		iprintf("      Invalid patch file!\n");
		halt();
	}

	int index_offset;
	aread(&index_offset,1,4,patchfile);

	aseek(patchfile,index_offset,SEEK_SET);

	vector<patchEntry> patches;
	patchEntry patch;

	while(1) {
		patch.description.clear();
		int string_offset;

		aread(&string_offset,1,4,patchfile);
		if (aeof(patchfile)) break;

		aread(&patch.fileoffset,1,4,patchfile);

		// save file pointer
		int file_ptr = atell(patchfile);

		aseek(patchfile,string_offset,SEEK_SET);

		char description[21];

		char *desc = agets(description, 20, patchfile);

		if (desc == NULL ) {
			iprintf("      Failed reading description\n");
			halt();
		}

		// terminate string
		description[20] = 0;
		patch.description = description;
		patches.push_back(patch);

		// restore file pointer for next offset
		aseek(patchfile,file_ptr,SEEK_SET);
	}

	int pressed,fwSelected=0,screenOffset=0;
	// Default Cakes.dat + custom
	int patch_count = patches.size() * 2;

	showPatchList(patches, DISPNAME, 0);
	showPatchList(patches, "ropCustom.txt", patches.size());

	while(1) {

		// Show cursor
		iprintf ("\x1b[%d;3H[>\x1b[21C<]", fwSelected - screenOffset + ITEMS_START_ROW);

		// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
		do {
			scanKeys();
			pressed = keysDownRepeat();
			swiWaitForVBlank();
		} while (!pressed);

		// Hide cursor
		iprintf ("\x1b[%d;3H  \x1b[21C  ", fwSelected - screenOffset + ITEMS_START_ROW);
		if (pressed & KEY_UP) 		fwSelected -= 1;
		if (pressed & KEY_DOWN) 	fwSelected += 1;

		if (pressed & KEY_A) break;

		if (fwSelected < 0) 	fwSelected = patch_count - 1;		// Wrap around to bottom of list
		if (fwSelected > (patch_count - 1))		fwSelected = 0;		// Wrap around to top of list

	}

	iprintf ("\x1b[5;0H\x1b[J");

    const patchEntry *selectedPatch;
    if (fwSelected < (int)patches.size()) {
	    selectedPatch = &patches.at(fwSelected);
    } else {
        selectedPatch = &patches.at(fwSelected - (patch_count - patches.size()));
    }

	iprintf("Patching for %s\n\n",selectedPatch->description.c_str());

	// read header
	readFirmware(0,workbuffer,42);

	u32 userSettingsOffset = (workbuffer[32] + (workbuffer[33] << 8))<<3;

	// read User Settings
	readFirmware(userSettingsOffset,workbuffer,512);

	aseek(patchfile,selectedPatch->fileoffset,SEEK_SET);
	aread(&header,1,4,patchfile);

	if (header != 'PTCH' ) {

			printf("      Patch set invalid\n");
			halt();

	} else {

		int32_t numPatches;
		uint32_t patchSize,patchOffset;
		aread(&numPatches,1,4,patchfile);

		uint32_t patchOffsetList[numPatches];
		aread(patchOffsetList,1,sizeof(patchOffsetList),patchfile);

		for (int i=0; i<numPatches; i++) {

			aseek(patchfile,patchOffsetList[i],SEEK_SET);
			aread(&patchSize,1,4,patchfile);
			aread(&patchOffset,1,4,patchfile);
			aread(&workbuffer[patchOffset],1,patchSize,patchfile);

		}
	}

	if (fwSelected < (int)patches.size()) {
		for(int i = 0;i < MAX_DATNAME_LEN * 2;i += 2){
			*(workbuffer + 0x11C + i) = datName[i / 2];
			*(workbuffer + 0x11C + i + 1) = 0;
		}
	} else {
		// Load filename from ropCustom.txt
		int csSelected=0;  //custom selected
		int customLinesTotal=6;
		int i=0;
		char pathBegin[]="YS:/";

		if(!fatInitDefault()){
			iprintf("      fat init error\n");
			halt();
		}

		FILE *text=fopen("ropCustom.txt","r");

		if(!text){
			iprintf("      ropCustom.txt load error\n      Does it exist?\n\n");
			halt();
		}

		for(i=0;i<customLinesTotal;i++){
			fgets(custom[i],30,text);
			if(!custom[i] || (custom[i][0] < 0x21) )break;

			for(int j=0; j < 30 ;j++){  //strip newline junk
				if(custom[i][j]==0x0D || custom[i][j]==0x0A)
					custom[i][j]=0;
			}
			custom[i][25]=0;    //make damn sure it terminates
		}
		if(i==0){
			iprintf("      ropCustom.txt read error\n");
			iprintf("      invalid first line path\n");
			halt();
		}

		customLinesTotal=i;

		fclose(text);

		iprintf("\x1b[2J"); //clear console
		iprintf("Custom filename list:");

		for(i=0;i<customLinesTotal;i++){
			iprintf ("\x1b[%d;3H", i + ITEMS_START_ROW -8);
			iprintf ("%s", custom[i]);
		}

		while(1) {

			// Show cursor
			iprintf ("\x1b[%d;0H[>", csSelected - screenOffset + ITEMS_START_ROW -8);

			// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
			do {
				scanKeys();
				pressed = keysDownRepeat();
				swiWaitForVBlank();
			} while (!pressed);

			// Hide cursor
			iprintf ("\x1b[%d;0H  ", csSelected - screenOffset + ITEMS_START_ROW -8);
			if (pressed & KEY_UP) 		csSelected -= 1;
			if (pressed & KEY_DOWN) 	csSelected += 1;

			if (pressed & KEY_A) break;

			if (csSelected < 0) 	csSelected =  customLinesTotal - 1;		// Wrap around to bottom of list
			if (csSelected > (customLinesTotal - 1))		csSelected = 0;		// Wrap around to top of list

		}

		for(int i = 0; i < 4 * 2 ;i += 2){
			*(workbuffer + 0x11C + i) = pathBegin[i / 2];
			*(workbuffer + 0x11C + i + 1) = 0;
		}

		for(int i = 0; i < (MAX_DATNAME_LEN - 4) * 2;i += 2){
			*(workbuffer + 0x124 + i) = custom[csSelected][i / 2];
			*(workbuffer + 0x124 + i + 1)=0;
		}

		*(workbuffer + 0x142)=0; //ensure terminated string (again)
		*(workbuffer + 0x143)=0;
    }

	userSettingsCRC(workbuffer);
	userSettingsCRC(workbuffer+256);

	iprintf("\n\n\n\n\n      Writing ... ");
	int ret = writeFirmware(userSettingsOffset,workbuffer,512);

	if (ret) {

		iprintf("failed\n");

	} else {

		iprintf("success\n");

	}

	iprintf("      Verifying ... ");
	readFirmware(userSettingsOffset,workbuffer+512,512);

	if (memcmp(workbuffer,workbuffer+512,512)){

		iprintf("failed\n");

	} else {

		iprintf("success\n");

	}

	halt();
	return 0;
}
<commit_msg>Fixing string termination and stuff.<commit_after>#include <nds.h>
#include <stdio.h>
#include <fat.h>
#include <vector>
#include <string>
#include "patches.h"
#include "drunkenlogo.h"

unsigned int rawDataOffset=0;

u8 workbuffer[1024] ALIGN(32);

#define SCREEN_COLS 32
#define ITEMS_PER_SCREEN 10
#define ITEMS_START_ROW 12
#define MAX_DATNAME_LEN 26

using namespace std;

struct patchEntry {
	string description;
	u32 fileoffset;
};

//---------------------------------------------------------------------------------
void halt() {
//---------------------------------------------------------------------------------
	int pressed;

	iprintf("      Press A to exit\n");

	while(1) {
		swiWaitForVBlank();
		scanKeys();
		pressed = keysDown();
		if (pressed & KEY_A) break;
	}
	exit(0);
}

//---------------------------------------------------------------------------------
void userSettingsCRC(void *buffer) {
//---------------------------------------------------------------------------------
	u16 *slot = (u16*)buffer;
	u16 CRC1 = swiCRC16(0xFFFF, slot, 0x70);
	u16 CRC2 = swiCRC16(0xFFFF, &slot[0x3a], 0x8A);
	slot[0x39] = CRC1; slot[0x7f] = CRC2;
}

/*
//---------------------------------------------------------------------------------
void saveFile(char *name, void *buffer, int size) {
//---------------------------------------------------------------------------------
	FILE *out = fopen(name,"wb");
	if (out) {
		fwrite(buffer, 1, 1024, out);
		fclose(out);
	} else {
		printf("couldn't open %s for writing\n",name);
	}
}
*/

//---------------------------------------------------------------------------------
void showPatchList (const vector<patchEntry>& patchList, const char* datName, int offset) {
//---------------------------------------------------------------------------------

	for (unsigned int i = 0; i < patchList.size() && i < ITEMS_PER_SCREEN; i++) {
		const patchEntry* patch = &patchList.at(i);

		// Set row
		iprintf ("\x1b[%d;5H", i + ITEMS_START_ROW + offset);
		iprintf ("%s", patch->description.c_str());
		iprintf (datName);
	}
}

void aread( void * ptr, size_t size, size_t count, int stream ){  // 'array read' drop in substitute for fread

	size=0;
	stream=0;
	memcpy(ptr,&rawData[rawDataOffset],count);
	rawDataOffset+=count;
}

int aseek( int stream, int offset, int origin ){                  // 'array seek' drop in substitute for fseek

	origin=0;
	stream=0;
	rawDataOffset=offset;
	return 0;
}

int aeof(int stream){

	stream=0;
	int result=0;
	if(rawDataOffset >= fSIZE)result=1;
	return result;
}

int atell(int stream){
	return rawDataOffset;
}

char * agets( char * str, int num, int stream ){

	stream=0;
	memcpy(str,&rawData[rawDataOffset],num);
	return str;
}

//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
	videoSetMode(MODE_5_2D);                         //shamlessly ripped from the libnds examples :p
	videoSetModeSub(MODE_0_2D);
	vramSetBankA(VRAM_A_MAIN_BG);
	bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0,0);
	decompress(drunkenlogoBitmap, BG_GFX,  LZ77Vram);

	consoleDemoInit();

	iprintf("\n\n\n\n\n\n");
	iprintf("   >> Cakes ROP Installer <<  \n");
	iprintf("\n\n");

	int patchfile = 0;
	int header;
	rawDataOffset=0;
	char datName[MAX_DATNAME_LEN]="YS:/" DATNAME;
	char custom[6][MAX_DATNAME_LEN-4]={};

	aread(&header,1,4,patchfile);

	if ( header != 'ROPP') {
		iprintf("      Invalid patch file!\n");
		halt();
	}

	int index_offset;
	aread(&index_offset,1,4,patchfile);

	aseek(patchfile,index_offset,SEEK_SET);

	vector<patchEntry> patches;
	patchEntry patch;

	while(1) {
		patch.description.clear();
		int string_offset;

		aread(&string_offset,1,4,patchfile);
		if (aeof(patchfile)) break;

		aread(&patch.fileoffset,1,4,patchfile);

		// save file pointer
		int file_ptr = atell(patchfile);

		aseek(patchfile,string_offset,SEEK_SET);

		char description[21];

		char *desc = agets(description, 20, patchfile);

		if (desc == NULL ) {
			iprintf("      Failed reading description\n");
			halt();
		}

		// terminate string
		description[20] = 0;
		patch.description = description;
		patches.push_back(patch);

		// restore file pointer for next offset
		aseek(patchfile,file_ptr,SEEK_SET);
	}

	int pressed,fwSelected=0,screenOffset=0;
	// Default Cakes.dat + custom
	int patch_count = patches.size() * 2;

	showPatchList(patches, DISPNAME, 0);
	showPatchList(patches, "ropCustom.txt", patches.size());

	while(1) {

		// Show cursor
		iprintf ("\x1b[%d;3H[>\x1b[21C<]", fwSelected - screenOffset + ITEMS_START_ROW);

		// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
		do {
			scanKeys();
			pressed = keysDownRepeat();
			swiWaitForVBlank();
		} while (!pressed);

		// Hide cursor
		iprintf ("\x1b[%d;3H  \x1b[21C  ", fwSelected - screenOffset + ITEMS_START_ROW);
		if (pressed & KEY_UP) 		fwSelected -= 1;
		if (pressed & KEY_DOWN) 	fwSelected += 1;

		if (pressed & KEY_A) break;

		if (fwSelected < 0) 	fwSelected = patch_count - 1;		// Wrap around to bottom of list
		if (fwSelected > (patch_count - 1))		fwSelected = 0;		// Wrap around to top of list

	}

	iprintf ("\x1b[5;0H\x1b[J");

    const patchEntry *selectedPatch;
    if (fwSelected < (int)patches.size()) {
	    selectedPatch = &patches.at(fwSelected);
    } else {
        selectedPatch = &patches.at(fwSelected - (patch_count - patches.size()));
    }

	iprintf("Patching for %s\n\n",selectedPatch->description.c_str());

	// read header
	readFirmware(0,workbuffer,42);

	u32 userSettingsOffset = (workbuffer[32] + (workbuffer[33] << 8))<<3;

	// read User Settings
	readFirmware(userSettingsOffset,workbuffer,512);

	aseek(patchfile,selectedPatch->fileoffset,SEEK_SET);
	aread(&header,1,4,patchfile);

	if (header != 'PTCH' ) {

			printf("      Patch set invalid\n");
			halt();

	} else {

		int32_t numPatches;
		uint32_t patchSize,patchOffset;
		aread(&numPatches,1,4,patchfile);

		uint32_t patchOffsetList[numPatches];
		aread(patchOffsetList,1,sizeof(patchOffsetList),patchfile);

		for (int i=0; i<numPatches; i++) {

			aseek(patchfile,patchOffsetList[i],SEEK_SET);
			aread(&patchSize,1,4,patchfile);
			aread(&patchOffset,1,4,patchfile);
			aread(&workbuffer[patchOffset],1,patchSize,patchfile);

		}
	}

	if (fwSelected < (int)patches.size()) {
		for(int i = 0;i < MAX_DATNAME_LEN * 2 - 2;i += 2){
			*(workbuffer + 0x11C + i) = datName[i / 2];
			*(workbuffer + 0x11C + i + 1) = 0;
		}
        *(workbuffer + 0x11C + MAX_DATNAME_LEN * 2 - 2)=0;
        *(workbuffer + 0x11C + MAX_DATNAME_LEN * 2 - 1)=0;
	} else {
		// Load filename from ropCustom.txt
		int csSelected=0;  //custom selected
		int customLinesTotal=6;
		int i=0;
		char pathBegin[]="YS:/";

		if(!fatInitDefault()){
			iprintf("      fat init error\n");
			halt();
		}

		FILE *text=fopen("ropCustom.txt","r");

		if(!text){
			iprintf("      ropCustom.txt load error\n      Does it exist?\n\n");
			halt();
		}

		for(i=0;i<customLinesTotal;i++){
			fgets(custom[i],MAX_DATNAME_LEN-4,text);
			if(!custom[i] || (custom[i][0] < 0x21) )break;

			for(int j=0; j < MAX_DATNAME_LEN-4 ;j++){  //strip newline junk
				if(custom[i][j]==0x0D || custom[i][j]==0x0A)
					custom[i][j]=0;
			}
			custom[i][MAX_DATNAME_LEN-5]=0;    //make damn sure it terminates
		}
		if(i==0){
			iprintf("      ropCustom.txt read error\n");
			iprintf("      invalid first line path\n");
			halt();
		}

		customLinesTotal=i;

		fclose(text);

		iprintf("\x1b[2J"); //clear console
		iprintf("Custom filename list:");

		for(i=0;i<customLinesTotal;i++){
			iprintf ("\x1b[%d;3H", i + ITEMS_START_ROW -8);
			iprintf ("%s", custom[i]);
		}

		while(1) {

			// Show cursor
			iprintf ("\x1b[%d;0H[>", csSelected - screenOffset + ITEMS_START_ROW -8);

			// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
			do {
				scanKeys();
				pressed = keysDownRepeat();
				swiWaitForVBlank();
			} while (!pressed);

			// Hide cursor
			iprintf ("\x1b[%d;0H  ", csSelected - screenOffset + ITEMS_START_ROW -8);
			if (pressed & KEY_UP) 		csSelected -= 1;
			if (pressed & KEY_DOWN) 	csSelected += 1;

			if (pressed & KEY_A) break;

			if (csSelected < 0) 	csSelected =  customLinesTotal - 1;		// Wrap around to bottom of list
			if (csSelected > (customLinesTotal - 1))		csSelected = 0;		// Wrap around to top of list

		}

		for(int i = 0; i < 4 * 2 ;i += 2){
			*(workbuffer + 0x11C + i) = pathBegin[i / 2];
			*(workbuffer + 0x11C + i + 1) = 0;
		}

		for(int i = 0; i < (MAX_DATNAME_LEN - 4) * 2 - 2;i += 2){
			*(workbuffer + 0x124 + i) = custom[csSelected][i / 2];
			*(workbuffer + 0x124 + i + 1)=0;
		}

		*(workbuffer + 0x11C + MAX_DATNAME_LEN * 2 - 2)=0; //ensure terminated string (again)
		*(workbuffer + 0x11C + MAX_DATNAME_LEN * 2 - 1)=0;
    }

	userSettingsCRC(workbuffer);
	userSettingsCRC(workbuffer+256);

	iprintf("\n\n\n\n\n      Writing ... ");
	int ret = writeFirmware(userSettingsOffset,workbuffer,512);

	if (ret) {

		iprintf("failed\n");

	} else {

		iprintf("success\n");

	}

	iprintf("      Verifying ... ");
	readFirmware(userSettingsOffset,workbuffer+512,512);

	if (memcmp(workbuffer,workbuffer+512,512)){

		iprintf("failed\n");

	} else {

		iprintf("success\n");

	}

	halt();
	return 0;
}
<|endoftext|>


<commit_before>#include <ctrcommon/input.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include <sstream>
#include <iomanip>
#include <stdio.h>

typedef enum {
    INSTALL,
    DELETE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL;
    bool exit = false;
    bool netInstall = false;
    u64 freeSpace = fsGetFreeSpace(destination);
    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_SELECT)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL) {
                mode = DELETE;
            } else {
                mode = INSTALL;
            }

            breakLoop = true;
        }

        if(inputIsPressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL ? "Install" : "Delete") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        stream << "Y - Receive an app over the network" << "\n";
        if(ninjhax) {
            stream << "SELECT - Exit to launcher" << "\n";
        }

        std::string str = stream.str();
        screenDrawString(str, (screenGetWidth() - screenGetStrWidth(str)) / 2, screenGetHeight() - 4 - screenGetStrHeight(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        uiDisplayProgress(TOP_SCREEN, "Installing", "Press B to cancel.", true, progress);
        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    while(platformIsRunning()) {
        std::string targetInstall;
        App targetDelete;
        if(mode == INSTALL) {
            uiSelectFile(&targetInstall, "sdmc:", extensions, [&](bool inRoot) {
                return onLoop();
            }, [&](std::string path, bool &updateList) {
                if(uiPrompt(TOP_SCREEN, "Install the selected title?", true)) {
                    AppResult ret = appInstallFile(destination, path, onProgress);
                    std::stringstream resultMsg;

                    resultMsg << "Install ";
                    if(ret == APP_SUCCESS) {
                        resultMsg << "succeeded!";
                    } else {
                        resultMsg << "failed!" << "\n";
                        resultMsg << appGetResultString(ret) << "\n";
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE) {
            uiSelectApp(&targetDelete, destination, onLoop, [&](App app, bool &updateList) {
                if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true)) {
                    updateList = true;
                    uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                    AppResult ret = appDelete(app);

                    std::stringstream resultMsg;
                    resultMsg << "Delete ";
                    if(ret == APP_SUCCESS) {
                        resultMsg << "succeeded!";
                    } else {
                        resultMsg << "failed!" << "\n";
                        resultMsg << appGetResultString(ret) << "\n";
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        }

        if(netInstall && !exit) {
            netInstall = false;

            screenClearBuffers(BOTTOM_SCREEN, 0, 0, 0);

            RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN);
            if(file.fd == NULL) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << appGetResultString(ret) << "\n";
                }

                uiPrompt(TOP_SCREEN, resultMsg.str(), false);
            }

            fclose(file.fd);
            continue;
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<commit_msg>Allow deleting CIA files and installing/deleting all CIA files in a directory at once.<commit_after>#include <ctrcommon/input.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include <stdio.h>

#include <sstream>
#include <iomanip>

#include <sys/dirent.h>

typedef enum {
    INSTALL_CIA,
    DELETE_CIA,
    DELETE_TITLE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();
    /* if(ninjhax) {
        consoleInit(GFX_BOTTOM, NULL);
        consoleClear();

        AcquireResult result = platformAcquireServices();
        if(result != ACQUIRE_SUCCESS) {
            //std::stringstream errorStream;
            //errorStream << "Failed to acquire services." << "\n";
            //errorStream << platformGetAcquireResultString(result) << "\n";
            //uiPrompt(TOP_SCREEN, errorStream.str(), false);

            while(true) {
                inputPoll();
                if(inputIsPressed(BUTTON_START)) {
                    break;
                }
            }

            platformCleanup();
            return 0;
        }
    } */

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL_CIA;
    bool exit = false;
    bool netInstall = false;
    u64 freeSpace = fsGetFreeSpace(destination);
    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_SELECT)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE_TITLE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL_CIA) {
                mode = DELETE_CIA;
            } else if(mode == DELETE_CIA) {
                mode = DELETE_TITLE;
            } else {
                mode = INSTALL_CIA;
            }

            breakLoop = true;
        }

        if(inputIsPressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL_CIA ? "Install CIA" : mode == DELETE_CIA ? "Delete CIA" : "Delete Title") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        if(mode == INSTALL_CIA) {
            stream << "X - Install all CIAs in the current directory" << "\n";
        } else if(mode == DELETE_CIA) {
            stream << "X - Delete all CIAs in the current directory" << "\n";
        }

        stream << "Y - Receive an app over the network" << "\n";
        if(ninjhax) {
            stream << "SELECT - Exit to launcher" << "\n";
        }

        std::string str = stream.str();
        screenDrawString(str, (screenGetWidth() - screenGetStrWidth(str)) / 2, screenGetHeight() - 4 - screenGetStrHeight(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        uiDisplayProgress(TOP_SCREEN, "Installing", "Press B to cancel.", true, progress);
        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    while(platformIsRunning()) {
        std::string fileTarget;
        App appTarget;
        if(mode == INSTALL_CIA) {
            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    if(uiPrompt(TOP_SCREEN, "Install all CIAs in the current directory?", true)) {
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            std::string fileName = (*it).name;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                AppResult ret = appInstallFile(destination, path, onProgress);
                                if(ret != APP_SUCCESS) {
                                    std::stringstream resultMsg;
                                    resultMsg << "Install failed!" << "\n";
                                    resultMsg << fileName << "\n";
                                    resultMsg << appGetResultString(ret) << "\n";
                                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                    failed = true;
                                    break;
                                }
                            }
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Install succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                if(uiPrompt(TOP_SCREEN, "Install the selected CIA?", true)) {
                    AppResult ret = appInstallFile(destination, path, onProgress);

                    std::stringstream resultMsg;
                    resultMsg << "Install ";
                    if(ret == APP_SUCCESS) {
                        resultMsg << "succeeded!";
                    } else {
                        resultMsg << "failed!" << "\n";
                        resultMsg << appGetResultString(ret) << "\n";
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_CIA) {
            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    if(uiPrompt(TOP_SCREEN, "Delete all CIAs in the current directory?", true)) {
                        updateList = true;
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            std::string fileName = (*it).name;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                if(!fsDelete(path)) {
                                    std::stringstream resultMsg;
                                    resultMsg << "Delete failed!" << "\n";
                                    resultMsg << fileName << "\n";
                                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                    failed = true;
                                    break;
                                }
                            }
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Delete succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                if(uiPrompt(TOP_SCREEN, "Delete the selected CIA?", true)) {
                    updateList = true;
                    std::stringstream resultMsg;
                    resultMsg << "Delete ";
                    if(fsDelete(path)) {
                        resultMsg << "succeeded!";
                    } else {
                        resultMsg << "failed!" << "\n";
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_TITLE) {
            uiSelectApp(&appTarget, destination, [&](bool &updateList) {
                return onLoop();
            }, [&](App app, bool &updateList) {
                if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true)) {
                    updateList = true;
                    uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                    AppResult ret = appDelete(app);

                    std::stringstream resultMsg;
                    resultMsg << "Delete ";
                    if(ret == APP_SUCCESS) {
                        resultMsg << "succeeded!";
                    } else {
                        resultMsg << "failed!" << "\n";
                        resultMsg << appGetResultString(ret) << "\n";
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        }

        if(netInstall && !exit) {
            netInstall = false;

            screenClearBuffers(BOTTOM_SCREEN, 0, 0, 0);

            RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN);
            if(file.fd == NULL) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                std::stringstream resultMsg;
                resultMsg << "Install ";
                if(ret == APP_SUCCESS) {
                    resultMsg << "succeeded!";
                } else {
                    resultMsg << "failed!" << "\n";
                    resultMsg << appGetResultString(ret) << "\n";
                }

                uiPrompt(TOP_SCREEN, resultMsg.str(), false);
            }

            fclose(file.fd);
            continue;
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<|endoftext|>


<commit_before>//
//
//  Created by Steven Massey on 4/15/19.
//  Copyright © 2019 Steven Massey. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "m3.hpp"

extern "C"
{
#	include "m3_core.h"
}

#include "m3_host.h"

void  m3Output  (const char * i_string)
{
	printf ("%s\n", i_string);
}

int  main  (int i_argc, const char * i_argv [])
{
	M3Result result = c_m3Err_none;

	if (i_argc >= 2)
	{
		FILE * f = fopen (i_argv [1], "rb");

		if (f)
		{
			fseek (f, 0, SEEK_END);
			size_t fsize = ftell (f);
			fseek (f, 0, SEEK_SET);

			if (fsize < 100000)
			{
				u8 * wasm = (u8 *) malloc (fsize);

				if (wasm)
				{
					IM3Runtime env = nullptr;

					try
					{
						fread (wasm, 1, fsize, f);
						fclose (f);

						IM3Module module;
						result = m3_ParseModule (& module, wasm, (u32) fsize); if (result) throw result;

						env = m3_NewRuntime (32768);

						result = m3_LoadModule (env, module); if (result) throw result;

						m3_LinkFunction (module, "_m3TestOut", "v(iFi)", (void *) m3TestOut);
						m3_LinkFunction (module, "_m3StdOut", "v(*)", (void *) m3Output);
						m3_LinkFunction (module, "_m3Export", "v(*i)", (void *) m3Export);
						m3_LinkFunction (module, "_m3Out_f64", "v(F)", (void *) m3Out_f64);
						m3_LinkFunction (module, "_m3Out_i32", "v(i)", (void *) m3Out_i32);
						m3_LinkFunction (module, "_TestReturn", "F(i)", (void *) TestReturn);

						m3_LinkFunction (module, "abortStackOverflow",	"v(i)",		(void *) m3_abort);

						result = m3_LinkCStd (module); if (result) throw result;

						m3_PrintRuntimeInfo (env);

						IM3Function f;
						result = m3_FindFunction (& f, env, "__post_instantiate");

						if (not result)
						{
							result = m3_Call (f); if (result) throw result;
						}

						IM3Function main;
						result = m3_FindFunction (& main, env, i_argv[2]); if (result) throw result;

						if (main)
						{
							printf ("found %s\n", i_argv[2]);

							clock_t start = clock ();

//							result = m3_Call (main);

							if (i_argc)
							{
								i_argc -= 2;
								i_argv += 2;
							}

							result = m3_CallWithArgs (main, i_argc, i_argv);

							clock_t end = clock ();
							double elapsed_time = (end - start) / (double) CLOCKS_PER_SEC ;
							printf("Time: %.3lf s\n", elapsed_time);

//							printf ("call: %s\n", result);

							m3_PrintProfilerInfo ();
						}

					}

					catch (const M3Result & r) {}

					if (result)
					{
						printf ("result: %s", result);

						if (env)
						{
							M3ErrorInfo info = m3_GetErrorInfo (env);
							printf (" (%s)", info.message);
						}

						printf ("\n");
						return 1;
					}

					m3_FreeRuntime (env);
				}

				free (wasm);
			}
		}
		else printf ("couldn't open '%s'\n", i_argv [1]);
	} else printf ("not enough arguments\n");

	printf ("\n");

	return 0;
}
<commit_msg>Allow running exported functions with args<commit_after>//
//
//  Created by Steven Massey on 4/15/19.
//  Copyright © 2019 Steven Massey. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "m3.hpp"

extern "C"
{
#	include "m3_core.h"
}

#include "m3_host.h"

void  m3Output  (const char * i_string)
{
	printf ("%s\n", i_string);
}

int  main  (int i_argc, const char * i_argv [])
{
	M3Result result = c_m3Err_none;

	if (i_argc >= 2)
	{
		FILE * f = fopen (i_argv [1], "rb");

		if (f)
		{
			fseek (f, 0, SEEK_END);
			size_t fsize = ftell (f);
			fseek (f, 0, SEEK_SET);

			if (fsize < 100000)
			{
				u8 * wasm = (u8 *) malloc (fsize);

				if (wasm)
				{
					IM3Runtime env = nullptr;

					try
					{
						fread (wasm, 1, fsize, f);
						fclose (f);

						IM3Module module;
						result = m3_ParseModule (& module, wasm, (u32) fsize); if (result) throw result;

						env = m3_NewRuntime (32768);

						result = m3_LoadModule (env, module); if (result) throw result;

						m3_LinkFunction (module, "_m3TestOut", "v(iFi)", (void *) m3TestOut);
						m3_LinkFunction (module, "_m3StdOut", "v(*)", (void *) m3Output);
						m3_LinkFunction (module, "_m3Export", "v(*i)", (void *) m3Export);
						m3_LinkFunction (module, "_m3Out_f64", "v(F)", (void *) m3Out_f64);
						m3_LinkFunction (module, "_m3Out_i32", "v(i)", (void *) m3Out_i32);
						m3_LinkFunction (module, "_TestReturn", "F(i)", (void *) TestReturn);

						m3_LinkFunction (module, "abortStackOverflow",	"v(i)",		(void *) m3_abort);

						result = m3_LinkCStd (module); if (result) throw result;

						//m3_PrintRuntimeInfo (env);

						IM3Function f;
						result = m3_FindFunction (& f, env, "__post_instantiate");

						if (not result)
						{
							result = m3_Call (f); if (result) throw result;
						}

						const char* fname = i_argv[2];

						IM3Function main;
						result = m3_FindFunction (& main, env, fname); if (result) throw result;

						if (main)
						{

							clock_t start = clock ();

							if (!strcmp(fname, "_main") || !strcmp(fname, "main")) {
								if (i_argc)
								{
									i_argc -= 2;
									i_argv += 2;
								}
								result = m3_CallMain (main, i_argc, i_argv);
							} else {
								if (i_argc)
								{
									i_argc -= 3;
									i_argv += 3;
								}
								result = m3_CallWithArgs (main, i_argc, i_argv);
							}

							clock_t end = clock ();
							double elapsed_time = (end - start) / (double) CLOCKS_PER_SEC ;
							printf("Time: %.3lf s\n", elapsed_time);

//							printf ("call: %s\n", result);

							//m3_PrintProfilerInfo ();
						} else {
							printf ("%s not found\n", fname);
						}

					}

					catch (const M3Result & r) {}

					if (result)
					{
						printf ("Error: %s", result);

						if (env)
						{
							M3ErrorInfo info = m3_GetErrorInfo (env);
							printf (" (%s)", info.message);
						}

						printf ("\n");
						return 1;
					}

					m3_FreeRuntime (env);
				}

				free (wasm);
			}
		}
		else printf ("couldn't open '%s'\n", i_argv [1]);
	} else printf ("not enough arguments\n");

	printf ("\n");

	return 0;
}
<|endoftext|>


<commit_before>#include <ctrcommon/common.hpp>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL,
    DELETE
} Mode;

int main(int argc, char **argv) {
    if(!platform_init()) {
        return 0;
    }

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL;
    bool netInstall = false;
    u64 freeSpace = fs_get_free_space(destination);
    auto onLoop = [&]() {
        bool breakLoop = false;
        if(input_is_pressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fs_get_free_space(destination);
            if(mode == DELETE) {
                breakLoop = true;
            }
        }

        if(input_is_pressed(BUTTON_R)) {
            if(mode == INSTALL) {
                mode = DELETE;
            } else {
                mode = INSTALL;
            }

            breakLoop = true;
        }

        if(input_is_pressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL ? "Install" : "Delete") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        stream << "Y - Receive an app over the network" << "\n";

        std::string str = stream.str();
        screen_draw_string(str, (screen_get_width() - screen_get_str_width(str)) / 2, screen_get_height() - 4 - screen_get_str_height(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        ui_display_progress("Installing", "Press B to cancel.", true, progress);
        input_poll();
        return !input_is_pressed(BUTTON_B);
    };

    while(platform_is_running()) {
        std::string targetInstall;
        App targetDelete;
        bool obtained = false;
        if(mode == INSTALL) {
            obtained = ui_select_file(&targetInstall, "sdmc:", extensions, onLoop);
        } else if(mode == DELETE) {
            obtained = ui_select_app(&targetDelete, destination, onLoop);
        }

        if(netInstall) {
            netInstall = false;

            // Clear bottom screen on both buffers.
            screen_begin_draw(BOTTOM_SCREEN);
            screen_clear(0, 0, 0);
            screen_end_draw();
            screen_swap_buffers();

            screen_begin_draw(BOTTOM_SCREEN);
            screen_clear(0, 0, 0);
            screen_end_draw();
            screen_swap_buffers();

            RemoteFile file = ui_accept_remote_file();
            if(file.socket == -1) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(ui_prompt(confirmStream.str(), true)) {
                int ret = app_install(destination, file.socket, true, file.fileSize, onProgress);
                std::stringstream resultMsg;
                resultMsg << "Install ";
                if(ret == 0) {
                    resultMsg << "succeeded!";
                } else if(ret == -2) {
                    resultMsg << "cancelled!";
                } else {
                    resultMsg << "failed! Error: 0x" << std::hex << ret;
                }

                ui_prompt(resultMsg.str(), false);
            }

            socket_close(file.socket);
            continue;
        }

        if(obtained) {
            std::stringstream prompt;
            if(mode == INSTALL) {
                prompt << "Install ";
            } else if(mode == DELETE) {
                prompt << "Delete ";
            }

            prompt << "the selected title?";
            if(ui_prompt(prompt.str(), true)) {
                int ret = 0;
                if(mode == INSTALL) {
                    ret = app_install_file(destination, targetInstall, onProgress);
                } else if(mode == DELETE) {
                    ui_display_message("Deleting title...");
                    ret = app_delete(targetDelete);
                }

                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == 0) {
                    resultMsg << "succeeded!";
                } else if(ret == -2) {
                    resultMsg << "cancelled!";
                } else {
                    resultMsg << "failed! Error: 0x" << std::hex << ret;
                }

                ui_prompt(resultMsg.str(), false);

                freeSpace = fs_get_free_space(destination);
            }
        }
    }

    platform_cleanup();
    return 0;
}
<commit_msg>Use app_install_socket.<commit_after>#include <ctrcommon/common.hpp>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL,
    DELETE
} Mode;

int main(int argc, char **argv) {
    if(!platform_init()) {
        return 0;
    }

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL;
    bool netInstall = false;
    u64 freeSpace = fs_get_free_space(destination);
    auto onLoop = [&]() {
        bool breakLoop = false;
        if(input_is_pressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fs_get_free_space(destination);
            if(mode == DELETE) {
                breakLoop = true;
            }
        }

        if(input_is_pressed(BUTTON_R)) {
            if(mode == INSTALL) {
                mode = DELETE;
            } else {
                mode = INSTALL;
            }

            breakLoop = true;
        }

        if(input_is_pressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        std::stringstream stream;
        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL ? "Install" : "Delete") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        stream << "Y - Receive an app over the network" << "\n";

        std::string str = stream.str();
        screen_draw_string(str, (screen_get_width() - screen_get_str_width(str)) / 2, screen_get_height() - 4 - screen_get_str_height(str), 255, 255, 255);

        return breakLoop;
    };

    auto onProgress = [&](int progress) {
        ui_display_progress("Installing", "Press B to cancel.", true, progress);
        input_poll();
        return !input_is_pressed(BUTTON_B);
    };

    while(platform_is_running()) {
        std::string targetInstall;
        App targetDelete;
        bool obtained = false;
        if(mode == INSTALL) {
            obtained = ui_select_file(&targetInstall, "sdmc:", extensions, onLoop);
        } else if(mode == DELETE) {
            obtained = ui_select_app(&targetDelete, destination, onLoop);
        }

        if(netInstall) {
            netInstall = false;

            // Clear bottom screen on both buffers.
            screen_begin_draw(BOTTOM_SCREEN);
            screen_clear(0, 0, 0);
            screen_end_draw();
            screen_swap_buffers();

            screen_begin_draw(BOTTOM_SCREEN);
            screen_clear(0, 0, 0);
            screen_end_draw();
            screen_swap_buffers();

            RemoteFile file = ui_accept_remote_file();
            if(file.socket == -1) {
                continue;
            }

            std::stringstream confirmStream;
            confirmStream << "Install the received application?" << "\n";
            confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)" << "\n";
            if(ui_prompt(confirmStream.str(), true)) {
                int ret = app_install_socket(destination, file.socket, file.fileSize, onProgress);
                std::stringstream resultMsg;
                resultMsg << "Install ";
                if(ret == 0) {
                    resultMsg << "succeeded!";
                } else if(ret == -2) {
                    resultMsg << "cancelled!";
                } else {
                    resultMsg << "failed! Error: 0x" << std::hex << ret;
                }

                ui_prompt(resultMsg.str(), false);
            }

            socket_close(file.socket);
            continue;
        }

        if(obtained) {
            std::stringstream prompt;
            if(mode == INSTALL) {
                prompt << "Install ";
            } else if(mode == DELETE) {
                prompt << "Delete ";
            }

            prompt << "the selected title?";
            if(ui_prompt(prompt.str(), true)) {
                int ret = 0;
                if(mode == INSTALL) {
                    ret = app_install_file(destination, targetInstall, onProgress);
                } else if(mode == DELETE) {
                    ui_display_message("Deleting title...");
                    ret = app_delete(targetDelete);
                }

                std::stringstream resultMsg;
                if(mode == INSTALL) {
                    resultMsg << "Install ";
                } else if(mode == DELETE) {
                    resultMsg << "Delete ";
                }

                if(ret == 0) {
                    resultMsg << "succeeded!";
                } else if(ret == -2) {
                    resultMsg << "cancelled!";
                } else {
                    resultMsg << "failed! Error: 0x" << std::hex << ret;
                }

                ui_prompt(resultMsg.str(), false);

                freeSpace = fs_get_free_space(destination);
            }
        }
    }

    platform_cleanup();
    return 0;
}
<|endoftext|>


<commit_before>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/
#ifndef __itkPatternIntensityImageToImageMetric_txx
#define __itkPatternIntensityImageToImageMetric_txx

#include "itkPatternIntensityImageToImageMetric.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkNumericTraits.h"

#include <iostream>
#include <iomanip>
#include <stdio.h>

#include "itkSimpleFilterWatcher.h"
//#include "itkImageFileWriter.h"

namespace itk
{

/**
 * ********************* Constructor ******************************
 */

template <class TFixedImage, class TMovingImage>
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::PatternIntensityImageToImageMetric()
{
  this->m_NormalizationFactor = 1.0;
  this->m_Rescalingfactor = 1.0;
  this->m_DerivativeDelta = 0.001;
  this->m_NoiseConstant = 10000; // = sigma * sigma = 100*100 if not specified
  this->m_NeighborhoodRadius = 3;
  this->m_FixedMeasure = 0;
  this->m_OptimizeNormalizationFactor = false;
  this->m_TransformMovingImageFilter = TransformMovingImageFilterType::New();
  this->m_CombinationTransform = CombinationTransformType::New();
  this->m_RescaleImageFilter = RescaleIntensityImageFilterType::New();
  this->m_DifferenceImageFilter = DifferenceImageFilterType::New();
  this->m_MultiplyByConstantImageFilter = MultiplyByConstantImageFilterType::New();

	} // end Constructor

/**
 * ********************* Initialize ******************************
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::Initialize( void ) throw ( ExceptionObject )
{
  Superclass::Initialize();

  /* resampling for 3D->2D */
  this->m_TransformMovingImageFilter->SetTransform(
    dynamic_cast<CombinationTransformType *>(
    dynamic_cast<RayCastInterpolatorType *>(
    const_cast<  InterpolatorType *>( ( this->GetInterpolator() ) ) )->GetTransform() ) );
  this->m_TransformMovingImageFilter->SetInterpolator( this->m_Interpolator );
  this->m_TransformMovingImageFilter->SetInput( this->m_MovingImage );
  this->m_TransformMovingImageFilter->SetDefaultPixelValue( 0 );

  this->m_TransformMovingImageFilter->SetSize(
    this->m_FixedImage->GetLargestPossibleRegion().GetSize() );
  this->m_TransformMovingImageFilter->SetOutputOrigin(
    this->m_FixedImage->GetOrigin() );
  this->m_TransformMovingImageFilter->SetOutputSpacing(
    this->m_FixedImage->GetSpacing() );
  this->m_TransformMovingImageFilter->SetOutputDirection(
    this->m_FixedImage->GetDirection() );
  this->m_TransformMovingImageFilter->UpdateLargestPossibleRegion();
  this->ComputeFixedImageExtrema(
    this->GetFixedImage(), this->GetFixedImageRegion() );
  this->ComputeMovingImageExtrema(
    this->m_TransformMovingImageFilter->GetOutput(),
    this->m_TransformMovingImageFilter->GetOutput()->GetBufferedRegion() );
  this->m_NormalizationFactor = this->m_FixedImageTrueMax / this->m_MovingImageTrueMax;
  this->m_MultiplyByConstantImageFilter->SetInput(
    this->m_TransformMovingImageFilter->GetOutput() );
  this->m_MultiplyByConstantImageFilter->SetConstant(
    this->m_NormalizationFactor );
  this->m_DifferenceImageFilter->SetInput1( this->m_FixedImage );
  this->m_DifferenceImageFilter->SetInput2( this->m_MultiplyByConstantImageFilter->GetOutput() );
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  this->m_FixedMeasure = this->ComputePIFixed();

  /* to rescale the similarity measure between 0-1;*/
  MeasureType tmpmeasure = this->GetValue( this->m_CombinationTransform->GetParameters() );

  while ( ( vcl_fabs( tmpmeasure ) / this->m_Rescalingfactor ) > 1 )
	{
    this->m_Rescalingfactor *= 10;
	}

} // end Initialize()

/**
 * ********************* PrintSelf ******************************
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf( os, indent );
    os << indent << "DerivativeDelta: " << this->m_DerivativeDelta << std::endl;

} // end PrintSelf()

/**
 * ********************* ComputePIFixed ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::ComputePIFixed( ) const
{
  unsigned int iDimension;
  MeasureType measure = NumericTraits< MeasureType >::Zero;
  MeasureType diff = NumericTraits< MeasureType >::Zero;

  typename FixedImageType::SizeType iterationSize =
    this->m_FixedImage->GetLargestPossibleRegion().GetSize();
  typename FixedImageType::IndexType iterationStartIndex, currentIndex, neighborIndex;
  typename FixedImageType::SizeType neighborIterationSize;
  typename FixedImageType::PointType point;

  for( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
  {
    iterationSize[ iDimension ] -= static_cast<int>( 2 * this->m_NeighborhoodRadius );
    iterationStartIndex[ iDimension ] = static_cast<int>( this->m_NeighborhoodRadius );
    neighborIterationSize[ iDimension ] = static_cast<int>(2 * this->m_NeighborhoodRadius) + 1;
	}

  /** replace this by checking the size of the 3rd dimension of fixedimage */
  iterationSize[ 2 ] = neighborIterationSize[ 2 ] = 1;
  iterationStartIndex[ 2 ] = 0;

  typename FixedImageType::RegionType iterationRegion, neighboriterationRegion;
  iterationRegion.SetIndex( iterationStartIndex );
  iterationRegion.SetSize( iterationSize );

  typedef  itk::ImageRegionConstIteratorWithIndex< FixedImageType > FixedImageTypeIteratorType;

  FixedImageTypeIteratorType fixedImageIt( this->m_FixedImage, iterationRegion );
  fixedImageIt.GoToBegin();

  neighboriterationRegion.SetSize( neighborIterationSize );

  bool sampleOK = false;

  if ( this->m_FixedImageMask.IsNull() )
  {
    sampleOK = true;
  }

  while ( !fixedImageIt.IsAtEnd() )
  {
    /** Get current index */
    currentIndex = fixedImageIt.GetIndex();
    this->m_FixedImage->TransformIndexToPhysicalPoint( currentIndex, point );

    /** if fixedMask is given */
    if ( !this->m_FixedImageMask.IsNull() )
    {
      if ( this->m_FixedImageMask->IsInside( point ) )
      {
        sampleOK = true;
      }
      else
      {
        sampleOK = false;
      }
		}

    if ( sampleOK )
    {
      /** setup the neighborhood iterator */
      for( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
      {
        neighborIndex[ iDimension ] = currentIndex[ iDimension ] - this->m_NeighborhoodRadius;
        neighborIndex[ 2 ] = 0; // 2D only
      }

    neighboriterationRegion.SetIndex( neighborIndex );
    FixedImageTypeIteratorType neighborIt( this->m_FixedImage, neighboriterationRegion );
    neighborIt.GoToBegin();

      while ( ! neighborIt.IsAtEnd() )
      {
        diff = fixedImageIt.Value() - neighborIt.Value();
        measure += ( this->m_NoiseConstant ) / ( this->m_NoiseConstant + ( diff * diff ) );
        ++neighborIt;
      } // end while neighborIt

    } // end if sampleOK

    ++fixedImageIt;
  } //end while fixedImageIt

  return measure;

} // end ComputePIFixed()

/**
 * ********************* ComputePIDiff ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::ComputePIDiff( const TransformParametersType & parameters, float scalingfactor ) const
{
  unsigned int iDimension;
  this->SetTransformParameters( parameters );
  this->m_TransformMovingImageFilter->Modified();
  this->m_MultiplyByConstantImageFilter->SetConstant( scalingfactor );
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  MeasureType measure = NumericTraits< MeasureType >::Zero;
  MeasureType diff = NumericTraits< MeasureType >::Zero;

  typename FixedImageType::SizeType iterationSize = this->m_FixedImage->GetLargestPossibleRegion().GetSize();
  typename FixedImageType::IndexType iterationStartIndex, currentIndex, neighborIndex;
  typename FixedImageType::SizeType neighborIterationSize;
  typename FixedImageType::PointType point;

  for ( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
  {
    iterationSize[iDimension] -= static_cast<int>( 2 * this->m_NeighborhoodRadius );
    iterationStartIndex[iDimension] = static_cast<int>( this->m_NeighborhoodRadius );
    neighborIterationSize[iDimension] = static_cast<int>( 2 * this->m_NeighborhoodRadius + 1 );
  }

  /** 3rd Dimension is 1 */
  iterationSize[ 2 ] = neighborIterationSize[ 2 ] = 1;
  iterationStartIndex[ 2 ] = 0;

  typename FixedImageType::RegionType iterationRegion, neighboriterationRegion;
  iterationRegion.SetIndex( iterationStartIndex );
  iterationRegion.SetSize( iterationSize );

  typedef itk::ImageRegionConstIteratorWithIndex< TransformedMovingImageType > DifferenceImageIteratorType;
  DifferenceImageIteratorType differenceImageIt( this->m_DifferenceImageFilter->GetOutput(), iterationRegion );
  differenceImageIt.GoToBegin();

  neighboriterationRegion.SetSize( neighborIterationSize );

  bool sampleOK = false;

  if ( this->m_FixedImageMask.IsNull() )
  {
    sampleOK = true;
  }

  while ( !differenceImageIt.IsAtEnd() )
  {
    /** Get current index */
    currentIndex = differenceImageIt.GetIndex();
    this->m_FixedImage->TransformIndexToPhysicalPoint( currentIndex, point );

    /** if fixedMask is given */
    if ( !this->m_FixedImageMask.IsNull() )
    {
      if ( this->m_FixedImageMask->IsInside( point ) )
      {
        sampleOK = true;
      }
      else
      {
        sampleOK = false;
      }
    }

    if ( sampleOK )
    {
      /** setup the neighborhood iterator */
      for ( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
      {
        neighborIndex[ iDimension ] = currentIndex[ iDimension ] - this->m_NeighborhoodRadius;
        neighborIndex[ 2 ] = 0; // 2D only
      }

      neighboriterationRegion.SetIndex( neighborIndex );
      DifferenceImageIteratorType neighborIt( this->m_DifferenceImageFilter->GetOutput(), neighboriterationRegion );
      neighborIt.GoToBegin();

      while ( !neighborIt.IsAtEnd() )
      {
        diff = differenceImageIt.Value() - neighborIt.Value();
        measure += ( this->m_NoiseConstant )/( this->m_NoiseConstant + ( diff * diff ) );
        ++neighborIt;
      } // end while neighborIt

    } // end if sampleOK

    ++differenceImageIt;
  } // end while differenceImageIt

  return measure;

} // end ComputePIDiff()

/**
 * ********************* GetValue ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetValue( const TransformParametersType & parameters ) const
{
  this->SetTransformParameters( parameters );
  this->m_TransformMovingImageFilter->Modified();
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  MeasureType measure = 1e10;
  MeasureType currentMeasure = 1e10;

  if ( this->m_OptimizeNormalizationFactor )
  {
    float tmpfactor =  0.0;
    float factorstep =  ( this->m_NormalizationFactor * 10 - tmpfactor ) / 100;
    float bestfactor = tmpfactor;
    MeasureType tmpMeasure = 1e10;

    while ( tmpfactor <=  this->m_NormalizationFactor * 1.0 )
    {
      measure = this->ComputePIDiff( parameters, tmpfactor );
      tmpMeasure = ( measure - this->m_FixedMeasure ) / - this->m_Rescalingfactor;

      if( tmpMeasure < currentMeasure )
      {
        currentMeasure = tmpMeasure;
        bestfactor = tmpfactor;
      }

      tmpfactor += factorstep;
    }
  }
  else
  {
    measure = this->ComputePIDiff( parameters, this->m_NormalizationFactor );
    currentMeasure = -( measure - this->m_FixedMeasure ) / this->m_Rescalingfactor;
  }

	return currentMeasure;

} // end GetValue()

/**
 * ********************* GetDerivative ******************************
 */

template < class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetDerivative( const TransformParametersType & parameters,
  DerivativeType & derivative ) const
{
  TransformParametersType testPoint;
  testPoint = parameters;
  const unsigned int numberOfParameters = this->GetNumberOfParameters();
  derivative = DerivativeType( numberOfParameters );

  for ( unsigned int i = 0; i < numberOfParameters; i++ )
  {
    testPoint[ i ] -= this->m_DerivativeDelta / vcl_sqrt( this->m_Scales[ i ] );
    const MeasureType valuep0 = this->GetValue( testPoint );
    testPoint[ i ] += 2 * this->m_DerivativeDelta / vcl_sqrt( this->m_Scales[ i ] );
    const MeasureType valuep1 = this->GetValue( testPoint );
    derivative[ i ] = ( valuep1 - valuep0 ) / ( 2 * this->m_DerivativeDelta / vcl_sqrt( this->m_Scales[ i ] ) );
    testPoint[ i ] = parameters[ i ];
	}

} // end GetDerivative()

/**
 * ********************* GetValueAndDerivative ******************************
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetValueAndDerivative( const TransformParametersType & parameters,
  MeasureType & Value, DerivativeType & derivative ) const
{
  Value = this->GetValue( parameters );
  this->GetDerivative( parameters, derivative );

} // end GetValueAndDerivative()

} // end namespace itk

#endif // end __itkPatternIntensityImageToImageMetric_txx
<commit_msg>Bug fix<commit_after>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/
#ifndef __itkPatternIntensityImageToImageMetric_txx
#define __itkPatternIntensityImageToImageMetric_txx

#include "itkPatternIntensityImageToImageMetric.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkNumericTraits.h"

#include <iostream>
#include <iomanip>
#include <stdio.h>

#include "itkSimpleFilterWatcher.h"
#include "itkImageFileWriter.h"

namespace itk
{

/**
 * ********************* Constructor ******************************
 */

template <class TFixedImage, class TMovingImage>
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::PatternIntensityImageToImageMetric()
{
  this->m_NormalizationFactor = 1.0;
  this->m_Rescalingfactor = 1.0;
  this->m_DerivativeDelta = 0.001;
  this->m_NoiseConstant = 10000; // = sigma * sigma = 100*100 if not specified
  this->m_NeighborhoodRadius = 3;
  this->m_FixedMeasure = 0;
  this->m_OptimizeNormalizationFactor = false;
  this->m_TransformMovingImageFilter = TransformMovingImageFilterType::New();
  this->m_CombinationTransform = CombinationTransformType::New();
  this->m_RescaleImageFilter = RescaleIntensityImageFilterType::New();
  this->m_DifferenceImageFilter = DifferenceImageFilterType::New();
  this->m_MultiplyByConstantImageFilter = MultiplyByConstantImageFilterType::New();

	} // end Constructor

/**
 * ********************* Initialize ******************************
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::Initialize( void ) throw ( ExceptionObject )
{
  Superclass::Initialize();

  /* resampling for 3D->2D */
  this->m_TransformMovingImageFilter->SetTransform(
    dynamic_cast<CombinationTransformType *>(
    dynamic_cast<RayCastInterpolatorType *>(
    const_cast<  InterpolatorType *>( ( this->GetInterpolator() ) ) )->GetTransform() ) );
  this->m_TransformMovingImageFilter->SetInterpolator( this->m_Interpolator );
  this->m_TransformMovingImageFilter->SetInput( this->m_MovingImage );
  this->m_TransformMovingImageFilter->SetDefaultPixelValue( 0 );

  this->m_TransformMovingImageFilter->SetSize(
    this->m_FixedImage->GetLargestPossibleRegion().GetSize() );
  this->m_TransformMovingImageFilter->SetOutputOrigin(
    this->m_FixedImage->GetOrigin() );
  this->m_TransformMovingImageFilter->SetOutputSpacing(
    this->m_FixedImage->GetSpacing() );
  this->m_TransformMovingImageFilter->SetOutputDirection(
    this->m_FixedImage->GetDirection() );
  this->m_TransformMovingImageFilter->UpdateLargestPossibleRegion();
  this->ComputeFixedImageExtrema(
    this->GetFixedImage(), this->GetFixedImageRegion() );
  this->ComputeMovingImageExtrema(
    this->m_TransformMovingImageFilter->GetOutput(),
    this->m_TransformMovingImageFilter->GetOutput()->GetBufferedRegion() );
  this->m_NormalizationFactor = this->m_FixedImageTrueMax / this->m_MovingImageTrueMax;
  this->m_MultiplyByConstantImageFilter->SetInput(
    this->m_TransformMovingImageFilter->GetOutput() );
  this->m_MultiplyByConstantImageFilter->SetConstant(
    this->m_NormalizationFactor );
  this->m_DifferenceImageFilter->SetInput1( this->m_FixedImage );
  this->m_DifferenceImageFilter->SetInput2( this->m_MultiplyByConstantImageFilter->GetOutput() );
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  this->m_FixedMeasure = this->ComputePIFixed();

  /* to rescale the similarity measure between 0-1;*/
  MeasureType tmpmeasure = this->GetValue( this->m_Transform->GetParameters() );

  while ( ( fabs( tmpmeasure ) / this->m_Rescalingfactor ) > 1 )
	{
    this->m_Rescalingfactor *= 10;
	}

} // end Initialize()

/**
 * ********************* Constructor ******************************PrintSelf
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf( os, indent );
    os << indent << "DerivativeDelta: " << this->m_DerivativeDelta << std::endl;
}

/**
 * ********************* ComputePIFixed ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::ComputePIFixed( ) const
{
  unsigned int iDimension;
  MeasureType measure = NumericTraits< MeasureType >::Zero;
  MeasureType diff = NumericTraits< MeasureType >::Zero;

  typename FixedImageType::SizeType iterationSize =
    this->m_FixedImage->GetLargestPossibleRegion().GetSize();
  typename FixedImageType::IndexType iterationStartIndex, currentIndex, neighborIndex;
  typename FixedImageType::SizeType neighborIterationSize;
  typename FixedImageType::PointType point;

  for( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
  {
    iterationSize[ iDimension ] -= static_cast<int>( 2 * this->m_NeighborhoodRadius );
    iterationStartIndex[ iDimension ] = static_cast<int>( this->m_NeighborhoodRadius );
    neighborIterationSize[ iDimension ] = static_cast<int>(2 * this->m_NeighborhoodRadius) + 1;
	}

  /** replace this by checking the size of the 3rd dimension of fixedimage */
  iterationSize[ 2 ] = neighborIterationSize[ 2 ] = 1;
  iterationStartIndex[ 2 ] = 0;

  typename FixedImageType::RegionType iterationRegion, neighboriterationRegion;
  iterationRegion.SetIndex( iterationStartIndex );
  iterationRegion.SetSize( iterationSize );

  typedef  itk::ImageRegionConstIteratorWithIndex< FixedImageType > FixedImageTypeIteratorType;

  FixedImageTypeIteratorType fixedImageIt( this->m_FixedImage, iterationRegion );
  fixedImageIt.GoToBegin();

  neighboriterationRegion.SetSize( neighborIterationSize );

  bool sampleOK = false;

  if ( this->m_FixedImageMask.IsNull() )
    sampleOK = true;

  while ( !fixedImageIt.IsAtEnd() )
  {
    /** Get current index */
    currentIndex = fixedImageIt.GetIndex();
    this->m_FixedImage->TransformIndexToPhysicalPoint( currentIndex, point );

    /** if fixedMask is given */
    if ( !this->m_FixedImageMask.IsNull() )
    {
      if ( this->m_FixedImageMask->IsInside( point ) )
        sampleOK = true;
      else
        sampleOK = false;
		}

    if( sampleOK )
    {
      /** setup the neighborhood iterator */
      for( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
      {
        neighborIndex[ iDimension ] = currentIndex[ iDimension ] - this->m_NeighborhoodRadius;
        neighborIndex[ 2 ] = 0; // 2D only
      }

    neighboriterationRegion.SetIndex( neighborIndex );
    FixedImageTypeIteratorType neighborIt( this->m_FixedImage, neighboriterationRegion );
    neighborIt.GoToBegin();

      while ( ! neighborIt.IsAtEnd() )
      {
        diff = fixedImageIt.Value() - neighborIt.Value();
        measure += ( this->m_NoiseConstant )/( this->m_NoiseConstant + ( diff ) * ( diff ) );
        ++neighborIt;
      } // end while neighborIt

    } // end if sampleOK

    ++fixedImageIt;
  } //end while fixedImageIt

  return measure;

}

/**
 * ********************* ComputePIDiff ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::ComputePIDiff( const TransformParametersType & parameters, float scalingfactor ) const
{
  unsigned int iDimension;
  this->SetTransformParameters( parameters );
  this->m_TransformMovingImageFilter->Modified();
  this->m_MultiplyByConstantImageFilter->SetConstant( scalingfactor );
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  MeasureType measure = NumericTraits< MeasureType >::Zero;
  MeasureType diff = NumericTraits< MeasureType >::Zero;

  typename FixedImageType::SizeType iterationSize = this->m_FixedImage->GetLargestPossibleRegion().GetSize();
  typename FixedImageType::IndexType iterationStartIndex, currentIndex, neighborIndex;
  typename FixedImageType::SizeType neighborIterationSize;
  typename FixedImageType::PointType point;

  for( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
  {
    iterationSize[iDimension] -= static_cast<int>( 2 * this->m_NeighborhoodRadius );
    iterationStartIndex[iDimension] = static_cast<int>( this->m_NeighborhoodRadius );
    neighborIterationSize[iDimension] = static_cast<int>( 2 * this->m_NeighborhoodRadius + 1 );
  }

  /** 3rd Dimension is 1 */
  iterationSize[ 2 ] = neighborIterationSize[ 2 ] = 1;
  iterationStartIndex[ 2 ] = 0;

  typename FixedImageType::RegionType iterationRegion, neighboriterationRegion;
  iterationRegion.SetIndex( iterationStartIndex );
  iterationRegion.SetSize( iterationSize );

  typedef itk::ImageRegionConstIteratorWithIndex< TransformedMovingImageType > DifferenceImageIteratorType;
  DifferenceImageIteratorType differenceImageIt( this->m_DifferenceImageFilter->GetOutput(), iterationRegion );
  differenceImageIt.GoToBegin();

  neighboriterationRegion.SetSize( neighborIterationSize );

  bool sampleOK = false;

  if ( this->m_FixedImageMask.IsNull() )
    sampleOK = true;

  while ( !differenceImageIt.IsAtEnd() )
  {
    /** Get current index */
    currentIndex = differenceImageIt.GetIndex();
    this->m_FixedImage->TransformIndexToPhysicalPoint( currentIndex, point );

    /** if fixedMask is given */
    if ( !this->m_FixedImageMask.IsNull() )
    {
      if ( this->m_FixedImageMask->IsInside( point ) )
        sampleOK = true;
      else
        sampleOK = false;

    }

    if( sampleOK )
    {
      /** setup the neighborhood iterator */
      for ( iDimension = 0; iDimension < this->m_FixedImage->GetImageDimension(); iDimension++ )
      {
        neighborIndex[ iDimension ] = currentIndex[ iDimension ] - this->m_NeighborhoodRadius;
        neighborIndex[ 2] = 0; // 2D only
      }

      neighboriterationRegion.SetIndex( neighborIndex );
      DifferenceImageIteratorType neighborIt( this->m_DifferenceImageFilter->GetOutput(), neighboriterationRegion );
      neighborIt.GoToBegin();

      while ( !neighborIt.IsAtEnd() )
      {
        diff = differenceImageIt.Value() - neighborIt.Value();
        measure += ( this->m_NoiseConstant )/( this->m_NoiseConstant + ( ( diff ) * ( diff ) ) );
        ++neighborIt;
      } // end while neighborIt

    } // end if sampleOK

    ++differenceImageIt;
  } // end while differenceImageIt

  return measure;
}

/**
 * ********************* GetValue ******************************
 */

template <class TFixedImage, class TMovingImage>
typename PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetValue( const TransformParametersType & parameters ) const
{
  this->SetTransformParameters( parameters );
  this->m_TransformMovingImageFilter->Modified();
  this->m_DifferenceImageFilter->UpdateLargestPossibleRegion();
  MeasureType measure = 1e10;
  MeasureType currentMeasure = 1e10;

  if ( this->m_OptimizeNormalizationFactor )
  {
    float tmpfactor =  0.0;
    float factorstep =  ( this->m_NormalizationFactor * 10 - tmpfactor ) / 100;
    float bestfactor = tmpfactor;
    MeasureType tmpMeasure = 1e10;

    while ( tmpfactor <=  this->m_NormalizationFactor * 1.0 )
    {
      measure = this->ComputePIDiff( parameters, tmpfactor );
      tmpMeasure = ( measure - this->m_FixedMeasure ) / - this->m_Rescalingfactor;

      if( tmpMeasure < currentMeasure )
      {
        currentMeasure = tmpMeasure;
        bestfactor = tmpfactor;
      }

      tmpfactor += factorstep;
    }

  }

  else
  {
    measure = this->ComputePIDiff( parameters, this->m_NormalizationFactor );
    currentMeasure = -( measure - this->m_FixedMeasure ) / this->m_Rescalingfactor;
  }

	return currentMeasure;

}

/**
 * ********************* GetDerivative ******************************
 */

template < class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetDerivative( const TransformParametersType & parameters,
DerivativeType & derivative ) const
{
  TransformParametersType testPoint;
  testPoint = parameters;
  const unsigned int numberOfParameters = this->GetNumberOfParameters();
  derivative = DerivativeType( numberOfParameters );

  for ( unsigned int i = 0; i < numberOfParameters; i++ )
  {
    testPoint[ i ] -= this->m_DerivativeDelta / sqrt( this->m_Scales[ i ] );
    const MeasureType valuep0 = this->GetValue( testPoint );
    testPoint[ i ] += 2* this->m_DerivativeDelta / sqrt( this->m_Scales[ i ] );
    const MeasureType valuep1 = this->GetValue( testPoint );
    derivative[ i ] = ( valuep1 - valuep0 ) / ( 2 * this->m_DerivativeDelta / sqrt( this->m_Scales[ i ] ) );
    testPoint[ i ] = parameters[ i ];
	}
}

/**
 * ********************* GetValueAndDerivative ******************************
 */

template <class TFixedImage, class TMovingImage>
void
PatternIntensityImageToImageMetric<TFixedImage,TMovingImage>
::GetValueAndDerivative( const TransformParametersType & parameters,
MeasureType & Value, DerivativeType  & Derivative ) const
{
  Value = this->GetValue( parameters );
  this->GetDerivative( parameters, Derivative );
}

} // end namespace itk

#endif // end __itkPatternIntensityImageToImageMetric_txx

<|endoftext|>