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 *.cia
*.elf *.elf
*.cmd *.cmd
*.dldi
data/*.bin data/*.bin
title/ title/
gm9n_bootstrap/arm9/build gm9n_bootstrap/arm9/build

View File

@ -35,6 +35,7 @@ CFLAGS := -g -Wall -O2\
CFLAGS += $(INCLUDE) -DARM7 CFLAGS += $(INCLUDE) -DARM7
ASFLAGS := -g $(ARCH) 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 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 <nds.h>
#include <string.h> #include <string.h>
#include "gba.h"
#define SD_IRQ_STATUS (*(vu32*)0x400481C) #define SD_IRQ_STATUS (*(vu32*)0x400481C)
#define BASE_DELAY (100) #define BASE_DELAY (100)

View File

@ -48,12 +48,13 @@ GRAPHICS := ../gfx
ARCH := -mthumb-interwork ARCH := -mthumb-interwork
CFLAGS := -g -Wall -Wno-psabi -O2 \ CFLAGS := -g -Wall -Wno-psabi -O2 \
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math \
-ffast-math \ $(ARCH)
$(ARCH) # -mthumb -mthumb-interwork -march=armv5te -mtune=arm946e-s
CFLAGS += $(INCLUDE) -DARM9 -D_NO_BOOTSTUB_ 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) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=../ds_arm9_hi.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 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/. obtain one at https://mozilla.org/MPL/2.0/.
--------------------------------------------------------------------------------*/ --------------------------------------------------------------------------------*/
MEMORY { 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 dtcm : ORIGIN = 0x0b000000, LENGTH = 16K
vectors : ORIGIN = 0x01000000, LENGTH = 256 vectors : ORIGIN = 0x01000000, LENGTH = 256
itcm : ORIGIN = 0x01000100, LENGTH = 32K - 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 "main.h"
#include "config.h" #include "config.h"
#include "date.h" #include "date.h"
#include "screenshot.h"
#include "driveOperations.h" #include "driveOperations.h"
#include "fileOperations.h" #include "fileOperations.h"
#include "font.h" #include "font.h"
@ -124,10 +123,7 @@ void dm_drawBottomScreen(void) {
} else if(flashcardMounted) { } else if(flashcardMounted) {
font->print(firstCol, row--, false, STR_UNMOUNT_FLASHCARD, alignStart); 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) { if(dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs || dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage) {
font->print(firstCol, row--, false, STR_IMAGETEXT, alignStart); font->print(firstCol, row--, false, STR_IMAGETEXT, alignStart);
} }
@ -299,9 +295,6 @@ void driveMenu (void) {
screenSwapped ? lcdMainOnBottom() : lcdMainOnTop(); screenSwapped ? lcdMainOnBottom() : lcdMainOnTop();
} }
// Make a screenshot
if ((held & KEY_R) && (pressed & KEY_L))screenshot();
if (isDSiMode() && !flashcardMountSkipped) { if (isDSiMode() && !flashcardMountSkipped) {
if (driveRemoved(Drive::flashcard)) { if (driveRemoved(Drive::flashcard)) {
if (flashcardMounted) { if (flashcardMounted) {

View File

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

View File

@ -35,7 +35,6 @@
#include "main.h" #include "main.h"
#include "config.h" #include "config.h"
#include "date.h" #include "date.h"
#include "screenshot.h"
#include "fileOperations.h" #include "fileOperations.h"
#include "driveMenu.h" #include "driveMenu.h"
#include "driveOperations.h" #include "driveOperations.h"
@ -171,7 +170,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
if(config->screenSwap()) if(config->screenSwap())
lcdMainOnTop(); lcdMainOnTop();
int pressed = 0, held = 0; int pressed = 0;
std::vector<FileOperation> operations; std::vector<FileOperation> operations;
int optionOffset = 0; int optionOffset = 0;
std::string fullPath = curdir + entry->name; std::string fullPath = curdir + entry->name;
@ -265,7 +264,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
do { do {
scanKeys(); scanKeys();
pressed = keysDownRepeat(); pressed = keysDownRepeat();
held = keysHeld();
swiWaitForVBlank(); swiWaitForVBlank();
if(driveRemoved(currentDrive)) { if(driveRemoved(currentDrive)) {
@ -288,6 +286,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
if (pressed & KEY_A) { if (pressed & KEY_A) {
switch(operations[optionOffset]) { switch(operations[optionOffset]) {
case FileOperation::bootFile: { case FileOperation::bootFile: {
font->clear(false);
applaunch = true; applaunch = true;
font->print(optionsCol, optionOffset + y, false, STR_LOADING, alignStart); font->print(optionsCol, optionOffset + y, false, STR_LOADING, alignStart);
font->update(false); font->update(false);
@ -399,10 +398,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
scanKeys(); scanKeys();
pressed = keysDownRepeat(); pressed = keysDownRepeat();
swiWaitForVBlank(); swiWaitForVBlank();
if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
} while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X))); } while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X)));
break; break;
} case FileOperation::none: { } case FileOperation::none: {
@ -421,10 +416,6 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
return FileOperation::none; 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, STR_START_START_MENU, alignStart);
font->print(firstCol, row--, false, clipboardOn ? STR_CLEAR_CLIPBOARD : STR_RESTORE_CLIPBOARD, 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); font->print(firstCol, row--, false, STR_DIRECTORY_OPTIONS, alignStart);
if(driveWritable(currentDrive)) if(driveWritable(currentDrive))
font->print(firstCol, row--, false, clipboardOn ? STR_PASTE_FILES_CREATE_ENTRY : STR_COPY_FILES_CREATE_ENTRY, alignStart); 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 } else if (pressed & config->screenSwapKey()) { // Swap screens
screenSwapped = !screenSwapped; screenSwapped = !screenSwapped;
screenSwapped ? lcdMainOnBottom() : lcdMainOnTop(); 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 "keyboard.h"
#include "language.h" #include "language.h"
#include "my_sd.h" #include "my_sd.h"
#include "screenshot.h"
#include "tonccpy.h" #include "tonccpy.h"
#include <algorithm> #include <algorithm>
@ -44,8 +43,6 @@ u32 jumpToOffset(u32 offset) {
cursorPosition--; cursorPosition--;
} else if(pressed & (KEY_A | KEY_B)) { } else if(pressed & (KEY_A | KEY_B)) {
return offset; return offset;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
} }
} }
} }
@ -75,8 +72,6 @@ u32 search(u32 offset, FILE *file) {
break; break;
} else if(pressed & KEY_B) { } else if(pressed & KEY_B) {
return offset; 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) if(cursorPosition > strLen * 2 - 1)
cursorPosition -= 2; 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); fwrite(data + cursorPosition, 1, 1, file);
} }
} }
if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
}
} }
fclose(file); fclose(file);
} }

View File

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

View File

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

View File

@ -35,10 +35,10 @@
#endif #endif
#include "nds_loader_arm9.h" #include "nds_loader_arm9.h"
#define LCDC_BANK_C (u16*)0x06840000 #define LCDC_BANK_D (u16*)0x06860000
#define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_C) + 1)) #define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_D) + 1))
#define INIT_DISC (*(((u32*)LCDC_BANK_C) + 2)) #define INIT_DISC (*(((u32*)LCDC_BANK_D) + 2))
#define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_C) + 3)) #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; 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; char* argStart;
u16* argData; u16* argData;
u16 argTempVal = 0; u16 argTempVal = 0;
@ -266,47 +265,41 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool
irqDisable(IRQ_ALL); irqDisable(IRQ_ALL);
// Direct CPU access to VRAM bank C // 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 // 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 // Set the parameters for the loader
// STORED_FILE_CLUSTER = cluster; // 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; // 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') { if(argv[0][0]=='s' && argv[0][1]=='d') {
dldiPatchNds = false; 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; // 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 // 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 argStart = (char*)(((int)argStart + 3) & ~3); // Align to word
argData = (u16*)argStart; argData = (u16*)argStart;
argSize = 0; argSize = 0;
for (; argc > 0 && *argv; ++argv, --argc) for (; argc > 0 && *argv; ++argv, --argc) {
{ for (argChar = *argv; *argChar != 0; ++argChar, ++argSize) {
for (argChar = *argv; *argChar != 0; ++argChar, ++argSize) if (argSize & 1) {
{
if (argSize & 1)
{
argTempVal |= (*argChar) << 8; argTempVal |= (*argChar) << 8;
*argData = argTempVal; *argData = argTempVal;
++argData; ++argData;
} } else {
else
{
argTempVal = *argChar; argTempVal = *argChar;
} }
} }
if (argSize & 1) if (argSize & 1) {
{
*argData = argTempVal; *argData = argTempVal;
++argData; ++argData;
} }
@ -315,49 +308,42 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool
} }
*argData = argTempVal; *argData = argTempVal;
writeAddr ((data_t*) LCDC_BANK_C, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_C); writeAddr ((data_t*) LCDC_BANK_D, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_D);
writeAddr ((data_t*) LCDC_BANK_C, ARG_SIZE_OFFSET, argSize); writeAddr ((data_t*) LCDC_BANK_D, ARG_SIZE_OFFSET, argSize);
if(dldiPatchNds) { if(dldiPatchNds) {
// Patch the loader with a DLDI for the card // Patch the loader with a DLDI for the card
if (!dldiPatchLoader ((data_t*)LCDC_BANK_C, loaderSize, initDisc)) { if (!dldiPatchLoader ((data_t*)LCDC_BANK_D, loaderSize, initDisc))return 3;
return 3;
}
} }
irqDisable(IRQ_ALL); irqDisable(IRQ_ALL);
// Give the VRAM to the ARM7 // 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 // Reset into a passme loop
REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD;
*((vu32*)0x02FFFFFC) = 0; *((vu32*)0x02FFFFFC) = 0;
*((vu32*)0x02FFFE04) = (u32)0xE59FF018; *((vu32*)0x02FFFE04) = (u32)0xE59FF018;
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04; *((vu32*)0x02FFFE24) = (u32)0x02FFFE04;
resetARM7(0x06000000); resetARM7(0x06020000);
swiSoftReset(); swiSoftReset();
return true; 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; struct stat st;
char filePath[PATH_MAX]; char filePath[PATH_MAX];
int pathLen; int pathLen;
const char* args[1]; const char* args[1];
if (stat (filename, &st) < 0) { if (stat (filename, &st) < 0)return 1;
return 1;
}
if (argc <= 0 || !argv) { if (argc <= 0 || !argv) {
// Construct a command line if we weren't supplied with one // Construct a command line if we weren't supplied with one
if (!getcwd (filePath, PATH_MAX)) { if (!getcwd (filePath, PATH_MAX))return 2;
return 2;
}
pathLen = strlen(filePath); pathLen = strlen(filePath);
if(pathLen < PATH_MAX && filePath[pathLen - 1] != '/') { if(pathLen < PATH_MAX && filePath[pathLen - 1] != '/') {
filePath[pathLen] = '/'; 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 "font.h"
#include "language.h" #include "language.h"
#include "main.h" #include "main.h"
#include "screenshot.h"
#include <array> #include <array>
#include <nds.h> #include <nds.h>
@ -105,8 +104,6 @@ void startMenu() {
} }
} else if(pressed & KEY_B) { } else if(pressed & KEY_B) {
return; return;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
} }
} }
} }
@ -188,8 +185,7 @@ void languageMenu() {
return; return;
} else if(pressed & KEY_B) { } else if(pressed & KEY_B) {
return; return;
} else if(keysHeld() & KEY_R && pressed & KEY_L) {
screenshot();
} }
} }
} }

View File

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

View File

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

View File

@ -77,24 +77,29 @@ void CartridgePrompt() {
for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } for (int i = 0; i < 20; i++) { swiWaitForVBlank(); }
} }
int main( int argc, char **argv) {
ITCM_CODE void CheckSlot() {
if (REG_SCFG_MC == 0x11) {
do { CartridgePrompt(); }
while (REG_SCFG_MC == 0x11);
disableSlot1();
for (int i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
} else {
if(REG_SCFG_MC == 0x10) {
disableSlot1();
for (int i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
}
}
}
ITCM_CODE int main( int argc, char **argv) {
defaultExceptionHandler(); defaultExceptionHandler();
if (fatInitDefault()) { if (fatInitDefault()) {
CIniFile GM9NBootstrap( "/_nds/GM9N_Bootstrap.ini" ); CIniFile GM9NBootstrap( "/_nds/GM9N_Bootstrap.ini" );
std::string ndsPath = GM9NBootstrap.GetString( "GM9N_BOOTSTRAP", "SRL", "/NDS/GodMode9Nrio.nds"); std::string ndsPath = GM9NBootstrap.GetString( "GM9N_BOOTSTRAP", "SRL", "/NDS/GodMode9Nrio.nds");
if (REG_SCFG_MC == 0x11) { CheckSlot();
do { CartridgePrompt(); }
while (REG_SCFG_MC == 0x11);
disableSlot1();
for (int i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
} else {
if(REG_SCFG_MC == 0x10) {
disableSlot1();
for (int i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
}
}
runNdsFile(ndsPath.c_str(), 0, NULL); runNdsFile(ndsPath.c_str(), 0, NULL);
} else { } else {
BootSplashInit(); 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; ((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* dst16 = (u16*)dst;
u16* src16 = (u16*)src; u16* src16 = (u16*)src;
//dmaCopy(src, dst, len); //dmaCopy(src, dst, len);
for ( ; len > 0; len -= 2) { for ( ; len > 0; len -= 2) { *dst16++ = *src16++; }
*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; char* argStart;
u16* argData; u16* argData;
u16 argTempVal = 0; u16 argTempVal = 0;
@ -149,7 +145,7 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, int
return true; 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; struct stat st;
char filePath[PATH_MAX]; char filePath[PATH_MAX];
int pathLen; int pathLen;

View File

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