3DS: Update to new API
@@ -213,8 +213,9 @@ UNUSED(portable);
snprintf(out, outLength, "/%s", projectName); mkdir(out, 0777); #elif defined(_3DS) + UNUSED(portable); snprintf(out, outLength, "/%s", projectName); - FSUSER_CreateDirectory(0, sdmcArchive, FS_makePath(PATH_CHAR, out)); + FSUSER_CreateDirectory(sdmcArchive, fsMakePath(PATH_ASCII, out), 0); #else getcwd(out, outLength); strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
@@ -18,7 +18,7 @@ };
struct VDirEntry3DS { struct VDirEntry d; - FS_dirent ent; + FS_DirectoryEntry ent; char utf8Name[256]; };@@ -49,14 +49,15 @@
static const char* _vd3deName(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)); if (!vf3d) { return 0; } - FS_path newPath = FS_makePath(PATH_CHAR, path); - Result res = FSUSER_OpenFile(0, &vf3d->handle, *archive, newPath, flags, FS_ATTRIBUTE_NONE); + // TODO: Use UTF-16 + FS_Path newPath = fsMakePath(PATH_ASCII, path); + Result res = FSUSER_OpenFile(&vf3d->handle, *archive, newPath, flags, 0); if (res & 0xFFFC03FF) { free(vf3d); return 0;@@ -175,8 +176,9 @@ if (!vd3d) {
return 0; } - FS_path newPath = FS_makePath(PATH_CHAR, path); - Result res = FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath); + // TODO: Use UTF-16 + FS_Path newPath = fsMakePath(PATH_ASCII, path); + Result res = FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); if (res & 0xFFFC03FF) { free(vd3d); return 0;@@ -207,8 +209,9 @@
static void _vd3dRewind(struct VDir* vd) { struct VDir3DS* vd3d = (struct VDir3DS*) vd; FSDIR_Close(vd3d->handle); - FS_path newPath = FS_makePath(PATH_CHAR, vd3d->path); - FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath); + // TODO: Use UTF-16 + FS_Path newPath = fsMakePath(PATH_ASCII, vd3d->path); + FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); } static struct VDirEntry* _vd3dListNext(struct VDir* vd) {@@ -264,7 +267,7 @@ }
static enum VFSType _vd3deType(struct VDirEntry* vde) { struct VDirEntry3DS* vd3de = (struct VDirEntry3DS*) vde; - if (vd3de->ent.isDirectory) { + if (vd3de->ent.attributes & FS_ATTRIBUTE_DIRECTORY) { return VFS_DIRECTORY; } return VFS_FILE;
@@ -10,8 +10,8 @@ #include "util/vfs.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
@@ -5,6 +5,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <3ds.h> +#include <3ds/gpu/gpu.h> +#include <3ds/gpu/gx.h> #include <stdlib.h> #include <string.h> #include <stdio.h>@@ -42,57 +44,12 @@ static int pendingEvents = 0;
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) { int toClear = events & pendingEvents; - if (toClear & (1 << GSPEVENT_PSC0)) { + if (toClear & (1 << GSPGPU_EVENT_PSC0)) { gspWaitForPSC0(); } - if (toClear & (1 << GSPEVENT_PPF)) { + if (toClear & (1 << GSPGPU_EVENT_PPF)) { gspWaitForPPF(); } pendingEvents ^= toClear;@@ -103,39 +60,39 @@ static void _GPU_SetFramebuffer(intptr_t colorBuffer, intptr_t depthBuffer, u16 w, u16 h) {
u32 buf[4]; // Unknown - GPUCMD_AddWrite(GPUREG_0111, 0x00000001); - GPUCMD_AddWrite(GPUREG_0110, 0x00000001); + GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001); + GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001); // Set depth/color buffer address and dimensions buf[0] = depthBuffer >> 3; buf[1] = colorBuffer >> 3; buf[2] = (0x01) << 24 | ((h-1) & 0xFFF) << 12 | (w & 0xFFF) << 0; 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 GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 3 /* D248S */ ); 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 buf[0] = colorBuffer != 0 ? 0xF : 0x0; buf[1] = buf[0]; buf[2] = depthBuffer != 0 ? 0x2 : 0x0; 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) { u32 buf[4]; - buf[0] = _f24FromFloat(w / 2.0f); - buf[1] = _f31FromFloat(2.0f / w) << 1; - buf[2] = _f24FromFloat(h / 2.0f); - buf[3] = _f31FromFloat(2.0f / h) << 1; - GPUCMD_AddIncrementalWrites(GPUREG_0041, buf, 4); + buf[0] = f32tof24(w / 2.0f); + buf[1] = f32tof31(2.0f / w) << 1; + buf[2] = f32tof24(h / 2.0f); + buf[3] = f32tof31(2.0f / h) << 1; + 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[1] = 0;@@ -259,7 +216,7 @@ } else {
fw = 320; } - _GPU_SetFramebuffer(osConvertVirtToPhys((u32)gpuColorBuffer[screen]), 0, 240, fw); + _GPU_SetFramebuffer(osConvertVirtToPhys(gpuColorBuffer[screen]), 0, 240, fw); } void ctrGpuBeginDrawing(void) {@@ -282,8 +239,8 @@ // Disable alpha testing
GPU_SetAlphaTest(false, GPU_ALWAYS, 0); // Unknown - GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0); - GPUCMD_AddWrite(GPUREG_0118, 0); + GPUCMD_AddMaskedWrite(GPUREG_EARLYDEPTH_TEST1, 0x1, 0); + GPUCMD_AddWrite(GPUREG_EARLYDEPTH_TEST2, 0); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0), // RGB@@ -299,7 +256,7 @@ _setDummyTexEnv(4);
_setDummyTexEnv(5); // Configure vertex attribute format - u32 bufferOffsets[] = { osConvertVirtToPhys((u32)ctrVertexBuffer) - VRAM_BASE }; + u32 bufferOffsets[] = { osConvertVirtToPhys(ctrVertexBuffer) - VRAM_BASE }; u64 arrayTargetAttributes[] = { 0x210 }; u8 numAttributesInArray[] = { 3 }; GPU_SetAttributeBuffers(@@ -332,29 +289,29 @@ void* colorBuffer = (u8*)gpuColorBuffer[screen] + ((fw - w) * 240 * 4);
const u32 GX_CROP_INPUT_LINES = (1 << 2); - ctrClearPending(1 << GSPEVENT_PSC0); - ctrClearPending(1 << GSPEVENT_PPF); + ctrClearPending(1 << GSPGPU_EVENT_PSC0); + ctrClearPending(1 << GSPGPU_EVENT_PPF); - GX_SetDisplayTransfer(NULL, + GX_DisplayTransfer( colorBuffer, GX_BUFFER_DIM(240, fw), outputFramebuffer, GX_BUFFER_DIM(h, w), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_CROP_INPUT_LINES); - pendingEvents |= (1 << GSPEVENT_PPF); + pendingEvents |= (1 << GSPGPU_EVENT_PPF); } void ctrGpuEndDrawing(void) { - ctrClearPending(1 << GSPEVENT_PPF); + ctrClearPending(1 << GSPGPU_EVENT_PPF); gfxSwapBuffersGpu(); - gspWaitForEvent(GSPEVENT_VBlank0, false); + gspWaitForEvent(GSPGPU_EVENT_VBlank0, false); void* gpuColorBuffer0End = (char*)gpuColorBuffer[0] + 240 * 400 * 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[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) {@@ -382,7 +339,7 @@ ctrFlushBatch();
GPU_SetTextureEnable(GPU_TEXUNIT0); GPU_SetTexture( - GPU_TEXUNIT0, (u32*)osConvertVirtToPhys((u32)texture->data), + GPU_TEXUNIT0, (u32*)osConvertVirtToPhys(texture->data), texture->width, texture->height, 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),@@ -444,15 +401,15 @@ if (ctrNumQuads == 0) {
return; } - ctrClearPending((1 << GSPEVENT_PSC0)); + ctrClearPending((1 << GSPGPU_EVENT_PSC0)); - GSPGPU_FlushDataCache(NULL, (u8*)ctrVertexBuffer, VERTEX_INDEX_BUFFER_SIZE); - GPU_DrawElements(GPU_UNKPRIM, (u32*)(osConvertVirtToPhys((u32)ctrIndexBuffer) - VRAM_BASE), ctrNumQuads * 6); + GSPGPU_FlushDataCache(ctrVertexBuffer, VERTEX_INDEX_BUFFER_SIZE); + GPU_DrawElements(GPU_GEOMETRY_PRIM, (u32*)(osConvertVirtToPhys(ctrIndexBuffer) - VRAM_BASE), ctrNumQuads * 6); GPU_FinishDrawing(); GPUCMD_Finalize(); - GSPGPU_FlushDataCache(NULL, (u8*)gpuCommandList, COMMAND_LIST_LENGTH * sizeof(u32)); - GPUCMD_FlushAndRun(NULL); + GSPGPU_FlushDataCache((u8*)gpuCommandList, COMMAND_LIST_LENGTH * sizeof(u32)); + GPUCMD_FlushAndRun(); gspWaitForP3D();
@@ -26,18 +26,23 @@ #include "util/common.h"
extern char* fake_heap_start; extern char* fake_heap_end; -u32 __linear_heap; -u32 __heapBase; -static u32 __heap_size = 0x02400000; -static u32 __linear_heap_size = 0x01400000; +extern u32 __ctru_linear_heap; +extern u32 __ctru_heap; +extern u32 __ctru_heap_size; +extern u32 __ctru_linear_heap_size; +static u32 __custom_heap_size = 0x02400000; +static u32 __custom_linear_heap_size = 0x01400000; extern void (*__system_retAddr)(void); -void __destroy_handle_list(void); +void envDestroyHandles(void); + void __appExit(); void __libc_fini_array(void); +Result __sync_fini(void) __attribute__((weak)); + uint32_t* romBuffer; size_t romBufferSize;@@ -58,36 +63,16 @@
void __system_allocateHeaps() { u32 tmp=0; + __ctru_heap_size = __custom_heap_size; + __ctru_linear_heap_size = __custom_linear_heap_size; + // Allocate the application heap - __heapBase = 0x08000000; - svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); + __ctru_heap = 0x08000000; + svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); // 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 - fake_heap_start = (char*)__heapBase; - fake_heap_end = fake_heap_start + __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(); + fake_heap_start = (char*)__ctru_heap; + fake_heap_end = fake_heap_start + __ctru_heap_size; }
@@ -31,8 +31,8 @@ tex->format = GPU_RGBA5551;
tex->width = 256; tex->height = 128; - GSPGPU_FlushDataCache(NULL, (u8*)font, font_size); - GX_RequestDma(NULL, (u32*)font, tex->data, font_size); + GSPGPU_FlushDataCache(font, font_size); + GX_RequestDma((u32*) font, tex->data, font_size); gspWaitForDMA(); return guiFont;
@@ -18,6 +18,7 @@ #include "3ds-vfs.h"
#include "ctr-gpu.h" #include <3ds.h> +#include <3ds/gpu/gx.h> static enum ScreenMode { SM_PA_BOTTOM,@@ -32,7 +33,7 @@
#define AUDIO_SAMPLES 0x80 #define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 24) -FS_archive sdmcArchive; +FS_Archive sdmcArchive; static struct GBA3DSRotationSource { struct GBARotationSource d;@@ -76,8 +77,8 @@ if (!loopMode) {
flags |= SOUND_ONE_SHOT; } - pleft = osConvertVirtToPhys((u32) left); - pright = osConvertVirtToPhys((u32) right); + pleft = osConvertVirtToPhys(left); + pright = osConvertVirtToPhys(right); u32 timer = CSND_TIMER(sampleRate); if (timer < 0x0042) {@@ -149,8 +150,8 @@
static int _batteryState(void) { u8 charge; u8 adapter; - PTMU_GetBatteryLevel(0, &charge); - PTMU_GetBatteryChargeState(0, &adapter); + PTMU_GetBatteryLevel(&charge); + PTMU_GetBatteryChargeState(&adapter); int state = 0; if (adapter) { state |= BATTERY_CHARGING;@@ -284,8 +285,8 @@
void* outputBuffer = renderer.outputBuffer; struct ctrTexture* tex = &gbaOutputTexture; - GSPGPU_FlushDataCache(NULL, outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2); - GX_SetDisplayTransfer(NULL, + GSPGPU_FlushDataCache(outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2); + GX_DisplayTransfer( outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, 256), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |@@ -324,9 +325,9 @@ }
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)); - GX_SetDisplayTransfer(NULL, - (void*)newPixels, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), + GSPGPU_FlushDataCache(newPixels, 256 * VIDEO_VERTICAL_PIXELS * sizeof(u32)); + GX_DisplayTransfer( + (u32*) newPixels, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, 256), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) |@@ -433,8 +434,8 @@ blip_read_samples(audio->right, &audioRight[audioPos], AUDIO_SAMPLES, false);
#elif RESAMPLE_LIBRARY == RESAMPLE_NN GBAAudioCopy(audio, &audioLeft[audioPos], &audioRight[audioPos], AUDIO_SAMPLES); #endif - GSPGPU_FlushDataCache(0, (void*) &audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); - GSPGPU_FlushDataCache(0, (void*) &audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); + GSPGPU_FlushDataCache(&audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); + GSPGPU_FlushDataCache(&audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER; if (audioPos == AUDIO_SAMPLES * 3) { u8 playing = 0;@@ -448,9 +449,6 @@ }
} int main() { - ptmInit(); - hasSound = !csndInit(); - rotation.d.sample = _sampleRotation; rotation.d.readTiltX = _readTiltX; rotation.d.readTiltY = _readTiltY;@@ -463,6 +461,9 @@
if (!allocateRomBuffer()) { return 1; } + + ptmuInit(); + hasSound = !csndInit(); if (hasSound) { audioLeft = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80);@@ -472,6 +473,7 @@
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false); if (ctrInitGpu() < 0) { + gbaOutputTexture.data = 0; goto cleanup; }@@ -482,19 +484,23 @@ gbaOutputTexture.width = 256;
gbaOutputTexture.height = 256; gbaOutputTexture.data = vramAlloc(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 - GX_SetMemoryFill(NULL, + GX_MemoryFill( gbaOutputTexture.data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER, NULL, 0, NULL, 0); gspWaitForPSC0(); - sdmcArchive = (FS_archive) { - ARCH_SDMC, - (FS_path) { PATH_EMPTY, 1, (const u8*)"" }, - 0, 0 + sdmcArchive = (FS_Archive) { + ARCHIVE_SDMC, + (FS_Path) { PATH_EMPTY, 1, "" }, + 0 }; - FSUSER_OpenArchive(0, &sdmcArchive); + FSUSER_OpenArchive(&sdmcArchive); struct GUIFont* font = GUIFontCreate();@@ -549,10 +555,14 @@ GBAGUIRunloop(&runner);
GBAGUIDeinit(&runner); cleanup: - linearFree(renderer.outputBuffer); + if (renderer.outputBuffer) { + linearFree(renderer.outputBuffer); + } - ctrDeinitGpu(); - vramFree(gbaOutputTexture.data); + if (gbaOutputTexture.data) { + ctrDeinitGpu(); + vramFree(gbaOutputTexture.data); + } gfxExit();@@ -560,7 +570,8 @@ if (hasSound) {
linearFree(audioLeft); linearFree(audioRight); } + csndExit(); - ptmExit(); + ptmuExit(); return 0; }
@@ -11,6 +11,11 @@
#include <3ds.h> #include <malloc.h> +#ifdef _3DS +// ctrulib already has a type called Thread +#define Thread CustomThread +#endif + #define THREAD_ENTRY void typedef ThreadFunc ThreadEntry;