mirror of https://github.com/mgba-emu/mgba.git
3DS: Update to new API
This commit is contained in:
parent
631b287b3a
commit
e65d12d35e
|
@ -213,8 +213,9 @@ void GBAConfigDirectory(char* out, size_t outLength) {
|
||||||
snprintf(out, outLength, "/%s", projectName);
|
snprintf(out, outLength, "/%s", projectName);
|
||||||
mkdir(out, 0777);
|
mkdir(out, 0777);
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
|
UNUSED(portable);
|
||||||
snprintf(out, outLength, "/%s", projectName);
|
snprintf(out, outLength, "/%s", projectName);
|
||||||
FSUSER_CreateDirectory(0, sdmcArchive, FS_makePath(PATH_CHAR, out));
|
FSUSER_CreateDirectory(sdmcArchive, fsMakePath(PATH_ASCII, out), 0);
|
||||||
#else
|
#else
|
||||||
getcwd(out, outLength);
|
getcwd(out, outLength);
|
||||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct VFile3DS {
|
||||||
|
|
||||||
struct VDirEntry3DS {
|
struct VDirEntry3DS {
|
||||||
struct VDirEntry d;
|
struct VDirEntry d;
|
||||||
FS_dirent ent;
|
FS_DirectoryEntry ent;
|
||||||
char utf8Name[256];
|
char utf8Name[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,14 +49,15 @@ static struct VDir* _vd3dOpenDir(struct VDir* vd, const char* path);
|
||||||
static const char* _vd3deName(struct VDirEntry* vde);
|
static const char* _vd3deName(struct VDirEntry* vde);
|
||||||
static enum VFSType _vd3deType(struct VDirEntry* vde);
|
static enum VFSType _vd3deType(struct VDirEntry* vde);
|
||||||
|
|
||||||
struct VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags) {
|
struct VFile* VFileOpen3DS(FS_Archive* archive, const char* path, int flags) {
|
||||||
struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS));
|
struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS));
|
||||||
if (!vf3d) {
|
if (!vf3d) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FS_path newPath = FS_makePath(PATH_CHAR, path);
|
// TODO: Use UTF-16
|
||||||
Result res = FSUSER_OpenFile(0, &vf3d->handle, *archive, newPath, flags, FS_ATTRIBUTE_NONE);
|
FS_Path newPath = fsMakePath(PATH_ASCII, path);
|
||||||
|
Result res = FSUSER_OpenFile(&vf3d->handle, *archive, newPath, flags, 0);
|
||||||
if (res & 0xFFFC03FF) {
|
if (res & 0xFFFC03FF) {
|
||||||
free(vf3d);
|
free(vf3d);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -175,8 +176,9 @@ struct VDir* VDirOpen(const char* path) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FS_path newPath = FS_makePath(PATH_CHAR, path);
|
// TODO: Use UTF-16
|
||||||
Result res = FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath);
|
FS_Path newPath = fsMakePath(PATH_ASCII, path);
|
||||||
|
Result res = FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath);
|
||||||
if (res & 0xFFFC03FF) {
|
if (res & 0xFFFC03FF) {
|
||||||
free(vd3d);
|
free(vd3d);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -207,8 +209,9 @@ static bool _vd3dClose(struct VDir* vd) {
|
||||||
static void _vd3dRewind(struct VDir* vd) {
|
static void _vd3dRewind(struct VDir* vd) {
|
||||||
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
||||||
FSDIR_Close(vd3d->handle);
|
FSDIR_Close(vd3d->handle);
|
||||||
FS_path newPath = FS_makePath(PATH_CHAR, vd3d->path);
|
// TODO: Use UTF-16
|
||||||
FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath);
|
FS_Path newPath = fsMakePath(PATH_ASCII, vd3d->path);
|
||||||
|
FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct VDirEntry* _vd3dListNext(struct VDir* vd) {
|
static struct VDirEntry* _vd3dListNext(struct VDir* vd) {
|
||||||
|
@ -264,7 +267,7 @@ static const char* _vd3deName(struct VDirEntry* vde) {
|
||||||
|
|
||||||
static enum VFSType _vd3deType(struct VDirEntry* vde) {
|
static enum VFSType _vd3deType(struct VDirEntry* vde) {
|
||||||
struct VDirEntry3DS* vd3de = (struct VDirEntry3DS*) vde;
|
struct VDirEntry3DS* vd3de = (struct VDirEntry3DS*) vde;
|
||||||
if (vd3de->ent.isDirectory) {
|
if (vd3de->ent.attributes & FS_ATTRIBUTE_DIRECTORY) {
|
||||||
return VFS_DIRECTORY;
|
return VFS_DIRECTORY;
|
||||||
}
|
}
|
||||||
return VFS_FILE;
|
return VFS_FILE;
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
extern FS_archive sdmcArchive;
|
extern FS_Archive sdmcArchive;
|
||||||
|
|
||||||
struct VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags);
|
struct VFile* VFileOpen3DS(FS_Archive* archive, const char* path, int flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <3ds/gpu/gpu.h>
|
||||||
|
#include <3ds/gpu/gx.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -42,57 +44,12 @@ static int pendingEvents = 0;
|
||||||
|
|
||||||
static const struct ctrTexture* activeTexture = NULL;
|
static const struct ctrTexture* activeTexture = NULL;
|
||||||
|
|
||||||
static u32 _f24FromFloat(float f) {
|
|
||||||
u32 i;
|
|
||||||
memcpy(&i, &f, 4);
|
|
||||||
|
|
||||||
u32 mantissa = (i << 9) >> 9;
|
|
||||||
s32 exponent = (i << 1) >> 24;
|
|
||||||
u32 sign = (i << 0) >> 31;
|
|
||||||
|
|
||||||
// Truncate mantissa
|
|
||||||
mantissa >>= 7;
|
|
||||||
|
|
||||||
// Re-bias exponent
|
|
||||||
exponent = exponent - 127 + 63;
|
|
||||||
if (exponent < 0) {
|
|
||||||
// Underflow: flush to zero
|
|
||||||
return sign << 23;
|
|
||||||
} else if (exponent > 0x7F) {
|
|
||||||
// Overflow: saturate to infinity
|
|
||||||
return sign << 23 | 0x7F << 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign << 23 | exponent << 16 | mantissa;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 _f31FromFloat(float f) {
|
|
||||||
u32 i;
|
|
||||||
memcpy(&i, &f, 4);
|
|
||||||
|
|
||||||
u32 mantissa = (i << 9) >> 9;
|
|
||||||
s32 exponent = (i << 1) >> 24;
|
|
||||||
u32 sign = (i << 0) >> 31;
|
|
||||||
|
|
||||||
// Re-bias exponent
|
|
||||||
exponent = exponent - 127 + 63;
|
|
||||||
if (exponent < 0) {
|
|
||||||
// Underflow: flush to zero
|
|
||||||
return sign << 30;
|
|
||||||
} else if (exponent > 0x7F) {
|
|
||||||
// Overflow: saturate to infinity
|
|
||||||
return sign << 30 | 0x7F << 23;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign << 30 | exponent << 23 | mantissa;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ctrClearPending(int events) {
|
void ctrClearPending(int events) {
|
||||||
int toClear = events & pendingEvents;
|
int toClear = events & pendingEvents;
|
||||||
if (toClear & (1 << GSPEVENT_PSC0)) {
|
if (toClear & (1 << GSPGPU_EVENT_PSC0)) {
|
||||||
gspWaitForPSC0();
|
gspWaitForPSC0();
|
||||||
}
|
}
|
||||||
if (toClear & (1 << GSPEVENT_PPF)) {
|
if (toClear & (1 << GSPGPU_EVENT_PPF)) {
|
||||||
gspWaitForPPF();
|
gspWaitForPPF();
|
||||||
}
|
}
|
||||||
pendingEvents ^= toClear;
|
pendingEvents ^= toClear;
|
||||||
|
@ -103,39 +60,39 @@ static void _GPU_SetFramebuffer(intptr_t colorBuffer, intptr_t depthBuffer, u16
|
||||||
u32 buf[4];
|
u32 buf[4];
|
||||||
|
|
||||||
// Unknown
|
// Unknown
|
||||||
GPUCMD_AddWrite(GPUREG_0111, 0x00000001);
|
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001);
|
||||||
GPUCMD_AddWrite(GPUREG_0110, 0x00000001);
|
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001);
|
||||||
|
|
||||||
// Set depth/color buffer address and dimensions
|
// Set depth/color buffer address and dimensions
|
||||||
buf[0] = depthBuffer >> 3;
|
buf[0] = depthBuffer >> 3;
|
||||||
buf[1] = colorBuffer >> 3;
|
buf[1] = colorBuffer >> 3;
|
||||||
buf[2] = (0x01) << 24 | ((h-1) & 0xFFF) << 12 | (w & 0xFFF) << 0;
|
buf[2] = (0x01) << 24 | ((h-1) & 0xFFF) << 12 | (w & 0xFFF) << 0;
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, buf, 3);
|
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, buf, 3);
|
||||||
GPUCMD_AddWrite(GPUREG_006E, buf[2]);
|
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, buf[2]);
|
||||||
|
|
||||||
// Set depth/color buffer pixel format
|
// Set depth/color buffer pixel format
|
||||||
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 3 /* D248S */ );
|
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 3 /* D248S */ );
|
||||||
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0 /* RGBA8 */ << 16 | 2 /* Unknown */);
|
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0 /* RGBA8 */ << 16 | 2 /* Unknown */);
|
||||||
GPUCMD_AddWrite(GPUREG_011B, 0); // Unknown
|
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0); // Unknown
|
||||||
|
|
||||||
// Enable color/depth buffers
|
// Enable color/depth buffers
|
||||||
buf[0] = colorBuffer != 0 ? 0xF : 0x0;
|
buf[0] = colorBuffer != 0 ? 0xF : 0x0;
|
||||||
buf[1] = buf[0];
|
buf[1] = buf[0];
|
||||||
buf[2] = depthBuffer != 0 ? 0x2 : 0x0;
|
buf[2] = depthBuffer != 0 ? 0x2 : 0x0;
|
||||||
buf[3] = buf[2];
|
buf[3] = buf[2];
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_0112, buf, 4);
|
GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, buf, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GPU_SetViewportEx(u16 x, u16 y, u16 w, u16 h) {
|
static void _GPU_SetViewportEx(u16 x, u16 y, u16 w, u16 h) {
|
||||||
u32 buf[4];
|
u32 buf[4];
|
||||||
|
|
||||||
buf[0] = _f24FromFloat(w / 2.0f);
|
buf[0] = f32tof24(w / 2.0f);
|
||||||
buf[1] = _f31FromFloat(2.0f / w) << 1;
|
buf[1] = f32tof31(2.0f / w) << 1;
|
||||||
buf[2] = _f24FromFloat(h / 2.0f);
|
buf[2] = f32tof24(h / 2.0f);
|
||||||
buf[3] = _f31FromFloat(2.0f / h) << 1;
|
buf[3] = f32tof31(2.0f / h) << 1;
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_0041, buf, 4);
|
GPUCMD_AddIncrementalWrites(GPUREG_VIEWPORT_WIDTH, buf, 4);
|
||||||
|
|
||||||
GPUCMD_AddWrite(GPUREG_0068, (y & 0xFFFF) << 16 | (x & 0xFFFF) << 0);
|
GPUCMD_AddWrite(GPUREG_VIEWPORT_XY, (y & 0xFFFF) << 16 | (x & 0xFFFF) << 0);
|
||||||
|
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
|
@ -259,7 +216,7 @@ void ctrGpuBeginFrame(int screen) {
|
||||||
fw = 320;
|
fw = 320;
|
||||||
}
|
}
|
||||||
|
|
||||||
_GPU_SetFramebuffer(osConvertVirtToPhys((u32)gpuColorBuffer[screen]), 0, 240, fw);
|
_GPU_SetFramebuffer(osConvertVirtToPhys(gpuColorBuffer[screen]), 0, 240, fw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctrGpuBeginDrawing(void) {
|
void ctrGpuBeginDrawing(void) {
|
||||||
|
@ -282,8 +239,8 @@ void ctrGpuBeginDrawing(void) {
|
||||||
GPU_SetAlphaTest(false, GPU_ALWAYS, 0);
|
GPU_SetAlphaTest(false, GPU_ALWAYS, 0);
|
||||||
|
|
||||||
// Unknown
|
// Unknown
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
|
GPUCMD_AddMaskedWrite(GPUREG_EARLYDEPTH_TEST1, 0x1, 0);
|
||||||
GPUCMD_AddWrite(GPUREG_0118, 0);
|
GPUCMD_AddWrite(GPUREG_EARLYDEPTH_TEST2, 0);
|
||||||
|
|
||||||
GPU_SetTexEnv(0,
|
GPU_SetTexEnv(0,
|
||||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0), // RGB
|
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0), // RGB
|
||||||
|
@ -299,7 +256,7 @@ void ctrGpuBeginDrawing(void) {
|
||||||
_setDummyTexEnv(5);
|
_setDummyTexEnv(5);
|
||||||
|
|
||||||
// Configure vertex attribute format
|
// Configure vertex attribute format
|
||||||
u32 bufferOffsets[] = { osConvertVirtToPhys((u32)ctrVertexBuffer) - VRAM_BASE };
|
u32 bufferOffsets[] = { osConvertVirtToPhys(ctrVertexBuffer) - VRAM_BASE };
|
||||||
u64 arrayTargetAttributes[] = { 0x210 };
|
u64 arrayTargetAttributes[] = { 0x210 };
|
||||||
u8 numAttributesInArray[] = { 3 };
|
u8 numAttributesInArray[] = { 3 };
|
||||||
GPU_SetAttributeBuffers(
|
GPU_SetAttributeBuffers(
|
||||||
|
@ -332,29 +289,29 @@ void ctrGpuEndFrame(int screen, void* outputFramebuffer, int w, int h) {
|
||||||
|
|
||||||
const u32 GX_CROP_INPUT_LINES = (1 << 2);
|
const u32 GX_CROP_INPUT_LINES = (1 << 2);
|
||||||
|
|
||||||
ctrClearPending(1 << GSPEVENT_PSC0);
|
ctrClearPending(1 << GSPGPU_EVENT_PSC0);
|
||||||
ctrClearPending(1 << GSPEVENT_PPF);
|
ctrClearPending(1 << GSPGPU_EVENT_PPF);
|
||||||
|
|
||||||
GX_SetDisplayTransfer(NULL,
|
GX_DisplayTransfer(
|
||||||
colorBuffer, GX_BUFFER_DIM(240, fw),
|
colorBuffer, GX_BUFFER_DIM(240, fw),
|
||||||
outputFramebuffer, GX_BUFFER_DIM(h, w),
|
outputFramebuffer, GX_BUFFER_DIM(h, w),
|
||||||
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) |
|
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) |
|
||||||
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
||||||
GX_CROP_INPUT_LINES);
|
GX_CROP_INPUT_LINES);
|
||||||
pendingEvents |= (1 << GSPEVENT_PPF);
|
pendingEvents |= (1 << GSPGPU_EVENT_PPF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctrGpuEndDrawing(void) {
|
void ctrGpuEndDrawing(void) {
|
||||||
ctrClearPending(1 << GSPEVENT_PPF);
|
ctrClearPending(1 << GSPGPU_EVENT_PPF);
|
||||||
gfxSwapBuffersGpu();
|
gfxSwapBuffersGpu();
|
||||||
gspWaitForEvent(GSPEVENT_VBlank0, false);
|
gspWaitForEvent(GSPGPU_EVENT_VBlank0, false);
|
||||||
|
|
||||||
void* gpuColorBuffer0End = (char*)gpuColorBuffer[0] + 240 * 400 * 4;
|
void* gpuColorBuffer0End = (char*)gpuColorBuffer[0] + 240 * 400 * 4;
|
||||||
void* gpuColorBuffer1End = (char*)gpuColorBuffer[1] + 240 * 320 * 4;
|
void* gpuColorBuffer1End = (char*)gpuColorBuffer[1] + 240 * 320 * 4;
|
||||||
GX_SetMemoryFill(NULL,
|
GX_MemoryFill(
|
||||||
gpuColorBuffer[0], 0x00000000, gpuColorBuffer0End, GX_FILL_32BIT_DEPTH | GX_FILL_TRIGGER,
|
gpuColorBuffer[0], 0x00000000, gpuColorBuffer0End, GX_FILL_32BIT_DEPTH | GX_FILL_TRIGGER,
|
||||||
gpuColorBuffer[1], 0x00000000, gpuColorBuffer1End, GX_FILL_32BIT_DEPTH | GX_FILL_TRIGGER);
|
gpuColorBuffer[1], 0x00000000, gpuColorBuffer1End, GX_FILL_32BIT_DEPTH | GX_FILL_TRIGGER);
|
||||||
pendingEvents |= 1 << GSPEVENT_PSC0;
|
pendingEvents |= 1 << GSPGPU_EVENT_PSC0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctrSetViewportSize(s16 w, s16 h) {
|
void ctrSetViewportSize(s16 w, s16 h) {
|
||||||
|
@ -382,7 +339,7 @@ void ctrActivateTexture(const struct ctrTexture* texture) {
|
||||||
|
|
||||||
GPU_SetTextureEnable(GPU_TEXUNIT0);
|
GPU_SetTextureEnable(GPU_TEXUNIT0);
|
||||||
GPU_SetTexture(
|
GPU_SetTexture(
|
||||||
GPU_TEXUNIT0, (u32*)osConvertVirtToPhys((u32)texture->data),
|
GPU_TEXUNIT0, (u32*)osConvertVirtToPhys(texture->data),
|
||||||
texture->width, texture->height,
|
texture->width, texture->height,
|
||||||
GPU_TEXTURE_MAG_FILTER(texture->filter) | GPU_TEXTURE_MIN_FILTER(texture->filter) |
|
GPU_TEXTURE_MAG_FILTER(texture->filter) | GPU_TEXTURE_MIN_FILTER(texture->filter) |
|
||||||
GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_BORDER) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_BORDER),
|
GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_BORDER) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_BORDER),
|
||||||
|
@ -444,15 +401,15 @@ void ctrFlushBatch(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrClearPending((1 << GSPEVENT_PSC0));
|
ctrClearPending((1 << GSPGPU_EVENT_PSC0));
|
||||||
|
|
||||||
GSPGPU_FlushDataCache(NULL, (u8*)ctrVertexBuffer, VERTEX_INDEX_BUFFER_SIZE);
|
GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_INDEX_BUFFER_SIZE);
|
||||||
GPU_DrawElements(GPU_UNKPRIM, (u32*)(osConvertVirtToPhys((u32)ctrIndexBuffer) - VRAM_BASE), ctrNumQuads * 6);
|
GPU_DrawElements(GPU_GEOMETRY_PRIM, (u32*)(osConvertVirtToPhys(ctrIndexBuffer) - VRAM_BASE), ctrNumQuads * 6);
|
||||||
|
|
||||||
GPU_FinishDrawing();
|
GPU_FinishDrawing();
|
||||||
GPUCMD_Finalize();
|
GPUCMD_Finalize();
|
||||||
GSPGPU_FlushDataCache(NULL, (u8*)gpuCommandList, COMMAND_LIST_LENGTH * sizeof(u32));
|
GSPGPU_FlushDataCache((u8*)gpuCommandList, COMMAND_LIST_LENGTH * sizeof(u32));
|
||||||
GPUCMD_FlushAndRun(NULL);
|
GPUCMD_FlushAndRun();
|
||||||
|
|
||||||
gspWaitForP3D();
|
gspWaitForP3D();
|
||||||
|
|
||||||
|
|
|
@ -26,18 +26,23 @@
|
||||||
|
|
||||||
extern char* fake_heap_start;
|
extern char* fake_heap_start;
|
||||||
extern char* fake_heap_end;
|
extern char* fake_heap_end;
|
||||||
u32 __linear_heap;
|
extern u32 __ctru_linear_heap;
|
||||||
u32 __heapBase;
|
extern u32 __ctru_heap;
|
||||||
static u32 __heap_size = 0x02400000;
|
extern u32 __ctru_heap_size;
|
||||||
static u32 __linear_heap_size = 0x01400000;
|
extern u32 __ctru_linear_heap_size;
|
||||||
|
static u32 __custom_heap_size = 0x02400000;
|
||||||
|
static u32 __custom_linear_heap_size = 0x01400000;
|
||||||
|
|
||||||
extern void (*__system_retAddr)(void);
|
extern void (*__system_retAddr)(void);
|
||||||
|
|
||||||
void __destroy_handle_list(void);
|
void envDestroyHandles(void);
|
||||||
|
|
||||||
void __appExit();
|
void __appExit();
|
||||||
|
|
||||||
void __libc_fini_array(void);
|
void __libc_fini_array(void);
|
||||||
|
|
||||||
|
Result __sync_fini(void) __attribute__((weak));
|
||||||
|
|
||||||
uint32_t* romBuffer;
|
uint32_t* romBuffer;
|
||||||
size_t romBufferSize;
|
size_t romBufferSize;
|
||||||
|
|
||||||
|
@ -58,36 +63,16 @@ bool allocateRomBuffer(void) {
|
||||||
void __system_allocateHeaps() {
|
void __system_allocateHeaps() {
|
||||||
u32 tmp=0;
|
u32 tmp=0;
|
||||||
|
|
||||||
|
__ctru_heap_size = __custom_heap_size;
|
||||||
|
__ctru_linear_heap_size = __custom_linear_heap_size;
|
||||||
|
|
||||||
// Allocate the application heap
|
// Allocate the application heap
|
||||||
__heapBase = 0x08000000;
|
__ctru_heap = 0x08000000;
|
||||||
svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
|
svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
|
||||||
|
|
||||||
// Allocate the linear heap
|
// Allocate the linear heap
|
||||||
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||||
// Set up newlib heap
|
// Set up newlib heap
|
||||||
fake_heap_start = (char*)__heapBase;
|
fake_heap_start = (char*)__ctru_heap;
|
||||||
fake_heap_end = fake_heap_start + __heap_size;
|
fake_heap_end = fake_heap_start + __ctru_heap_size;
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((noreturn)) __libctru_exit(int rc)
|
|
||||||
{
|
|
||||||
UNUSED(rc);
|
|
||||||
|
|
||||||
u32 tmp=0;
|
|
||||||
|
|
||||||
// Unmap the linear heap
|
|
||||||
svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
|
|
||||||
|
|
||||||
// Unmap the application heap
|
|
||||||
svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
|
|
||||||
|
|
||||||
// Close some handles
|
|
||||||
__destroy_handle_list();
|
|
||||||
|
|
||||||
// Jump to the loader if it provided a callback
|
|
||||||
if (__system_retAddr)
|
|
||||||
__system_retAddr();
|
|
||||||
|
|
||||||
// Since above did not jump, end this process
|
|
||||||
svcExitProcess();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ struct GUIFont* GUIFontCreate(void) {
|
||||||
tex->width = 256;
|
tex->width = 256;
|
||||||
tex->height = 128;
|
tex->height = 128;
|
||||||
|
|
||||||
GSPGPU_FlushDataCache(NULL, (u8*)font, font_size);
|
GSPGPU_FlushDataCache(font, font_size);
|
||||||
GX_RequestDma(NULL, (u32*)font, tex->data, font_size);
|
GX_RequestDma((u32*) font, tex->data, font_size);
|
||||||
gspWaitForDMA();
|
gspWaitForDMA();
|
||||||
|
|
||||||
return guiFont;
|
return guiFont;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "ctr-gpu.h"
|
#include "ctr-gpu.h"
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <3ds/gpu/gx.h>
|
||||||
|
|
||||||
static enum ScreenMode {
|
static enum ScreenMode {
|
||||||
SM_PA_BOTTOM,
|
SM_PA_BOTTOM,
|
||||||
|
@ -32,7 +33,7 @@ static enum ScreenMode {
|
||||||
#define AUDIO_SAMPLES 0x80
|
#define AUDIO_SAMPLES 0x80
|
||||||
#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 24)
|
#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 24)
|
||||||
|
|
||||||
FS_archive sdmcArchive;
|
FS_Archive sdmcArchive;
|
||||||
|
|
||||||
static struct GBA3DSRotationSource {
|
static struct GBA3DSRotationSource {
|
||||||
struct GBARotationSource d;
|
struct GBARotationSource d;
|
||||||
|
@ -76,8 +77,8 @@ static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, voi
|
||||||
flags |= SOUND_ONE_SHOT;
|
flags |= SOUND_ONE_SHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pleft = osConvertVirtToPhys((u32) left);
|
pleft = osConvertVirtToPhys(left);
|
||||||
pright = osConvertVirtToPhys((u32) right);
|
pright = osConvertVirtToPhys(right);
|
||||||
|
|
||||||
u32 timer = CSND_TIMER(sampleRate);
|
u32 timer = CSND_TIMER(sampleRate);
|
||||||
if (timer < 0x0042) {
|
if (timer < 0x0042) {
|
||||||
|
@ -149,8 +150,8 @@ static void _drawEnd(void) {
|
||||||
static int _batteryState(void) {
|
static int _batteryState(void) {
|
||||||
u8 charge;
|
u8 charge;
|
||||||
u8 adapter;
|
u8 adapter;
|
||||||
PTMU_GetBatteryLevel(0, &charge);
|
PTMU_GetBatteryLevel(&charge);
|
||||||
PTMU_GetBatteryChargeState(0, &adapter);
|
PTMU_GetBatteryChargeState(&adapter);
|
||||||
int state = 0;
|
int state = 0;
|
||||||
if (adapter) {
|
if (adapter) {
|
||||||
state |= BATTERY_CHARGING;
|
state |= BATTERY_CHARGING;
|
||||||
|
@ -284,8 +285,8 @@ static void _drawFrame(struct GBAGUIRunner* runner, bool faded) {
|
||||||
void* outputBuffer = renderer.outputBuffer;
|
void* outputBuffer = renderer.outputBuffer;
|
||||||
struct ctrTexture* tex = &gbaOutputTexture;
|
struct ctrTexture* tex = &gbaOutputTexture;
|
||||||
|
|
||||||
GSPGPU_FlushDataCache(NULL, outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
GSPGPU_FlushDataCache(outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||||
GX_SetDisplayTransfer(NULL,
|
GX_DisplayTransfer(
|
||||||
outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS),
|
outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS),
|
||||||
tex->data, GX_BUFFER_DIM(256, 256),
|
tex->data, GX_BUFFER_DIM(256, 256),
|
||||||
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
||||||
|
@ -324,9 +325,9 @@ static void _drawScreenshot(struct GBAGUIRunner* runner, const uint32_t* pixels,
|
||||||
memset(&newPixels[y * 256 + VIDEO_HORIZONTAL_PIXELS], 0, (256 - VIDEO_HORIZONTAL_PIXELS) * sizeof(u32));
|
memset(&newPixels[y * 256 + VIDEO_HORIZONTAL_PIXELS], 0, (256 - VIDEO_HORIZONTAL_PIXELS) * sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
GSPGPU_FlushDataCache(NULL, (void*)newPixels, 256 * VIDEO_VERTICAL_PIXELS * sizeof(u32));
|
GSPGPU_FlushDataCache(newPixels, 256 * VIDEO_VERTICAL_PIXELS * sizeof(u32));
|
||||||
GX_SetDisplayTransfer(NULL,
|
GX_DisplayTransfer(
|
||||||
(void*)newPixels, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS),
|
(u32*) newPixels, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS),
|
||||||
tex->data, GX_BUFFER_DIM(256, 256),
|
tex->data, GX_BUFFER_DIM(256, 256),
|
||||||
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
||||||
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) |
|
||||||
|
@ -433,8 +434,8 @@ static void _postAudioBuffer(struct GBAAVStream* stream, struct GBAAudio* audio)
|
||||||
#elif RESAMPLE_LIBRARY == RESAMPLE_NN
|
#elif RESAMPLE_LIBRARY == RESAMPLE_NN
|
||||||
GBAAudioCopy(audio, &audioLeft[audioPos], &audioRight[audioPos], AUDIO_SAMPLES);
|
GBAAudioCopy(audio, &audioLeft[audioPos], &audioRight[audioPos], AUDIO_SAMPLES);
|
||||||
#endif
|
#endif
|
||||||
GSPGPU_FlushDataCache(0, (void*) &audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t));
|
GSPGPU_FlushDataCache(&audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t));
|
||||||
GSPGPU_FlushDataCache(0, (void*) &audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t));
|
GSPGPU_FlushDataCache(&audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t));
|
||||||
audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER;
|
audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER;
|
||||||
if (audioPos == AUDIO_SAMPLES * 3) {
|
if (audioPos == AUDIO_SAMPLES * 3) {
|
||||||
u8 playing = 0;
|
u8 playing = 0;
|
||||||
|
@ -448,9 +449,6 @@ static void _postAudioBuffer(struct GBAAVStream* stream, struct GBAAudio* audio)
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ptmInit();
|
|
||||||
hasSound = !csndInit();
|
|
||||||
|
|
||||||
rotation.d.sample = _sampleRotation;
|
rotation.d.sample = _sampleRotation;
|
||||||
rotation.d.readTiltX = _readTiltX;
|
rotation.d.readTiltX = _readTiltX;
|
||||||
rotation.d.readTiltY = _readTiltY;
|
rotation.d.readTiltY = _readTiltY;
|
||||||
|
@ -464,6 +462,9 @@ int main() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptmuInit();
|
||||||
|
hasSound = !csndInit();
|
||||||
|
|
||||||
if (hasSound) {
|
if (hasSound) {
|
||||||
audioLeft = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80);
|
audioLeft = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80);
|
||||||
audioRight = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80);
|
audioRight = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80);
|
||||||
|
@ -472,6 +473,7 @@ int main() {
|
||||||
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false);
|
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false);
|
||||||
|
|
||||||
if (ctrInitGpu() < 0) {
|
if (ctrInitGpu() < 0) {
|
||||||
|
gbaOutputTexture.data = 0;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,18 +485,22 @@ int main() {
|
||||||
gbaOutputTexture.data = vramAlloc(256 * 256 * 2);
|
gbaOutputTexture.data = vramAlloc(256 * 256 * 2);
|
||||||
void* outputTextureEnd = (u8*)gbaOutputTexture.data + 256 * 256 * 2;
|
void* outputTextureEnd = (u8*)gbaOutputTexture.data + 256 * 256 * 2;
|
||||||
|
|
||||||
|
if (!gbaOutputTexture.data) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Zero texture data to make sure no garbage around the border interferes with filtering
|
// Zero texture data to make sure no garbage around the border interferes with filtering
|
||||||
GX_SetMemoryFill(NULL,
|
GX_MemoryFill(
|
||||||
gbaOutputTexture.data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER,
|
gbaOutputTexture.data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER,
|
||||||
NULL, 0, NULL, 0);
|
NULL, 0, NULL, 0);
|
||||||
gspWaitForPSC0();
|
gspWaitForPSC0();
|
||||||
|
|
||||||
sdmcArchive = (FS_archive) {
|
sdmcArchive = (FS_Archive) {
|
||||||
ARCH_SDMC,
|
ARCHIVE_SDMC,
|
||||||
(FS_path) { PATH_EMPTY, 1, (const u8*)"" },
|
(FS_Path) { PATH_EMPTY, 1, "" },
|
||||||
0, 0
|
0
|
||||||
};
|
};
|
||||||
FSUSER_OpenArchive(0, &sdmcArchive);
|
FSUSER_OpenArchive(&sdmcArchive);
|
||||||
|
|
||||||
struct GUIFont* font = GUIFontCreate();
|
struct GUIFont* font = GUIFontCreate();
|
||||||
|
|
||||||
|
@ -549,10 +555,14 @@ int main() {
|
||||||
GBAGUIDeinit(&runner);
|
GBAGUIDeinit(&runner);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
if (renderer.outputBuffer) {
|
||||||
linearFree(renderer.outputBuffer);
|
linearFree(renderer.outputBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gbaOutputTexture.data) {
|
||||||
ctrDeinitGpu();
|
ctrDeinitGpu();
|
||||||
vramFree(gbaOutputTexture.data);
|
vramFree(gbaOutputTexture.data);
|
||||||
|
}
|
||||||
|
|
||||||
gfxExit();
|
gfxExit();
|
||||||
|
|
||||||
|
@ -560,7 +570,8 @@ cleanup:
|
||||||
linearFree(audioLeft);
|
linearFree(audioLeft);
|
||||||
linearFree(audioRight);
|
linearFree(audioRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
csndExit();
|
csndExit();
|
||||||
ptmExit();
|
ptmuExit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#ifdef _3DS
|
||||||
|
// ctrulib already has a type called Thread
|
||||||
|
#define Thread CustomThread
|
||||||
|
#endif
|
||||||
|
|
||||||
#define THREAD_ENTRY void
|
#define THREAD_ENTRY void
|
||||||
typedef ThreadFunc ThreadEntry;
|
typedef ThreadFunc ThreadEntry;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue