Further optimizations...

* Screenshot feature removed to free up more ram.
* SCFG register changes on startup moved to dedicated function run from
ITCM memory. This should hopefully reduce instances where program hangs
at startup. Bootstarp is still provided incase some people still have
that problem.
This commit is contained in:
ApacheThunder 2024-03-20 16:10:48 -05:00
parent a10debc12f
commit 27d6c3c6c1
23 changed files with 89 additions and 427 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
*.cia
*.elf
*.cmd
*.dldi
data/*.bin
title/
gm9n_bootstrap/arm9/build

View File

@ -35,6 +35,7 @@ CFLAGS := -g -Wall -O2\
CFLAGS += $(INCLUDE) -DARM7
ASFLAGS := -g $(ARCH)
# LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map

View File

@ -1,123 +0,0 @@
#include "gba.h"
#include <nds/dma.h>
#include <nds/memory.h>
#include <nds/fifocommon.h>
#include <string.h>
#define EEPROM_ADDRESS (0x09FFFF00)
#define REG_EEPROM *(vu16 *)(EEPROM_ADDRESS)
#define DMA3_CR_H *(vu16 *)(0x040000DE)
void EEPROM_SendPacket(u16 *packet, int size)
{
REG_EXMEMSTAT = (REG_EXMEMSTAT & 0xFFE3) | 0x000C;
DMA3_SRC = (u32)packet;
DMA3_DEST = EEPROM_ADDRESS;
DMA3_CR = 0x80000000 + size;
while((DMA3_CR_H & 0x8000) != 0);
}
void EEPROM_ReceivePacket(u16 *packet, int size)
{
REG_EXMEMSTAT = (REG_EXMEMSTAT & 0xFFE3) | 0x000C;
DMA3_SRC = EEPROM_ADDRESS;
DMA3_DEST = (u32)packet;
DMA3_CR = 0x80000000 + size;
while((DMA3_CR_H & 0x8000) != 0);
}
void gbaEepromRead8Bytes(u8 *out, u16 addr, bool short_addr)
{
u16 packet[68];
memset(packet, 0, 68 * 2);
// Read request
packet[0] = 1;
packet[1] = 1;
// 6 or 14 bytes eeprom address (MSB first)
for(int i = 2, shift = (short_addr ? 5 : 13); i < (short_addr ? 8 : 16); i++, shift--) {
packet[i] = (addr >> shift) & 1;
}
// End of request
packet[short_addr ? 8 : 16] = 0;
// Do transfers
EEPROM_SendPacket(packet, short_addr ? 9 : 17);
memset(packet, 0, 68 * 2);
EEPROM_ReceivePacket(packet, 68);
// Extract data
u16 *in_pos = &packet[4];
for(int byte = 7; byte >= 0; --byte) {
u8 out_byte = 0;
for(int bit = 7; bit >= 0; --bit) {
// out_byte += (*in_pos++) << bit;
out_byte += ((*in_pos++) & 1) << bit;
}
*out++ = out_byte;
}
}
void gbaEepromWrite8Bytes(u8 *in, u16 addr, bool short_addr)
{
u16 packet_length = short_addr ? 73 : 81;
u16 packet[packet_length];
memset(packet, 0, packet_length * 2);
// Write request
packet[0] = 1;
packet[1] = 0;
// 6 or 14 bytes eeprom address (MSB first)
for(int i = 2, shift = (short_addr ? 5 : 13); i < (short_addr ? 8 : 16); i++, shift--) {
packet[i] = (addr >> shift) & 1;
}
// Extract data
u16 *out_pos = &packet[short_addr ? 8 : 16];
for(int byte = 7; byte >= 0; --byte) {
u8 in_byte = *in++;
for(int bit = 7; bit >= 0; --bit) {
*out_pos++ = (in_byte >> bit) & 1;
}
}
// End of request
packet[packet_length - 1] = 0;
// Do transfers
EEPROM_SendPacket(packet, packet_length);
// Wait for EEPROM to finish (should timeout after 10 ms)
while((REG_EEPROM & 1) == 0);
}
void readEeprom(u8 *dst, u32 src, u32 len)
{
int start, end;
start = src >> 3;
end = (src + len) >> 3;
u8 buffer[8];
for (int j = start; j < end; j++) {
gbaEepromRead8Bytes(buffer, j, len == 0x200);
fifoSendDatamsg(FIFO_USER_02, 8, buffer);
}
}
void writeEeprom(u32 dst, u8 *src, u32 len)
{
int start, end;
start = dst >> 3;
end = (dst + len) >> 3;
u8 *ptr = src;
for (int j = start; j < end; j++, ptr += 8) {
gbaEepromWrite8Bytes(ptr, j, len == 0x200);
}
fifoSendValue32(FIFO_USER_02, 0x454E4F44 /* 'DONE' */);
}

View File

@ -30,8 +30,6 @@
#include <nds.h>
#include <string.h>
#include "gba.h"
#define SD_IRQ_STATUS (*(vu32*)0x400481C)
#define BASE_DELAY (100)

View File

@ -48,12 +48,13 @@ GRAPHICS := ../gfx
ARCH := -mthumb-interwork
CFLAGS := -g -Wall -Wno-psabi -O2 \
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
-ffast-math \
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math \
$(ARCH)
# -mthumb -mthumb-interwork -march=armv5te -mtune=arm946e-s
CFLAGS += $(INCLUDE) -DARM9 -D_NO_BOOTSTUB_
CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++17
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
#CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=../ds_arm9_hi.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)

View File

@ -4,7 +4,8 @@
obtain one at https://mozilla.org/MPL/2.0/.
--------------------------------------------------------------------------------*/
MEMORY {
ewram : ORIGIN = 0x0200C000, LENGTH = 3M + 512K - 0xC000
/* ewram : ORIGIN = 0x0200C000, LENGTH = 3M + 512K - 0xC000 */
ewram : ORIGIN = 0x02000000, LENGTH = 4M - 512k
dtcm : ORIGIN = 0x0b000000, LENGTH = 16K
vectors : ORIGIN = 0x01000000, LENGTH = 256
itcm : ORIGIN = 0x01000100, LENGTH = 32K - 256

View File

@ -1,29 +0,0 @@
#ifndef _bmp_h_
#define _bmp_h_
#include <nds/ndstypes.h>
typedef struct {
u16 type; /* Magic identifier */
u32 size; /* File size in bytes */
u16 reserved1, reserved2;
u32 offset; /* Offset to image data, bytes */
} PACKED HEADER;
typedef struct {
u32 size; /* Header size in bytes */
u32 width, height; /* Width and height of image */
u16 planes; /* Number of colour planes */
u16 bits; /* Bits per pixel */
u32 compression; /* Compression type */
u32 imagesize; /* Image size in bytes */
u32 xresolution, yresolution; /* Pixels per meter */
u32 ncolours; /* Number of colours */
u32 importantcolours; /* Important colours */
u32 redBitmask; /* Red bitmask */
u32 greenBitmask; /* Green bitmask */
u32 blueBitmask; /* Blue bitmask */
u32 reserved;
} PACKED INFOHEADER;
#endif //_bmp_h_

View File

@ -1,7 +0,0 @@
#ifndef SCREENSHOT_H
#define SCREENSHOT_H
bool screenshot(void);
#endif // SCREENSHOT_H

View File

@ -30,7 +30,6 @@
#include "main.h"
#include "config.h"
#include "date.h"
#include "screenshot.h"
#include "driveOperations.h"
#include "fileOperations.h"
#include "font.h"
@ -124,9 +123,6 @@ void dm_drawBottomScreen(void) {
} else if(flashcardMounted) {
font->print(firstCol, row--, false, STR_UNMOUNT_FLASHCARD, alignStart);
}
if ((sdMounted && driveWritable(Drive::sdCard)) || (flashcardMounted && driveWritable(Drive::flashcard))) {
font->print(firstCol, row--, false, STR_SCREENSHOTTEXT, alignStart);
}
if(dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs || dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage) {
font->print(firstCol, row--, false, STR_IMAGETEXT, alignStart);
@ -299,9 +295,6 @@ void driveMenu (void) {
screenSwapped ? lcdMainOnBottom() : lcdMainOnTop();
}
// Make a screenshot
if ((held & KEY_R) && (pressed & KEY_L))screenshot();
if (isDSiMode() && !flashcardMountSkipped) {
if (driveRemoved(Drive::flashcard)) {
if (flashcardMounted) {

View File

@ -9,10 +9,10 @@
#include "file_browse.h"
#include "font.h"
#include "ndsheaderbanner.h"
#include "screenshot.h"
#include "language.h"
#define copyBufSize 0x8000
// #define copyBufSize 0x8000
#define copyBufSize 0x10000
#define shaChunkSize 0x10000
// u8* copyBuf = (u8*)0x02004000;
@ -321,7 +321,7 @@ bool fcopy(const char *sourcePath, const char *destinationPath) {
}
void changeFileAttribs(const DirEntry *entry) {
int pressed = 0, held = 0;
int pressed = 0;
int cursorScreenPos = font->calcHeight(entry->name);
uint8_t currentAttribs = FAT_getAttr(entry->name.c_str());
uint8_t newAttribs = currentAttribs;
@ -352,7 +352,6 @@ void changeFileAttribs(const DirEntry *entry) {
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
do {
scanKeys();
held = keysHeld();
pressed = keysDown();
swiWaitForVBlank();
} while (!(pressed & KEY_UP) && !(pressed & KEY_DOWN) && !(pressed & KEY_RIGHT) && !(pressed & KEY_LEFT)
@ -373,10 +372,7 @@ void changeFileAttribs(const DirEntry *entry) {
}
}
if (pressed & (KEY_A | KEY_B)) {
break;
} else if (held & KEY_R && pressed & KEY_L) {
screenshot();
}
if (pressed & (KEY_A | KEY_B))break;
}
}

View File

@ -35,7 +35,6 @@
#include "main.h"
#include "config.h"
#include "date.h"
#include "screenshot.h"
#include "fileOperations.h"
#include "driveMenu.h"
#include "driveOperations.h"
@ -171,7 +170,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
if(config->screenSwap())
lcdMainOnTop();
int pressed = 0, held = 0;
int pressed = 0;
std::vector<FileOperation> operations;
int optionOffset = 0;
std::string fullPath = curdir + entry->name;
@ -265,7 +264,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
do {
scanKeys();
pressed = keysDownRepeat();
held = keysHeld();
swiWaitForVBlank();
if(driveRemoved(currentDrive)) {
@ -288,6 +286,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
if (pressed & KEY_A) {
switch(operations[optionOffset]) {
case FileOperation::bootFile: {
font->clear(false);
applaunch = true;
font->print(optionsCol, optionOffset + y, false, STR_LOADING, alignStart);
font->update(false);
@ -399,10 +398,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
scanKeys();
pressed = keysDownRepeat();
swiWaitForVBlank();
if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
} while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X)));
break;
} case FileOperation::none: {
@ -421,10 +416,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
return FileOperation::none;
}
// Make a screenshot
else if ((held & KEY_R) && (pressed & KEY_L)) {
screenshot();
}
}
}
@ -536,9 +527,6 @@ void fileBrowse_drawBottomScreen(DirEntry* entry) {
}
font->print(firstCol, row--, false, STR_START_START_MENU, alignStart);
font->print(firstCol, row--, false, clipboardOn ? STR_CLEAR_CLIPBOARD : STR_RESTORE_CLIPBOARD, alignStart);
if ((sdMounted && driveWritable(Drive::sdCard)) || (flashcardMounted && driveWritable(Drive::flashcard))) {
font->print(firstCol, row--, false, STR_SCREENSHOTTEXT, alignStart);
}
font->print(firstCol, row--, false, STR_DIRECTORY_OPTIONS, alignStart);
if(driveWritable(currentDrive))
font->print(firstCol, row--, false, clipboardOn ? STR_PASTE_FILES_CREATE_ENTRY : STR_COPY_FILES_CREATE_ENTRY, alignStart);
@ -921,9 +909,7 @@ std::string browseForFile (void) {
} else if (pressed & config->screenSwapKey()) { // Swap screens
screenSwapped = !screenSwapped;
screenSwapped ? lcdMainOnBottom() : lcdMainOnTop();
} else if ((held & KEY_R) && (pressed & KEY_L)) { // Make a screenshot
if(screenshot())
getDirectoryContents(dirContents);
}
}
}

View File

@ -5,7 +5,6 @@
#include "keyboard.h"
#include "language.h"
#include "my_sd.h"
#include "screenshot.h"
#include "tonccpy.h"
#include <algorithm>
@ -44,8 +43,6 @@ u32 jumpToOffset(u32 offset) {
cursorPosition--;
} else if(pressed & (KEY_A | KEY_B)) {
return offset;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
}
@ -75,8 +72,6 @@ u32 search(u32 offset, FILE *file) {
break;
} else if(pressed & KEY_B) {
return offset;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
@ -137,8 +132,6 @@ u32 search(u32 offset, FILE *file) {
if(cursorPosition > strLen * 2 - 1)
cursorPosition -= 2;
}
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
}
@ -347,11 +340,8 @@ void hexEditor(const char *path, Drive drive) {
fwrite(data + cursorPosition, 1, 1, file);
}
}
if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
fclose(file);
}

View File

@ -40,6 +40,10 @@ std::string prevTime;
bool applaunch = false;
extern bool __dsimode;
bool forceNTRMode = true;
static int bg3;
//---------------------------------------------------------------------------------
@ -74,12 +78,8 @@ void vblankHandler (void) {
}
}
extern bool __dsimode;
bool forceNTRMode = true;
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
// MBK/RAM change should be done from ITCM as GBATek suggested. ;)
ITCM_CODE void SETSCFG() {
if (forceNTRMode && (REG_SCFG_EXT & BIT(31))) {
__dsimode = false;
int i;
@ -100,6 +100,12 @@ int main(int argc, char **argv) {
for (i = 0; i < 30; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); }
// REG_SCFG_EXT &= ~(1UL << 31);
}
}
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
SETSCFG();
// overwrite reboot stub identifier
extern u64 *fake_heap_end;
@ -112,18 +118,15 @@ int main(int argc, char **argv) {
bool yHeld = false;
// sprintf(titleName, "GodMode9i %s", VER_NUMBER);
sprintf(titleName, "GodMode9Nrio %s", "v3.4.4-NRIO");
sprintf(titleName, "GodMode9Nrio %s", "v3.4.5-NRIO");
// initialize video mode
videoSetMode(MODE_5_2D);
videoSetModeSub(MODE_5_2D);
// initialize VRAM banks
vramSetPrimaryBanks(VRAM_A_MAIN_BG,
VRAM_B_MAIN_SPRITE,
VRAM_C_SUB_BG,
VRAM_D_LCD);
vramSetBankI(VRAM_I_SUB_SPRITE);
// vramSetPrimaryBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE, VRAM_C_SUB_BG);
// vramSetBankI(VRAM_I_SUB_SPRITE);
// Init built-in font
font = new Font(nullptr);

View File

@ -2,7 +2,6 @@
#include "font.h"
#include "language.h"
#include "screenshot.h"
#include "tonccpy.h"
#include <nds.h>
@ -153,8 +152,6 @@ void ndsInfo(const char *path) {
lang++;
} else if(pressed & KEY_B) {
break;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
@ -166,3 +163,4 @@ void ndsInfo(const char *path) {
oamFreeGfx(&oamSub, iconGfx);
oamDisable(&oamSub);
}

View File

@ -35,10 +35,10 @@
#endif
#include "nds_loader_arm9.h"
#define LCDC_BANK_C (u16*)0x06840000
#define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_C) + 1))
#define INIT_DISC (*(((u32*)LCDC_BANK_C) + 2))
#define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_C) + 3))
#define LCDC_BANK_D (u16*)0x06860000
#define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_D) + 1))
#define INIT_DISC (*(((u32*)LCDC_BANK_D) + 2))
#define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_D) + 3))
/*
@ -255,8 +255,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS)
return true;
}
int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv)
{
ITCM_CODE int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv) {
char* argStart;
u16* argData;
u16 argTempVal = 0;
@ -266,47 +265,41 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool
irqDisable(IRQ_ALL);
// Direct CPU access to VRAM bank C
VRAM_C_CR = VRAM_ENABLE | VRAM_C_LCD;
VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD;
// Load the loader/patcher into the correct address
tonccpy (LCDC_BANK_C, loader, loaderSize);
tonccpy (LCDC_BANK_D, loader, loaderSize);
// Set the parameters for the loader
// STORED_FILE_CLUSTER = cluster;
writeAddr ((data_t*) LCDC_BANK_C, STORED_FILE_CLUSTER_OFFSET, cluster);
writeAddr ((data_t*) LCDC_BANK_D, STORED_FILE_CLUSTER_OFFSET, cluster);
// INIT_DISC = initDisc;
writeAddr ((data_t*) LCDC_BANK_C, INIT_DISC_OFFSET, initDisc);
writeAddr ((data_t*) LCDC_BANK_D, INIT_DISC_OFFSET, initDisc);
writeAddr ((data_t*) LCDC_BANK_C, DSIMODE_OFFSET, isDSiMode());
writeAddr ((data_t*) LCDC_BANK_D, DSIMODE_OFFSET, isDSiMode());
if(argv[0][0]=='s' && argv[0][1]=='d') {
dldiPatchNds = false;
writeAddr ((data_t*) LCDC_BANK_C, HAVE_DSISD_OFFSET, 1);
writeAddr ((data_t*) LCDC_BANK_D, HAVE_DSISD_OFFSET, 1);
}
// WANT_TO_PATCH_DLDI = dldiPatchNds;
writeAddr ((data_t*) LCDC_BANK_C, WANT_TO_PATCH_DLDI_OFFSET, dldiPatchNds);
writeAddr ((data_t*) LCDC_BANK_D, WANT_TO_PATCH_DLDI_OFFSET, dldiPatchNds);
// Give arguments to loader
argStart = (char*)LCDC_BANK_C + readAddr((data_t*)LCDC_BANK_C, ARG_START_OFFSET);
argStart = (char*)LCDC_BANK_D + readAddr((data_t*)LCDC_BANK_D, ARG_START_OFFSET);
argStart = (char*)(((int)argStart + 3) & ~3); // Align to word
argData = (u16*)argStart;
argSize = 0;
for (; argc > 0 && *argv; ++argv, --argc)
{
for (argChar = *argv; *argChar != 0; ++argChar, ++argSize)
{
if (argSize & 1)
{
for (; argc > 0 && *argv; ++argv, --argc) {
for (argChar = *argv; *argChar != 0; ++argChar, ++argSize) {
if (argSize & 1) {
argTempVal |= (*argChar) << 8;
*argData = argTempVal;
++argData;
}
else
{
} else {
argTempVal = *argChar;
}
}
if (argSize & 1)
{
if (argSize & 1) {
*argData = argTempVal;
++argData;
}
@ -315,49 +308,42 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool
}
*argData = argTempVal;
writeAddr ((data_t*) LCDC_BANK_C, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_C);
writeAddr ((data_t*) LCDC_BANK_C, ARG_SIZE_OFFSET, argSize);
writeAddr ((data_t*) LCDC_BANK_D, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_D);
writeAddr ((data_t*) LCDC_BANK_D, ARG_SIZE_OFFSET, argSize);
if(dldiPatchNds) {
// Patch the loader with a DLDI for the card
if (!dldiPatchLoader ((data_t*)LCDC_BANK_C, loaderSize, initDisc)) {
return 3;
}
if (!dldiPatchLoader ((data_t*)LCDC_BANK_D, loaderSize, initDisc))return 3;
}
irqDisable(IRQ_ALL);
// Give the VRAM to the ARM7
VRAM_C_CR = VRAM_ENABLE | VRAM_C_ARM7_0x06000000;
VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000;
// Reset into a passme loop
REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD;
*((vu32*)0x02FFFFFC) = 0;
*((vu32*)0x02FFFE04) = (u32)0xE59FF018;
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04;
resetARM7(0x06000000);
resetARM7(0x06020000);
swiSoftReset();
return true;
}
int runNdsFile (const char* filename, int argc, const char** argv) {
ITCM_CODE int runNdsFile (const char* filename, int argc, const char** argv) {
struct stat st;
char filePath[PATH_MAX];
int pathLen;
const char* args[1];
if (stat (filename, &st) < 0) {
return 1;
}
if (stat (filename, &st) < 0)return 1;
if (argc <= 0 || !argv) {
// Construct a command line if we weren't supplied with one
if (!getcwd (filePath, PATH_MAX)) {
return 2;
}
if (!getcwd (filePath, PATH_MAX))return 2;
pathLen = strlen(filePath);
if(pathLen < PATH_MAX && filePath[pathLen - 1] != '/') {
filePath[pathLen] = '/';

View File

@ -1,130 +0,0 @@
#include "screenshot.h"
#include "bmp.h"
#include "date.h"
#include "driveOperations.h"
#include "file_browse.h"
#include "font.h"
#include <dirent.h>
#include <fat.h>
#include <nds.h>
#include <stdio.h>
void wait();
void write16(void *address, u16 value) {
u8* first = (u8*)address;
u8* second = first + 1;
*first = value & 0xff;
*second = value >> 8;
}
void write32(void *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;
}
bool screenshotbmp(const char* filename) {
FILE *file = fopen(filename, "wb");
if(!file)
return false;
REG_DISPCAPCNT = DCAP_BANK(DCAP_BANK_VRAM_D) | DCAP_SIZE(DCAP_SIZE_256x192) | DCAP_ENABLE;
while(REG_DISPCAPCNT & DCAP_ENABLE);
u8* temp = new u8[256 * 192 * 2 + sizeof(INFOHEADER) + sizeof(HEADER)];
if(!temp) {
fclose(file);
return false;
}
HEADER *header= (HEADER*)temp;
INFOHEADER *infoheader = (INFOHEADER*)(temp + sizeof(HEADER));
write16(&header->type, 0x4D42);
write32(&header->size, 256 * 192 * 2 + sizeof(INFOHEADER) + sizeof(HEADER));
write32(&header->reserved1, 0);
write32(&header->reserved2, 0);
write32(&header->offset, sizeof(INFOHEADER) + sizeof(HEADER));
write32(&infoheader->size, sizeof(INFOHEADER));
write32(&infoheader->width, 256);
write32(&infoheader->height, 192);
write16(&infoheader->planes, 1);
write16(&infoheader->bits, 16);
write32(&infoheader->compression, 3);
write32(&infoheader->imagesize, 256 * 192 * 2);
write32(&infoheader->xresolution, 2835);
write32(&infoheader->yresolution, 2835);
write32(&infoheader->ncolours, 0);
write32(&infoheader->importantcolours, 0);
write32(&infoheader->redBitmask, 0xF800);
write32(&infoheader->greenBitmask, 0x07E0);
write32(&infoheader->blueBitmask, 0x001F);
write32(&infoheader->reserved, 0);
u16 *ptr = (u16*)(temp + sizeof(HEADER) + sizeof(INFOHEADER));
for(int y = 0; y < 192; y++) {
for(int x = 0; x < 256; x++) {
u16 color = VRAM_D[256 * 191 - y * 256 + x];
*(ptr++) = ((color >> 10) & 0x1F) | (color & (0x1F << 5)) << 1 | ((color & 0x1F) << 11);
}
}
DC_FlushAll();
fwrite(temp, 1, 256 * 192 * 2 + sizeof(INFOHEADER) + sizeof(HEADER), file);
fclose(file);
delete[] temp;
return true;
}
bool screenshot(void) {
if (!((sdMounted && driveWritable(Drive::sdCard)) || (flashcardMounted && driveWritable(Drive::flashcard))))
return false;
bool sdWritable = sdMounted && driveWritable(Drive::sdCard);
if (access((sdWritable ? "sd:/gm9i" : "fat:/gm9i"), F_OK) != 0) {
mkdir((sdWritable ? "sd:/gm9i" : "fat:/gm9i"), 0777);
}
if (access((sdWritable ? "sd:/gm9i/out" : "fat:/gm9i/out"), F_OK) != 0) {
mkdir((sdWritable ? "sd:/gm9i/out" : "fat:/gm9i/out"), 0777);
}
std::string fileTimeText = RetTime("%H%M%S");
char snapPath[40];
// Take top screenshot
snprintf(snapPath, sizeof(snapPath), "%s:/gm9i/out/snap_%s_top.bmp", (sdWritable ? "sd" : "fat"), fileTimeText.c_str());
if(!screenshotbmp(snapPath))
return false;
// Seamlessly swap top and bottom screens
font->mainOnTop(false);
font->update(false);
font->update(true);
lcdMainOnBottom();
// Take bottom screenshot
snprintf(snapPath, sizeof(snapPath), "%s:/gm9i/out/snap_%s_bot.bmp", (sdWritable ? "sd" : "fat"), fileTimeText.c_str());
if(!screenshotbmp(snapPath))
return false;
font->mainOnTop(true);
font->update(true);
font->update(false);
lcdMainOnTop();
return true;
}

View File

@ -5,7 +5,6 @@
#include "font.h"
#include "language.h"
#include "main.h"
#include "screenshot.h"
#include <array>
#include <nds.h>
@ -105,8 +104,6 @@ void startMenu() {
}
} else if(pressed & KEY_B) {
return;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
}
@ -188,8 +185,7 @@ void languageMenu() {
return;
} else if(pressed & KEY_B) {
return;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
}
}

View File

@ -4,7 +4,7 @@ ENTRY(_start)
MEMORY {
vram : ORIGIN = 0x06000000, LENGTH = 128K
vram : ORIGIN = 0x06020000, LENGTH = 64K
}
__vram_start = ORIGIN(vram);

View File

@ -33,7 +33,7 @@ void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)
TIMER_DATA(i) = 0;
}
VRAM_CR = (VRAM_CR & 0xffff0000) | 0x00008080 ;
/* VRAM_CR = (VRAM_CR & 0xffff0000) | 0x00008080 ;
vu16 *mainregs = (vu16*)0x04000000;
vu16 *subregs = (vu16*)0x04001000;
@ -55,7 +55,7 @@ void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)
VRAM_G_CR = 0;
VRAM_H_CR = 0;
VRAM_I_CR = 0;
REG_POWERCNT = 0x820F;
REG_POWERCNT = 0x820F;*/
//set shared ram to ARM7
WRAM_CR = 0x03;

View File

@ -77,11 +77,8 @@ void CartridgePrompt() {
for (int i = 0; i < 20; i++) { swiWaitForVBlank(); }
}
int main( int argc, char **argv) {
defaultExceptionHandler();
if (fatInitDefault()) {
CIniFile GM9NBootstrap( "/_nds/GM9N_Bootstrap.ini" );
std::string ndsPath = GM9NBootstrap.GetString( "GM9N_BOOTSTRAP", "SRL", "/NDS/GodMode9Nrio.nds");
ITCM_CODE void CheckSlot() {
if (REG_SCFG_MC == 0x11) {
do { CartridgePrompt(); }
while (REG_SCFG_MC == 0x11);
@ -95,6 +92,14 @@ int main( int argc, char **argv) {
enableSlot1();
}
}
}
ITCM_CODE int main( int argc, char **argv) {
defaultExceptionHandler();
if (fatInitDefault()) {
CIniFile GM9NBootstrap( "/_nds/GM9N_Bootstrap.ini" );
std::string ndsPath = GM9NBootstrap.GetString( "GM9N_BOOTSTRAP", "SRL", "/NDS/GodMode9Nrio.nds");
CheckSlot();
runNdsFile(ndsPath.c_str(), 0, NULL);
} else {
BootSplashInit();

View File

@ -57,20 +57,16 @@ static void writeAddr (data_t *mem, addr_t offset, addr_t value) {
((addr_t*)mem)[offset/sizeof(addr_t)] = value;
}
static void vramcpy (void* dst, const void* src, int len)
{
static void vramcpy (void* dst, const void* src, int len) {
u16* dst16 = (u16*)dst;
u16* src16 = (u16*)src;
//dmaCopy(src, dst, len);
for ( ; len > 0; len -= 2) {
*dst16++ = *src16++;
}
for ( ; len > 0; len -= 2) { *dst16++ = *src16++; }
}
int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, int argc, const char** argv)
{
ITCM_CODE int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, int argc, const char** argv) {
char* argStart;
u16* argData;
u16 argTempVal = 0;
@ -149,7 +145,7 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, int
return true;
}
int runNdsFile (const char* filename, int argc, const char** argv) {
ITCM_CODE int runNdsFile (const char* filename, int argc, const char** argv) {
struct stat st;
char filePath[PATH_MAX];
int pathLen;

View File

@ -117,7 +117,7 @@ void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)
#ifdef NTRMODE
// REG_SCFG_CLK = 0x80;
REG_SCFG_EXT = 0x03000000;
REG_SCFG_EXT = 0x03002000;
#endif
arm9code();
while(1);