diff --git a/arm9/source/date.cpp b/arm9/source/date.cpp index 840fe18..531b785 100644 --- a/arm9/source/date.cpp +++ b/arm9/source/date.cpp @@ -60,12 +60,28 @@ string RetTime() time(&Raw); const struct tm *Time = localtime(&Raw); - char Tmp[24]; + char Tmp[8]; strftime(Tmp, sizeof(Tmp), "%k:%M", Time); return string(Tmp); } +/** + * Get the current time formatted for filenames. + * @return std::string containing the time. + */ +string RetTimeForFilename() +{ + time_t Raw; + time(&Raw); + const struct tm *Time = localtime(&Raw); + + char Tmp[8]; + strftime(Tmp, sizeof(Tmp), "%k%M%S", Time); + + return string(Tmp); +} + /** * Draw the date using the specified format. * @param Xpos X position. diff --git a/arm9/source/date.h b/arm9/source/date.h index d712d4d..a5602dc 100644 --- a/arm9/source/date.h +++ b/arm9/source/date.h @@ -32,6 +32,12 @@ size_t GetDate(DateFormat format, char *buf, size_t size); */ std::string RetTime(); +/** + * Get the current time formatted for filenames. + * @return std::string containing the time. + */ +std::string RetTimeForFilename(); + /** * Draw the date using the specified format. * @param format Date format. diff --git a/arm9/source/driveMenu.cpp b/arm9/source/driveMenu.cpp index d7f212a..80a8e69 100644 --- a/arm9/source/driveMenu.cpp +++ b/arm9/source/driveMenu.cpp @@ -28,6 +28,7 @@ #include "main.h" #include "date.h" +#include "screenshot.h" #include "driveOperations.h" #define SCREEN_COLS 32 @@ -179,6 +180,10 @@ void driveMenu (void) { printf ("\n"); printf (flashcardMounted ? "R+B - Unmount Flashcard" : "R+B - Remount Flashcard"); } + if (sdMounted || flashcardMounted) { + printf ("\n"); + printf (SCREENSHOTTEXT); + } printf ("\n"); if (!isDSiMode() && isRegularDS) { printf (POWERTEXT_DS); @@ -353,6 +358,15 @@ void driveMenu (void) { } } + // Make a screenshot + if ((held & KEY_R) && (pressed & KEY_L)) { + if (sdMounted || flashcardMounted) { + char snapPath[32]; + snprintf(snapPath, sizeof(snapPath), "%s:/gm9i/out/snap_%s.bmp", (sdMounted ? "sd" : "fat"), RetTimeForFilename().c_str()); + screenshotbmp(snapPath); + } + } + if (isDSiMode() && !flashcardMountSkipped && !pressed && !held) { if (REG_SCFG_MC == 0x11) { if (flashcardMounted) { diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 5ef0dc5..8d47668 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -32,6 +32,7 @@ #include "main.h" #include "date.h" +#include "screenshot.h" #include "fileOperations.h" #include "driveMenu.h" #include "driveOperations.h" @@ -389,6 +390,7 @@ void recRemove(DirEntry* entry, std::vector dirContents) { string browseForFile (void) { int pressed = 0; + int held = 0; int screenOffset = 0; int fileOffset = 0; vector dirContents; @@ -406,6 +408,8 @@ string browseForFile (void) { printf ("\n"); printf (clipboardOn ? "Y - PASTE file" : "Y - COPY file"); printf ("\n"); + printf (SCREENSHOTTEXT); + printf ("\n"); printf (clipboardOn ? "SELECT - Clear Clipboard" : "SELECT - Restore Clipboard"); printf ("\n"); if (!isDSiMode() && isRegularDS) { @@ -454,11 +458,16 @@ string browseForFile (void) { scanKeys(); pressed = keysDownRepeat(); + held = keysHeld(); swiWaitForVBlank(); if (REG_SCFG_MC != stored_SCFG_MC) { break; } + + if ((held & KEY_R) && (pressed & KEY_L)) { + break; + } } while (!(pressed & KEY_UP) && !(pressed & KEY_DOWN) && !(pressed & KEY_LEFT) && !(pressed & KEY_RIGHT) && !(pressed & KEY_A) && !(pressed & KEY_B) && !(pressed & KEY_X) && !(pressed & KEY_Y) && !(pressed & KEY_SELECT)); @@ -598,5 +607,15 @@ string browseForFile (void) { if ((pressed & KEY_SELECT) && clipboardUsed) { clipboardOn = !clipboardOn; } + + // Make a screenshot + if ((held & KEY_R) && (pressed & KEY_L)) { + char snapPath[32]; + snprintf(snapPath, sizeof(snapPath), "%s:/gm9i/out/snap_%s.bmp", (sdMounted ? "sd" : "fat"), RetTimeForFilename().c_str()); + screenshotbmp(snapPath); + if (strcmp (path, (sdMounted ? "sd:/gm9i/out/" : "fat:/gm9i/out/")) == 0) { + getDirectoryContents (dirContents); + } + } } } diff --git a/arm9/source/main.h b/arm9/source/main.h index 8185543..82a44b4 100644 --- a/arm9/source/main.h +++ b/arm9/source/main.h @@ -1,10 +1,11 @@ #ifndef MAIN_H #define MAIN_H -#define POWERTEXT_DS "POWER - Poweroff" -#define POWERTEXT "POWER - Reboot/[+held] Poweroff" -#define POWERTEXT_3DS "POWER - Sleep Mode screen" -#define HOMETEXT "HOME - HOME Menu prompt" +#define POWERTEXT_DS "POWER - Poweroff" +#define POWERTEXT "POWER - Reboot/[+held] Poweroff" +#define POWERTEXT_3DS "POWER - Sleep Mode screen" +#define HOMETEXT "HOME - HOME Menu prompt" +#define SCREENSHOTTEXT "R+L - Make a screenshot" extern char titleName[32]; diff --git a/arm9/source/screenshot.cpp b/arm9/source/screenshot.cpp new file mode 100644 index 0000000..c981406 --- /dev/null +++ b/arm9/source/screenshot.cpp @@ -0,0 +1,117 @@ +#include +#include +#include + +#include + +#include "screenshot.h" +#include "bmp.h" + +void wait(); + +void screenshot(u8* buffer) { + + u8 vram_cr_temp=VRAM_A_CR; + VRAM_A_CR=VRAM_A_LCD; + + u8* vram_temp=(u8*)malloc(128*1024); + dmaCopy(VRAM_A, vram_temp, 128*1024); + + REG_DISPCAPCNT=DCAP_BANK(0)|DCAP_ENABLE|DCAP_SIZE(3); + while(REG_DISPCAPCNT & DCAP_ENABLE); + + dmaCopy(VRAM_A, buffer, 256*192*2); + dmaCopy(vram_temp, VRAM_A, 128*1024); + + VRAM_A_CR=vram_cr_temp; + + free(vram_temp); + +} + +void screenshot(char* filename) { + + //fatInitDefault(); + FILE* file=fopen(filename, "w"); + + u8* temp=(u8*)malloc(256*192*2); + dmaCopy(VRAM_B, temp, 256*192*2); + fwrite(temp, 1, 256*192*2, file); + fclose(file); + free(temp); +} + +void write16(u16* address, u16 value) { + + u8* first=(u8*)address; + u8* second=first+1; + + *first=value&0xff; + *second=value>>8; +} + +void write32(u32* address, u32 value) { + + u8* first=(u8*)address; + u8* second=first+1; + u8* third=first+2; + u8* fourth=first+3; + + *first=value&0xff; + *second=(value>>8)&0xff; + *third=(value>>16)&0xff; + *fourth=(value>>24)&0xff; +} + +void screenshotbmp(const char* filename) { + + //fatInitDefault(); + FILE* file=fopen(filename, "wb"); + + REG_DISPCAPCNT=DCAP_BANK(3)|DCAP_ENABLE|DCAP_SIZE(3); + while(REG_DISPCAPCNT & DCAP_ENABLE); + + u8* temp=(u8*)malloc(256*192*3+sizeof(INFOHEADER)+sizeof(HEADER)); + + HEADER* header=(HEADER*)temp; + INFOHEADER* infoheader=(INFOHEADER*)(temp+sizeof(HEADER)); + + write16(&header->type, 0x4D42); + write32(&header->size, 256*192*3+sizeof(INFOHEADER)+sizeof(HEADER)); + write32(&header->offset, sizeof(INFOHEADER)+sizeof(HEADER)); + write16(&header->reserved1, 0); + write16(&header->reserved2, 0); + + write16(&infoheader->bits, 24); + write32(&infoheader->size, sizeof(INFOHEADER)); + write32(&infoheader->compression, 0); + write32(&infoheader->width, 256); + write32(&infoheader->height, 192); + write16(&infoheader->planes, 1); + write32(&infoheader->imagesize, 256*192*3); + write32(&infoheader->xresolution, 0); + write32(&infoheader->yresolution, 0); + write32(&infoheader->importantcolours, 0); + write32(&infoheader->ncolours, 0); + + for(int y=0;y<192;y++) + { + for(int x=0;x<256;x++) + { + u16 color=VRAM_D[256*192-y*256+x]; + + u8 b=(color&31)<<3; + u8 g=((color>>5)&31)<<3; + u8 r=((color>>10)&31)<<3; + + temp[((y*256)+x)*3+sizeof(INFOHEADER)+sizeof(HEADER)]=r; + temp[((y*256)+x)*3+1+sizeof(INFOHEADER)+sizeof(HEADER)]=g; + temp[((y*256)+x)*3+2+sizeof(INFOHEADER)+sizeof(HEADER)]=b; + } + } + + DC_FlushAll(); + fwrite(temp, 1, 256*192*3+sizeof(INFOHEADER)+sizeof(HEADER), file); + fclose(file); + free(temp); +}