Re-add ability to run on DS/DS lite

Memory Expansion Pak is required for music and to increase character limit from 2 to 5
This commit is contained in:
RocketRobz 2021-06-14 13:37:08 -06:00
parent a2f2d25eca
commit 07cda03b36
25 changed files with 623 additions and 175 deletions

View File

@ -24,7 +24,8 @@ makearm9:
$(TARGET).nds: makearm7 makearm9
ndstool -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf -d $(NITRODATA) \
-g HPHA 00 "SUPERPHOTO" -z 80040000 -u 00030004 -a 00000138 -b icon.bmp "Super Photo Studio;RocketRobz"
-g HPHA 00 "SUPERPHOTO" -z 80040000 -u 00030004 -a 00000138 -b icon.bmp "Super Photo Studio;Rocket Robz"
python2 patch_ndsheader_dsiware.py $(TARGET).nds --twlTouch
clean:
@echo clean ...

View File

@ -27,7 +27,7 @@ MUSIC := ../sound
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -marm -mthumb-interwork
ARCH := -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O3 \
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\

View File

@ -19,6 +19,7 @@
extern "C" {
#endif
void init_streaming_buf(void);
mm_word on_stream_request(mm_word length, mm_addr dest, mm_stream_formats format);
#ifdef __cplusplus

View File

@ -0,0 +1,14 @@
#ifndef MY_DSI_MODE_INCLUDE
#define MY_DSI_MODE_INCLUDE
#include <nds/ndstypes.h>
#include <nds/system.h>
// Checks if DSi features are enabled,
// regardless if the console runs in DS or DSi mode
static inline
bool dsiFeatures(void) {
return (isDSiMode() || REG_SCFG_EXT != 0);
}
#endif

View File

@ -1,8 +1,9 @@
#include "common.hpp"
#include "color.h"
#include "lodepng.h"
#include "tonccpy.h"
#include "myDSiMode.h"
#include "sound.h"
#include "tonccpy.h"
#include "photo_bg.h"
@ -12,8 +13,8 @@
#define charSpriteSize 0x18000
u16 bmpImageBuffer[2][256*192];
u16 bmpImageBuffer2[2][256*192];
static u16 bgSpriteMem[(256*192)*3] = {0};
u16* bmpImageBuffer2[2] = {NULL};
static u16* bgSpriteMem = NULL;
static u16 charSpriteMem[2][(256*192)*3];
static u8 charSpriteAlpha[2][(256*192)*3];
static u16* charSpriteMem3 = (u16*)0x02480000;
@ -22,6 +23,9 @@ static u16* charSpriteMem5 = (u16*)0x02510000;
static u8* charSpriteAlpha3 = (u8*)0x02558000;
static u8* charSpriteAlpha4 = (u8*)0x0257C000;
static u8* charSpriteAlpha5 = (u8*)0x025A0000;
static u16* charSpriteAlpha3_16 = (u16*)0x09100000;
static u16* charSpriteAlpha4_16 = (u16*)0x09148000;
static u16* charSpriteAlpha5_16 = (u16*)0x09190000;
static u16* bgSpriteMemExt[3] = {(u16*)0x025C8000, (u16*)0x02610000, (u16*)0x02658000};
static u16* charSpriteMem_2[2] = {(u16*)0x026F0000, (u16*)0x02738000};
static u16* charSpriteMem3_2 = (u16*)0x02780000;
@ -71,30 +75,26 @@ void GFX::resetCharStatus(int num) {
chracterSpriteFound[4] = false;
}
//extern int characterLimit;
extern int characterLimit;
extern bool mepFound;
void GFX::loadSheets() {
/*if (!isDSiMode()) {
//sysSetCartOwner (BUS_OWNER_ARM9); // Allow arm9 to access GBA ROM (or in this case, the DS Memory Expansion Pak)
*(vu32*)(0x08240000) = 1;
if (*(vu32*)(0x08240000) == 1) {
charSpriteMem3 = (u16*)0x09000000;
charSpriteMem4 = (u16*)0x09048000;
charSpriteMem5 = (u16*)0x09090000;
charSpriteAlpha3 = (u8*)0x090D8000;
charSpriteAlpha4 = (u8*)0x090FC000;
charSpriteAlpha5 = (u8*)0x09120000;
bgSpriteMemExt[0] = (u16*)0x09148000;
bgSpriteMemExt[1] = (u16*)0x09190000;
bgSpriteMemExt[2] = (u16*)0x091D8000;
if (mepFound) {
charSpriteMem3 = (u16*)0x09000000;
charSpriteMem4 = (u16*)0x09048000;
charSpriteMem5 = (u16*)0x09090000;
bgSpriteMemExt[0] = (u16*)0x09248000;
bgSpriteMemExt[1] = (u16*)0x09290000;
bgSpriteMemExt[2] = (u16*)0x092C8000;
}
if (*(vu32*)(0x02403FFC) == 1 || mepFound) {
characterLimit = 4; // Up the limit from 2 to 5 characters
if (dsiFeatures()) {
bmpImageBuffer2[0] = new u16[256*192];
bmpImageBuffer2[1] = new u16[256*192];
}
}
// Check for DS Debug RAM or DSi RAM
*(vu32*)(0x0279FFFC) = 1;
*(vu32*)(0x0239FFFC) = 0;
if (*(vu32*)(0x0279FFFC) == 1 || *(vu32*)(0x08240000) == 1) {
characterLimit = 4; // Up the limit from 2 to 5 characters
}*/
bgSpriteMem = mepFound ? (u16*)0x09200000 : new u16[(256*192)*3];
int metalXpos = 0;
int metalYpos = 0;
@ -140,6 +140,7 @@ void GFX::loadSheets() {
} else if (i >= 256*72 && i < 256*131) {
bmpImageBuffer[0][i] = alphablend(bmpImageBuffer[1][i], charSpriteMem[0][(metalYpos*384)+metalXpos], charSpriteAlpha[0][i]);
}
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -169,16 +170,19 @@ void GFX::loadSheets() {
} else if (i >= 256*72 && i < 256*131) {
bmpImageBuffer2[0][i] = alphablend(bmpImageBuffer2[1][i], charSpriteMem[0][(metalYpos*384)+metalXpos], charSpriteAlpha[0][i]);
}
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
dmaCopyHalfWords(0, bmpImageBuffer[0], bgSpriteMem, 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2, 0x18000);
dmaCopyHalfWords(0, bmpImageBuffer[0], bgSpriteMem+(charSpriteSize/2), 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2+(charSpriteSize/2), 0x18000);
dmaCopyHalfWords(0, bmpImageBuffer[0], bgSpriteMem+((charSpriteSize/2)*2), 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2+((charSpriteSize/2)*2), 0x18000);
if (dsiFeatures()) {
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2, 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2+(charSpriteSize/2), 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bgSpriteMem2+((charSpriteSize/2)*2), 0x18000);
}
}
void updateTitleScreen(const int metalXposBase) {
@ -196,16 +200,16 @@ void updateTitleScreen(const int metalXposBase) {
if (charSpriteAlpha[0][i] != 255) {
if (charSpriteAlpha[0][i] == 0) {
bmpImageBuffer[0][i] = charSpriteMem[0][(metalYpos*384)+metalXpos];
bmpImageBuffer2[0][i] = charSpriteMem[0][(metalYpos*384)+metalXpos];
if (dsiFeatures()) bmpImageBuffer2[0][i] = charSpriteMem[0][(metalYpos*384)+metalXpos];
} else if (i >= 256*72 && i < 256*131) {
bmpImageBuffer[0][i] = alphablend(bmpImageBuffer[1][i], charSpriteMem[0][(metalYpos*384)+metalXpos], charSpriteAlpha[0][i]);
bmpImageBuffer2[0][i] = alphablend(bmpImageBuffer2[1][i], charSpriteMem[0][(metalYpos*384)+metalXpos], charSpriteAlpha[0][i]);
if (dsiFeatures()) bmpImageBuffer2[0][i] = alphablend(bmpImageBuffer2[1][i], charSpriteMem[0][(metalYpos*384)+metalXpos], charSpriteAlpha[0][i]);
}
}
}
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bgGetGfxPtr(bg2Main), 0x18000);
dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
if (!titleBottomLoaded) {
//tonccpy(bgGetGfxPtr(bg3Sub), photo_bgBitmap, photo_bgBitmapLen);
decompress(photo_bgBitmap, bgGetGfxPtr(bg3Sub), LZ77Vram);
@ -238,9 +242,11 @@ void GFX::loadBgSprite(void) {
animateTitle = false;
swiWaitForVBlank(); // Prevent screen tearing
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg2Main), 0x18000);
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) {
swiWaitForVBlank(); // Prevent screen tearing
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg2Main), 0x18000);
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg3Main), 0x18000);
}
timeOutside = 2; // Default is Nighttime
int aniFrames = 0;
@ -583,6 +589,7 @@ void GFX::loadBgSprite(void) {
}
}
bgSpriteMem[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -605,6 +612,7 @@ void GFX::loadBgSprite(void) {
}
}
bgSpriteMem2[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
@ -616,7 +624,7 @@ void GFX::loadBgSprite(void) {
animateBg = false;
// Load animated parts
if (aniFrames > 0) {
if (aniFrames > 0 && characterLimit == 4) {
switch (studioBg) {
case 12:
if (timeOutside == 0) {
@ -658,6 +666,7 @@ void GFX::loadBgSprite(void) {
}
}
bgSpriteMemExt[i-1][p] = image[p*4]>>3 | (image[(p*4)+1]>>3)<<5 | (image[(p*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(p*4)+3] & BIT(0)) {
image[(p*4)] += 0x4;
@ -680,6 +689,7 @@ void GFX::loadBgSprite(void) {
}
}
bgSpriteMemExt2[i-1][p] = image[p*4]>>3 | (image[(p*4)+1]>>3)<<5 | (image[(p*4)+2]>>3)<<10 | BIT(15);
}
if ((p % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
@ -721,10 +731,10 @@ void GFX::reloadBgSprite() {
unloadBgSprite();
loadBgSprite();
dmaCopyHalfWords(0, bgSpriteMem, bmpImageBuffer[0], 0x18000);
dmaCopyHalfWords(1, bgSpriteMem2, bmpImageBuffer2[0], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bgSpriteMem2, bmpImageBuffer2[0], 0x18000);
swiWaitForVBlank(); // Prevent screen tearing
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bgGetGfxPtr(bg2Main), 0x18000);
dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
}
bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3xPathOneSeason) {
@ -752,8 +762,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
bool alternatePixel = false;
if (num == 4) {
for(unsigned i=0;i<image.size()/4;i++) {
//tonccpy(&charSpriteAlpha5[i], &image[(i*4)+3], 1);
charSpriteAlpha5[i] = image[(i*4)+3];
if (mepFound) charSpriteAlpha5_16[i] = image[(i*4)+3]; else charSpriteAlpha5[i] = image[(i*4)+3];
image[(i*4)+3] = 0;
if (alternatePixel) {
if (image[(i*4)] >= 0x4) {
@ -770,6 +779,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem5[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -792,13 +802,13 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem5_2[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
} else if (num == 3) {
for(unsigned i=0;i<image.size()/4;i++) {
//tonccpy(&charSpriteAlpha4[i], &image[(i*4)+3], 1);
charSpriteAlpha4[i] = image[(i*4)+3];
if (mepFound) charSpriteAlpha4_16[i] = image[(i*4)+3]; else charSpriteAlpha4[i] = image[(i*4)+3];
image[(i*4)+3] = 0;
if (alternatePixel) {
if (image[(i*4)] >= 0x4) {
@ -815,6 +825,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem4[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -837,13 +848,13 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem4_2[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
} else if (num == 2) {
for(unsigned i=0;i<image.size()/4;i++) {
//tonccpy(&charSpriteAlpha3[i], &image[(i*4)+3], 1);
charSpriteAlpha3[i] = image[(i*4)+3];
if (mepFound) charSpriteAlpha3_16[i] = image[(i*4)+3]; else charSpriteAlpha3[i] = image[(i*4)+3];
image[(i*4)+3] = 0;
if (alternatePixel) {
if (image[(i*4)] >= 0x4) {
@ -860,6 +871,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem3[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -882,6 +894,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem3_2[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
@ -904,6 +917,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem[num][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -926,6 +940,7 @@ bool GFX::loadCharSprite(int num, const char* t3xPathAllSeasons, const char* t3x
}
}
charSpriteMem_2[num][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
@ -948,11 +963,11 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
dmaCopyHalfWords(0, bgLoc+((256*192)*zoomIn), bmpImageBuffer[0], 0x18000);
dmaCopyHalfWords(1, bgLoc2+((256*192)*zoomIn), bmpImageBuffer2[0], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bgLoc2+((256*192)*zoomIn), bmpImageBuffer2[0], 0x18000);
if (!displayChars || !chracterSpriteFound[0]) {
swiWaitForVBlank(); // Prevent screen tearing
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bgGetGfxPtr(bg2Main), 0x18000);
dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[0], bgGetGfxPtr(bg3Main), 0x18000);
return;
}
@ -1020,6 +1035,7 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
int x2 = 0;
u16 color = 0;
u16 color2 = 0;
u16 alpha = 0;
if (chracterSpriteFound[2]) {
// Character 1
for (int y = 0; y < 192; y++) {
@ -1035,10 +1051,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
if (charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)] == 255) {
bmpImageBuffer[0][(y*256)+x2] = color;
bmpImageBuffer2[0][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = color2;
} else {
bmpImageBuffer[0][(y*256)+x2] = alphablend(color, bgLoc[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
}
}
flipH[0] ? x2-- : x2++;
@ -1046,7 +1062,7 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
// Character 2
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bmpImageBuffer[1], 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000); else while(dmaBusy(0));
for (int y = 0; y < 192; y++) {
x2 = flipH[1] ? 255 : 0;
for (int x = 0; x < 256; x++) {
@ -1059,10 +1075,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
if (charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)] == 255) {
bmpImageBuffer[1][(y*256)+x2] = color;
bmpImageBuffer2[1][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[1][(y*256)+x2] = color2;
} else {
bmpImageBuffer[1][(y*256)+x2] = alphablend(color, bmpImageBuffer[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[1][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
if (dsiFeatures()) bmpImageBuffer2[1][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
}
}
flipH[1] ? x2-- : x2++;
@ -1070,24 +1086,25 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
// Character 3
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[1], bmpImageBuffer[0], 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[1], bmpImageBuffer2[0], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bmpImageBuffer2[1], bmpImageBuffer2[0], 0x18000); else while(dmaBusy(0));
for (int y = 0; y < 192; y++) {
x2 = flipH[2] ? 255 : 0;
x2 += (zoomIn==1 ? 96 : 50);
for (int x = 0; x < 256; x++) {
if (x2 >= 0 && x2 < 256 && charSpriteAlpha3[((y*256)+x)+((256*192)*zoomIn)] != 0) {
alpha = mepFound ? charSpriteAlpha3_16[((y*256)+x)+((256*192)*zoomIn)] : charSpriteAlpha3[((y*256)+x)+((256*192)*zoomIn)];
if (x2 >= 0 && x2 < 256 && alpha != 0) {
color = charSpriteMem3[((y*256)+x)+((256*192)*zoomIn)];
color2 = charSpriteMem3_2[((y*256)+x)+((256*192)*zoomIn)];
if (blendAlpha > 0) {
color = alphablend(fg, charSpriteMem3[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
color2 = alphablend(fg, charSpriteMem3_2[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
}
if (charSpriteAlpha3[((y*256)+x)+((256*192)*zoomIn)] == 255) {
if (alpha == 255) {
bmpImageBuffer[0][(y*256)+x2] = color;
bmpImageBuffer2[0][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = color2;
} else {
bmpImageBuffer[0][(y*256)+x2] = alphablend(color, bmpImageBuffer[1][(y*256)+x2], charSpriteAlpha3[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[1][(y*256)+x2], charSpriteAlpha3[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer[0][(y*256)+x2] = alphablend(color, bmpImageBuffer[1][(y*256)+x2], (u8)alpha);
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[1][(y*256)+x2], (u8)alpha);
}
}
flipH[2] ? x2-- : x2++;
@ -1109,10 +1126,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
if (charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)] == 255) {
bmpImageBuffer[0][(y*256)+x2] = color;
bmpImageBuffer2[0][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = color2;
} else {
bmpImageBuffer[0][(y*256)+x2] = alphablend(color, bgLoc[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
}
}
flipH[0] ? x2-- : x2++;
@ -1120,7 +1137,7 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
// Character 2
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bmpImageBuffer[1], 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000); else while(dmaBusy(0));
for (int y = 0; y < 192; y++) {
x2 = flipH[1] ? 255 : 0;
x2 += (zoomIn==1 ? 64 : 26);
@ -1134,10 +1151,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
if (charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)] == 255) {
bmpImageBuffer[1][(y*256)+x2] = color;
bmpImageBuffer2[1][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[1][(y*256)+x2] = color2;
} else {
bmpImageBuffer[1][(y*256)+x2] = alphablend(color, bmpImageBuffer[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[1][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
if (dsiFeatures()) bmpImageBuffer2[1][(y*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y*256)+x2], charSpriteAlpha[1][((y*256)+x)+((256*192)*zoomIn)]);
}
}
flipH[1] ? x2-- : x2++;
@ -1157,10 +1174,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
}
if (charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)] == 255) {
bmpImageBuffer[0][(y*256)+x2] = color;
bmpImageBuffer2[0][(y*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = color2;
} else {
bmpImageBuffer[0][(y*256)+x2] = alphablend(color, bgLoc[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
if (dsiFeatures()) bmpImageBuffer2[0][(y*256)+x2] = alphablend(color2, bgLoc2[((y*256)+x2)+((256*192)*zoomIn)], charSpriteAlpha[0][((y*256)+x)+((256*192)*zoomIn)]);
}
}
flipH[0] ? x2-- : x2++;
@ -1171,25 +1188,26 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
// Continued from "if (chracterSpriteFound[2])"
// Character 4
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[0], bmpImageBuffer[1], 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bmpImageBuffer2[0], bmpImageBuffer2[1], 0x18000); else while(dmaBusy(0));
int y2 = 72;
for (int y = 0; y < 120; y++) {
x2 = flipH[3] ? 255 : 0;
x2 -= (zoomIn==1 ? 64 : 26);
for (int x = 0; x < 256; x++) {
if (x2 >= 0 && x2 < 256 && charSpriteAlpha4[((y*256)+x)+((256*192)*zoomIn)] != 0) {
alpha = mepFound ? charSpriteAlpha4_16[((y*256)+x)+((256*192)*zoomIn)] : charSpriteAlpha4[((y*256)+x)+((256*192)*zoomIn)];
if (x2 >= 0 && x2 < 256 && alpha != 0) {
color = charSpriteMem4[((y*256)+x)+((256*192)*zoomIn)];
color2 = charSpriteMem4_2[((y*256)+x)+((256*192)*zoomIn)];
if (blendAlpha > 0) {
color = alphablend(fg, charSpriteMem4[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
color2 = alphablend(fg, charSpriteMem4_2[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
}
if (charSpriteAlpha4[((y*256)+x)+((256*192)*zoomIn)] == 255) {
if (alpha == 255) {
bmpImageBuffer[1][(y2*256)+x2] = color;
bmpImageBuffer2[1][(y2*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[1][(y2*256)+x2] = color2;
} else {
bmpImageBuffer[1][(y2*256)+x2] = alphablend(color, bmpImageBuffer[0][(y2*256)+x2], charSpriteAlpha4[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[1][(y2*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y2*256)+x2], charSpriteAlpha4[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer[1][(y2*256)+x2] = alphablend(color, bmpImageBuffer[0][(y2*256)+x2], (u8)alpha);
if (dsiFeatures()) bmpImageBuffer2[1][(y2*256)+x2] = alphablend(color2, bmpImageBuffer2[0][(y2*256)+x2], (u8)alpha);
}
}
flipH[3] ? x2-- : x2++;
@ -1201,25 +1219,26 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
if (chracterSpriteFound[4]) {
// Character 5
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[1], bmpImageBuffer[0], 0x18000);
dmaCopyHalfWords(1, bmpImageBuffer2[1], bmpImageBuffer2[0], 0x18000);
if (dsiFeatures()) dmaCopyHalfWords(1, bmpImageBuffer2[1], bmpImageBuffer2[0], 0x18000); else while(dmaBusy(0));
int y2 = 72;
for (int y = 0; y < 120; y++) {
x2 = flipH[4] ? 255 : 0;
x2 += (zoomIn==1 ? 64 : 26);
for (int x = 0; x < 256; x++) {
if (x2 >= 0 && x2 < 256 && charSpriteAlpha5[((y*256)+x)+((256*192)*zoomIn)] != 0) {
alpha = mepFound ? charSpriteAlpha5_16[((y*256)+x)+((256*192)*zoomIn)] : charSpriteAlpha5[((y*256)+x)+((256*192)*zoomIn)];
if (x2 >= 0 && x2 < 256 && alpha != 0) {
color = charSpriteMem5[((y*256)+x)+((256*192)*zoomIn)];
color2 = charSpriteMem5_2[((y*256)+x)+((256*192)*zoomIn)];
if (blendAlpha > 0) {
color = alphablend(fg, charSpriteMem5[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
color2 = alphablend(fg, charSpriteMem5_2[((y*256)+x)+((256*192)*zoomIn)], blendAlpha);
}
if (charSpriteAlpha5[((y*256)+x)+((256*192)*zoomIn)] == 255) {
if (alpha == 255) {
bmpImageBuffer[0][(y2*256)+x2] = color;
bmpImageBuffer2[0][(y2*256)+x2] = color2;
if (dsiFeatures()) bmpImageBuffer2[0][(y2*256)+x2] = color2;
} else {
bmpImageBuffer[0][(y2*256)+x2] = alphablend(color, bmpImageBuffer[1][(y2*256)+x2], charSpriteAlpha5[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer2[0][(y2*256)+x2] = alphablend(color2, bmpImageBuffer2[1][(y2*256)+x2], charSpriteAlpha5[((y*256)+x)+((256*192)*zoomIn)]);
bmpImageBuffer[0][(y2*256)+x2] = alphablend(color, bmpImageBuffer[1][(y2*256)+x2], (u8)alpha);
if (dsiFeatures()) bmpImageBuffer2[0][(y2*256)+x2] = alphablend(color2, bmpImageBuffer2[1][(y2*256)+x2], (u8)alpha);
}
}
flipH[4] ? x2-- : x2++;
@ -1231,7 +1250,7 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
swiWaitForVBlank(); // Prevent screen tearing
dmaCopyHalfWordsAsynch(0, bmpImageBuffer[buffer], bgGetGfxPtr(bg2Main), 0x18000);
dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[buffer], bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) dmaCopyHalfWordsAsynch(1, bmpImageBuffer2[buffer], bgGetGfxPtr(bg3Main), 0x18000);
chracterSpriteLoaded = true;
}

View File

@ -27,6 +27,7 @@
#include "gui.hpp"
#include "screenCommon.hpp"
#include "fontHandler.h"
#include "myDSiMode.h"
#include "tonccpy.h"
#include "arrow_back.h"
@ -66,7 +67,7 @@ void SetBrightness(u8 screen, s8 bright) {
}
if (bright > 31)
bright = 31;
*(u16 *)(0x0400006C + (0x1000 * screen)) = bright + mode;
*(vu16 *)(0x0400006C + (0x1000 * screen)) = bright + mode;
}
// Clear Text.
@ -77,7 +78,7 @@ void Gui::DrawSprite(int imgindex, int x, int y) {
}
void Gui__ChangeBrightness() {
if (ditherlaceOnVBlank) {
if (dsiFeatures() && ditherlaceOnVBlank) {
secondFrame ? bgShow(bg3Main) : bgHide(bg3Main);
secondFrame = !secondFrame;
}
@ -88,8 +89,8 @@ void Gui__ChangeBrightness() {
// Initialize GUI.
void Gui::init(void) {
*(u16*)0x0400006C |= BIT(14);
*(u16*)0x0400006C &= BIT(15);
*(vu16*)0x0400006C |= BIT(14);
*(vu16*)0x0400006C &= BIT(15);
SetBrightness(0, 31);
SetBrightness(1, 31);

View File

@ -9,6 +9,7 @@
#include <string.h>
#include <unistd.h>
#include "myDSiMode.h"
#include "nitrofs.h"
#include "sound.h"
#include "photoStudio.hpp"
@ -16,6 +17,7 @@
#include "rocketRobz.hpp"
#include "screen.hpp"
bool mepFound = false;
bool fatInited = false;
bool isInit = true;
bool exiting = false;
@ -80,9 +82,6 @@ void doPause() {
}
int main(int argc, char **argv) {
extern void dsiOnly(void);
dsiOnly();
defaultExceptionHandler();
fatInited = fatInitDefault();
@ -100,6 +99,15 @@ int main(int argc, char **argv) {
stop();
}
if (!dsiFeatures()) {
sysSetCartOwner (BUS_OWNER_ARM9); // Allow arm9 to access GBA ROM (or in this case, the DS Memory Expansion Pak)
*(vu32*)(0x08240000) = 1;
mepFound = (*(vu32*)(0x08240000) == 1);
}
// Check for DS Debug RAM or DSi RAM
*(vu32*)(0x02403FFC) = 1;
*(vu32*)(0x02003FFC) = 0;
snd();
Gui::init();
@ -136,7 +144,7 @@ int main(int argc, char **argv) {
touchRead(&touch);
if (!ditherlaceOnVBlank) {
if (dsiFeatures() && !ditherlaceOnVBlank) {
secondFrame ? bgShow(bg3Main) : bgHide(bg3Main);
secondFrame = !secondFrame;
}

View File

@ -1,50 +0,0 @@
#include <nds.h>
#include "dsiOnly_top.h"
#include "dsiOnly_bot.h"
#include "tonccpy.h"
static void dsiOnly_setBrightness(u8 screen, s8 bright) {
u16 mode = 1 << 14;
if (bright < 0) {
mode = 2 << 14;
bright = -bright;
}
if (bright > 31) {
bright = 31;
}
*(u16*)(0x0400006C + (0x1000 * screen)) = bright + mode;
}
void dsiOnly(void) {
if (isDSiMode() || REG_SCFG_EXT != 0) return; // Proceed running on DSi
*(u16*)0x0400006C |= BIT(14);
*(u16*)0x0400006C &= BIT(15);
dsiOnly_setBrightness(0, 31);
dsiOnly_setBrightness(1, 31);
videoSetMode(MODE_4_2D);
videoSetModeSub(MODE_4_2D);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankD(VRAM_D_LCD);
// Display DSi Only screen
int bg3 = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
decompress(dsiOnly_topBitmap, bgGetGfxPtr(bg3), LZ77Vram);
tonccpy(BG_PALETTE, dsiOnly_topPal, dsiOnly_topPalLen);
int bg3sub = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
decompress(dsiOnly_botBitmap, bgGetGfxPtr(bg3sub), LZ77Vram);
tonccpy(BG_PALETTE_SUB, dsiOnly_botPal, dsiOnly_botPalLen);
dsiOnly_setBrightness(0, 0);
dsiOnly_setBrightness(1, 0);
while (1) {
swiWaitForVBlank();
}
}

View File

@ -1,5 +1,7 @@
#include <nds/dma.h>
#include "productIdent.hpp"
#include "lodepng.h"
#include "myDSiMode.h"
extern char verText[32];
@ -25,7 +27,7 @@ void ProductIdent::Draw(void) const {
void ProductIdent::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
if (!graphicLoaded) {
u16* bgLoc = (u16*)0x02F00000;
u16* bgLoc = new u16[256*192];
extern int bg2Main;
extern int bg3Main;
@ -36,7 +38,12 @@ void ProductIdent::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
bgLoc[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
dmaCopyHalfWordsAsynch(0, bgLoc, bgGetGfxPtr(bg2Main), 0x18000);
dmaCopyHalfWordsAsynch(1, bgLoc, bgGetGfxPtr(bg3Main), 0x18000);
if (dsiFeatures()) {
dmaCopyHalfWordsAsynch(1, bgLoc, bgGetGfxPtr(bg3Main), 0x18000);
} else {
while (dmaBusy(0));
free(bgLoc);
}
graphicLoaded = true;
}
}

View File

@ -6,6 +6,8 @@
#include "tonccpy.h"
#include <algorithm>
extern bool mepFound;
extern volatile s16 fade_counter;
extern volatile bool fade_out;
@ -29,7 +31,7 @@ extern char debug_buf[256];
extern volatile u32 sample_delay_count;
char* SFX_DATA = (char*)0x02FD0000;
char* SFX_DATA = (char*)NULL;
mm_word SOUNDBANK[MSL_BANKSIZE] = {0};
SoundControl::SoundControl()
@ -45,7 +47,8 @@ SoundControl::SoundControl()
soundbank_file = fopen("nitro:/soundbank.bin", "rb");
fread(SFX_DATA, 1, 0x20000, soundbank_file);
SFX_DATA = new char[0x13000];
fread(SFX_DATA, 1, 0x13000, soundbank_file);
fclose(soundbank_file);
@ -91,6 +94,10 @@ SoundControl::SoundControl()
};
if (*(vu32*)(0x02403FFC) != 1 && !mepFound) return;
init_streaming_buf();
stream_start_source = fopen("nitro:/music/start.raw", "rb");
stream_source = fopen("nitro:/music/loop.raw", "rb");
@ -149,6 +156,8 @@ mm_sfxhand SoundControl::playBack() { return mmEffectEx(&snd_back); }
mm_sfxhand SoundControl::playHighlight() { return mmEffectEx(&snd_highlight); }
void SoundControl::beginStream() {
if (!stream_source) return;
// open the stream
stream_is_playing = true;
mmStreamOpen(&stream);
@ -156,6 +165,8 @@ void SoundControl::beginStream() {
}
void SoundControl::stopStream() {
if (!stream_source) return;
stream_is_playing = false;
mmStreamClose();
}

View File

@ -1,16 +1,6 @@
#include "streamingaudio.h"
#include "tonccpy.h"
// Private members
// The main stream buffer that is streamed to maxmod
static volatile s16 streaming_buf_main[STREAMING_BUF_LENGTH] = {0};
/* The swap buffer, which is filled with bytes from the file
* before it is streamed to maxmod.
*/
static volatile s16 streaming_buf_swap[STREAMING_BUF_LENGTH] = {0};
/* Not a actual pointer, but the index to the current location of the
* buffers that are being streamed.
*/
@ -22,8 +12,8 @@ volatile s32 streaming_buf_ptr = 0;
volatile s32 filled_samples = 0;
// Pointers to the stream buffers.
volatile s16* play_stream_buf = streaming_buf_main;
volatile s16* fill_stream_buf = streaming_buf_swap;
volatile s16* play_stream_buf = NULL;
volatile s16* fill_stream_buf = NULL;
// Toggle this to true to trigger a fill as soon as possible.
@ -38,6 +28,11 @@ volatile u32 sample_delay_count = 0;
char debug_buf[256] = {0};
#endif
void init_streaming_buf(void) {
play_stream_buf = malloc(STREAMING_BUF_LENGTH*sizeof(s16));
fill_stream_buf = malloc(STREAMING_BUF_LENGTH*sizeof(s16));
}
/*
* The maxmod stream request handler.
*

View File

@ -1,12 +0,0 @@
-W3
#bitmap mode
-gb
# disable alpha and set opaque bit for all pixels
-gT!
# use lz77 compression
-gzl
# Set the bit depth to 8
-gB8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,12 +0,0 @@
-W3
#bitmap mode
-gb
# disable alpha and set opaque bit for all pixels
-gT!
# use lz77 compression
-gzl
# Set the bit depth to 8
-gB8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,460 @@
# -*- coding: utf8 -*-
# Patch an .nds (works with homebrew and ds demo only) to make it ready for make_cia
#
# 2016-02-28, Ahezard
#
# inspired by
# Apache Thunder .nds edited files and comments
# https://github.com/Relys/Project_CTR/blob/master/makerom/srl.h
# https://dsibrew.org/wiki/DSi_Cartridge_Header
# if the header size of the input nds file is 0x200 (homebrew)
# the header size of the output nds file will be patched to 0x4000 (normal ds/dsi header), 0x3E00 offset
from struct import *
from collections import namedtuple
from collections import OrderedDict
from pprint import pprint
import os, sys
import binascii
import argparse
parser = argparse.ArgumentParser(description='Patch an nds in order to be ready cia conversion via make_cia --srl=.')
parser.add_argument('file', metavar='file.nds', type=file, help='nds file to patch')
parser.add_argument('--verbose', help='verbose mode', action="store_true")
parser.add_argument('--out', help='output file [optionnal]')
parser.add_argument('--read', help='print only the header content, do not patch', action="store_true")
parser.add_argument('--extract', help='extract the content of the rom : header.bin,arm9.bin,arm7.bin,icon.bin,arm9i.bin,arm7i.bin, do not patch', action="store_true") #Not yet implemented
parser.add_argument('--title', help='Game title')
parser.add_argument('--code', help='Game code')
parser.add_argument('--maker', help='Maker code')
parser.add_argument('--mode', help='target mode, default mode is ds [ds|dsi|dsinogba|nitrohax]')
parser.add_argument('--arm9', type=file, help='swap the ds arm9 binary by the one provided')
parser.add_argument('--arm7', type=file, help='swap the ds arm7 binary by the one provided')
parser.add_argument('--arm9EntryAddress', help='arm9 ram address of the binary provided')
parser.add_argument('--arm7EntryAddress', help='arm7 ram address of the binary provided')
parser.add_argument('--arm9i', type=file, help='add a dsi arm9i binary to the file, not needed for homebrew so far')
parser.add_argument('--arm7i', type=file, help='add a dsi arm7i binary to the file, not needed for homebrew so far')
parser.add_argument('--accessControl', help='access control field')
parser.add_argument('--twlTouch', help='Toggle TWL Touch or not', action="store_true")
args = parser.parse_args()
if args.mode is None:
args.mode = "dsi"
#
# CRC16 MODULE
#
# includes CRC16 and CRC16 MODBUS
#
from ctypes import c_ushort
# from https://github.com/cristianav/PyCRC/blob/master/demo.py
class CRC16(object):
crc16_tab = []
# The CRC's are computed using polynomials. Here is the most used
# coefficient for CRC16
crc16_constant = 0xA001 # 40961
def __init__(self, modbus_flag=False):
# initialize the precalculated tables
if not len(self.crc16_tab):
self.init_crc16()
self.mdflag = bool(modbus_flag)
def calculate(self, input_data=None):
try:
is_string = isinstance(input_data, str)
is_bytes = isinstance(input_data, (bytes, bytearray))
if not is_string and not is_bytes:
raise Exception("Please provide a string or a byte sequence "
"as argument for calculation.")
crc_value = 0x0000 if not self.mdflag else 0xffff
for c in input_data:
d = ord(c) if is_string else c
tmp = crc_value ^ d
rotated = crc_value >> 8
crc_value = rotated ^ self.crc16_tab[(tmp & 0x00ff)]
return crc_value
except Exception as e:
print("EXCEPTION(calculate): {}".format(e))
def init_crc16(self):
"""The algorithm uses tables with precalculated values"""
for i in range(0, 256):
crc = c_ushort(i).value
for j in range(0, 8):
if crc & 0x0001:
crc = c_ushort(crc >> 1).value ^ self.crc16_constant
else:
crc = c_ushort(crc >> 1).value
self.crc16_tab.append(crc)
def getSize(fileobject):
current = fileobject.tell()
fileobject.seek(0,2) # move the cursor to the end of the file
size = fileobject.tell()
fileobject.seek(current,0)
return size
def skipUntilAddress(f_in,f_out, caddr, taddr):
chunk = f_in.read(taddr-caddr)
f_out.write(chunk)
def writeBlankuntilAddress(f_out, caddr, taddr):
f_out.write("\x00"*(taddr-caddr))
fname=args.file.name
args.file.close()
if not args.read:
print "Patching file : "+fname
else:
print "Reading header of file : "+fname
#offset of 0x4600 created
# File size compute
file = open(fname, 'rb')
fsize=getSize(file)
file.close()
#CRC header compute "CRC-16 (Modbus)"
file = open(fname, 'rb')
#0x15E from https://github.com/devkitPro/ndstool/ ... source/header.cpp
hdr = file.read(0x15E)
hdrCrc=CRC16(modbus_flag=True).calculate(hdr)
if args.verbose:
print("{:10s} {:20X}".format('HDR CRC-16 ModBus', hdrCrc))
#print "origin header cr c"+hdr[0x15E:0x15F]
#filew = open(fname+".hdr", "wb")
#filew.write(hdr);
#filew.close()
file.close()
if args.arm9 is not None:
arm9Fname=args.arm9.name
args.arm9.close()
arm9File = open(arm9Fname, 'rb')
arm9FileSize=getSize(arm9File)
dataArm9=arm9File.read(arm9FileSize)
arm9File.close()
if args.arm7 is not None:
arm7Fname=args.arm7.name
args.arm7.close()
arm7File = open(arm7Fname, 'rb')
arm7FileSize=getSize(arm7File)
dataArm7=arm7File.read(arm7FileSize)
arm7File.close()
filer = open(fname, 'rb')
data = filer.read(0x180)
caddr=0x180
#DS Data 180 bytes
SrlHeader = namedtuple('SrlHeader',
"gameTitle "
"gameCode "
"makerCode "
"unitCode "
"encryptionSeedSelect "
"deviceCapacity "
"reserved0 "
"dsiflags "
"romVersion "
"internalFlag "
"arm9RomOffset "
"arm9EntryAddress "
"arm9RamAddress "
"arm9Size "
"arm7RomOffset "
"arm7EntryAddress "
"arm7RamAddress "
"arm7Size "
"fntOffset "
"fntSize "
"fatOffset "
"fatSize "
"arm9OverlayOffset "
"arm9OverlaySize "
"arm7OverlayOffset "
"arm7OverlaySize "
"normalCardControlRegSettings "
"secureCardControlRegSettings "
"icon_bannerOffset "
"secureAreaCrc "
"secure_transfer_timeout "
"arm9Autoload "
"arm7Autoload "
"secureDisable "
"ntrRomSize "
"headerSize "
"reserved1 "
"nintendoLogo "
"nintendoLogoCrc "
"headerCrc "
"debugReserved ")
srlHeaderFormat='<12s4s2scbb7s2sbcIIIIIIIIIIIIIIIIIIIHHII8sII56s156s2sH32s'
srlHeader=SrlHeader._make(unpack_from(srlHeaderFormat, data))
if args.verbose:
print "origin header crc "+hex(srlHeader.headerCrc)
print "origin secure crc "+hex(srlHeader.secureAreaCrc)
#SecureArea CRC compute "CRC-16 (Modbus)"
file = open(fname, 'rb')
#0x15E from https://github.com/devkitPro/ndstool/ ... source/header.cpp
file.read(0x200)
sec = file.read(0x4000)
secCrc=CRC16(modbus_flag=True).calculate(sec)
if args.verbose:
print("{:10s} {:20X}".format('SEC CRC-16 ModBus', secCrc))
file.close()
if srlHeader.arm7EntryAddress>0x2400000 and not args.read and args.arm7 is None:
print "WARNING: .nds arm7EntryAddress greater than 0x2400000 will not boot as cia"
print "you need to recompile or swap the arm7 binary with a precompiled one with --arm7 and --arm7EntryAddress"
if "dsi" in args.mode :
srlHeaderPatched=srlHeader._replace(
dsiflags= '\x01\x00', #disable modcrypt but enable twl
unitCode= '\x02',
)
data1=pack(*[srlHeaderFormat]+srlHeaderPatched._asdict().values())
newHdrCrc=CRC16(modbus_flag=True).calculate(data1[0:0x15E])
srlHeaderPatched=srlHeaderPatched._replace(headerCrc=newHdrCrc)
if args.verbose:
print "new header crc "+hex(newHdrCrc)
if not args.read :
if args.verbose:
pprint(dict(srlHeaderPatched._asdict()))
else:
pprint(dict(srlHeader._asdict()))
data1=pack(*[srlHeaderFormat]+srlHeaderPatched._asdict().values())
arm9isize=0
arm7isize=0
#TWL Only Data 384 bytes
SrlTwlExtHeader = namedtuple('SrlTwlExtHeader',
"MBK_1_5_Settings "
"MBK_6_8_Settings_ARM9 "
"MBK_6_8_Settings_ARM7 "
"global_MBK_9_Setting "
"regionFlags "
"accessControl "
"arm7ScfgExtMask "
"reserved_flags "
"arm9iRomOffset "
"reserved2 "
"arm9iLoadAddress "
"arm9iSize "
"arm7iRomOffset "
"struct_param_baseAddress "
"arm7iLoadAddress "
"arm7iSize "
"digest_ntrRegionOffset "
"digest_ntrRegionSize "
"digest_twlRegionOffset "
"digest_twlRegionSize "
"digestSectorHashtableOffset "
"digestSectorHashtableSize "
"digest_blockHashtableOffset "
"digest_blockHashtableSize "
"digestSectorSize "
"digest_blockSectorcount "
"iconSize " #usually 0x23C0 or 2112 in homebrew
"unknown1 "
"twlRomSize "
"unknown2 "
"modcryptArea1Offset "
"modcryptArea1Size "
"modcryptArea2Offset "
"modcryptArea2Size "
"title_id "
"pubSaveDataSize "
"privSaveDataSize "
"reserved4 "
"parentalControl ")
srlTwlExtHeaderFormat="<20s12s12s4s4sIIII4sIIIIIIIIIIIIIIIII4sI12sIIII8sII176s16s"
if srlHeader.headerSize<0x300:
#homebrew
srlTwlExtHeader=SrlTwlExtHeader._make(unpack_from(srlTwlExtHeaderFormat, "\x00" * (0x300-0x180)))
else:
data = filer.read(0x300-0x180)
srlTwlExtHeader=SrlTwlExtHeader._make(unpack_from(srlTwlExtHeaderFormat, data))
caddr=0x300
#pprint(dict(srlTwlExtHeader._asdict()))
if not args.read:
# Fix srlTwlExtHeader
if "dsi" in args.mode:
arm7iRomOffset=srlHeaderPatched.arm7RomOffset
arm9iRomOffset=srlHeaderPatched.arm9RomOffset
arm7isize=srlHeaderPatched.arm7Size
arm9isize=srlHeaderPatched.arm9Size
totaldsisize=0
arm7iname = None
arm9iname = None
if args.arm9i is not None:
arm9iname = args.arm9i.name
arm9isize = getSize(args.arm9i)
arm9iRomOffset=srlHeaderPatched.ntrRomSize
if args.verbose:
print "arm9isize : "+hex(arm9isize)
print "arm9ioffset : "+hex(srlHeaderPatched.ntrRomSize)
args.arm9i.close()
totaldsisize=arm9isize
if args.arm7i is not None:
arm7iname = args.arm7i.name
arm7isize = getSize(args.arm7i)
arm7iRomOffset=srlHeaderPatched.ntrRomSize+arm9isize
if args.verbose:
print "arm7isize : "+hex(arm7isize)
print "arm9ioffset : "+hex(srlHeaderPatched.ntrRomSize+arm9isize)
args.arm7i.close()
totaldsisize=arm9isize+arm7isize
srlTwlExtHeader=srlTwlExtHeader._replace(
accessControl= 0x00000138,
arm7ScfgExtMask= 0x80040000,
reserved_flags= 0x00000000
)
if args.twlTouch:
srlTwlExtHeader=srlTwlExtHeader._replace(
reserved_flags= 0x01000000,
)
if args.accessControl is not None:
srlTwlExtHeader=srlTwlExtHeader._replace(
accessControl= int(args.accessControl,0),
)
if args.verbose or args.read:
pprint(dict(srlTwlExtHeader._asdict()))
data2=pack(*[srlTwlExtHeaderFormat]+srlTwlExtHeader._asdict().values())
#TWL and Signed NTR 3328 bytes
SrlSignedHeader = namedtuple('SrlSignedHeader',
"arm9WithSecAreaSha1Hmac "
"arm7Sha1Hmac "
"digestMasterSha1Hmac "
"bannerSha1Hmac "
"arm9iSha1Hmac "
"arm7iSha1Hmac "
"reserved5 "
"arm9Sha1Hmac "
"reserved6 "
"reserved7 "
"signature "
)
srlSignedHeaderFormat="<20s20s20s20s20s20s40s20s2636s384s128s"
if srlHeader.headerSize<0x1100:
#homebrew
srlSignedHeader=SrlSignedHeader._make(unpack_from(srlSignedHeaderFormat, "\x00" * (3328)))
else:
data = filer.read(3328)
srlSignedHeader=SrlSignedHeader._make(unpack_from(srlSignedHeaderFormat, data))
caddr=0x300+3328
filer.read(0x4000-caddr)
caddr=0x4000
#pprint(dict(srlSignedHeader._asdict()))
# Fix srlSignedHeader
if not args.read:
srlSignedHeader=srlSignedHeader._replace(
arm7Sha1Hmac= '\xff'*20,
arm9WithSecAreaSha1Hmac= '\xff'*20,
bannerSha1Hmac= '\xff'*20,
signature= '\xff'*128
)
if "dsi" in args.mode :
srlSignedHeader=srlSignedHeader._replace(
arm7Sha1Hmac= '\xff'*20,
arm7iSha1Hmac= '\xff'*20,
arm9Sha1Hmac= '\xff'*20,
arm9WithSecAreaSha1Hmac= '\xff'*20,
arm9iSha1Hmac= '\xff'*20,
bannerSha1Hmac= '\xff'*20,
digestMasterSha1Hmac= '\xff'*20,
signature= '\xff'*128
)
if args.verbose or args.read:
pprint(dict(srlSignedHeader._asdict()))
data3=pack(*[srlSignedHeaderFormat]+srlSignedHeader._asdict().values())
# ARM9 footer
# from https://github.com/devkitPro/ndstool/ ... source/header.cpp
# ARM9 footer size = 3*4
ARM9Footer = namedtuple('ARM9Footer',
"nitrocode " #0xDEC00621
"versionInfo "
"reserved "
)
ARM9FooterFormat="<III"
file = open(fname, 'rb')
arm9FooterAddr=srlHeader.arm9RomOffset + srlHeader.arm9Size
file.read(arm9FooterAddr)
data=file.read(12)
arm9Footer=ARM9Footer._make(unpack_from(ARM9FooterFormat, data))
if args.verbose:
print "footer addr "+hex(arm9FooterAddr)
if arm9Footer.nitrocode == 0xDEC00621:
if args.verbose or args.read:
print "ARM9 footer found."
print "no patch needed"
print "nitrocode "+hex(arm9Footer.nitrocode)
print "versionInfo "+hex(arm9Footer.versionInfo)
print "reserved "+hex(arm9Footer.reserved)
print "\n"
else:
if args.verbose or args.read:
print "ARM9 footer not found.\n"
arm9FooterPatched=arm9Footer._replace(
nitrocode= 0xDEC00621,
versionInfo= 0xad8,
reserved= 0
)
data4=pack(*[ARM9FooterFormat]+arm9FooterPatched._asdict().values())
file.close()
if not args.read:
# write the file
if args.out is not None:
filew = open(args.out, "wb")
else:
filew = open(fname+".tmp", "wb")
filew.write(data1)
filew.write(data2)
filew.write(data3[0:0xC80])
filew.write('\xff'*16*8)
writeBlankuntilAddress(filew,0x1000,0x4000)
skipUntilAddress(filer,filew,caddr,srlTwlExtHeader.twlRomSize)
filew.close()
filer.close()
if args.out is None:
if os.path.exists(fname+".orig.nds"):
os.remove(fname+".orig.nds")
os.rename(fname,fname+".orig.nds")
os.rename(fname+".tmp",fname)
print "file patched"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

View File

@ -51,8 +51,10 @@ void gspWaitForVBlank(void) {
static bool redrawText = true;
extern bool ditherlaceOnVBlank;
#endif
int characterLimit = 1;
#else
int characterLimit = 4;
#endif
static u8 bgPageOrder[] = {
4, // Logos

View File

@ -2,6 +2,7 @@
#include "screenvars.h"
#ifdef NDS
#include "lodepng.h"
#include "myDSiMode.h"
#endif
static int subMode = 0;
@ -133,6 +134,7 @@ void RocketRobz::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
}
}
bgGetGfxPtr(bg2Main)[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (dsiFeatures()) {
if (alternatePixel) {
if (image[(i*4)+3] & BIT(0)) {
image[(i*4)] += 0x4;
@ -155,6 +157,7 @@ void RocketRobz::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
}
}
bgGetGfxPtr(bg3Main)[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
}
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}