Fixed compatibility with latest libn3ds.
This commit is contained in:
parent
2bca9b04b6
commit
d7f701f02a
|
@ -44,12 +44,13 @@ Settings are stored in `/3ds/open_agb_firm/config.ini`.
|
|||
### General
|
||||
General settings.
|
||||
|
||||
`u8 backlight` - Backlight brightness
|
||||
`u8 backlight` - Backlight brightness in luminance (cd/m²)
|
||||
* Default: `64`
|
||||
* Possible values:
|
||||
* Old 3DS: `20`-`117`
|
||||
* New 3DS: `16`-`142`
|
||||
* Values ≤`64` are recommended.
|
||||
* Hardware calibration from your CTRNAND is required to get the correct brightness for both LCDs.
|
||||
|
||||
`u8 backlightSteps` - How much to adjust backlight brightness by
|
||||
* Default: `5`
|
||||
|
|
|
@ -22,7 +22,7 @@ BUILD := build
|
|||
SOURCES += ../source ../source/arm11 ../libraries/inih
|
||||
DATA :=
|
||||
INCLUDES += ../include ../libraries
|
||||
DEFINES := -DARM11 -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
DEFINES := -D__ARM11__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
|
||||
ASSETS :=
|
||||
|
||||
|
@ -35,11 +35,11 @@ endif
|
|||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
|
||||
|
||||
CFLAGS := $(ARCH) -std=c17 -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
CFLAGS := $(ARCH) -std=c2x -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
-ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
CXXFLAGS := $(ARCH) -std=c++17 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
-mword-relocations -ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CXXFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ include $(TOPDIR)/../libraries/libn3ds/libn3ds9.mk
|
|||
BUILD := build
|
||||
SOURCES += ../source/arm9
|
||||
DATA :=
|
||||
INCLUDES += ../include ../thirdparty
|
||||
DEFINES := -DARM9 -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
INCLUDES += ../include
|
||||
DEFINES := -D__ARM9__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
|
||||
|
||||
ifneq ($(strip $(NO_DEBUG)),)
|
||||
|
@ -34,11 +34,11 @@ endif
|
|||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
|
||||
|
||||
CFLAGS := $(ARCH) -std=c17 -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
CFLAGS := $(ARCH) -std=c2x -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
-ffunction-sections -Wall -Wextra
|
||||
CFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
CXXFLAGS := $(ARCH) -std=c++17 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
-mword-relocations -ffunction-sections -Wall -Wextra
|
||||
CXXFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 magic; // "BM"
|
||||
u32 fileSize;
|
||||
u16 reserved;
|
||||
u16 reserved2;
|
||||
u32 pixelOffset; // From file start.
|
||||
} PACKED BmpHeader;
|
||||
static_assert(sizeof(BmpHeader) == 14);
|
||||
|
||||
/*typedef enum
|
||||
{
|
||||
BI_RGB = 0x0000,
|
||||
BI_RLE8 = 0x0001,
|
||||
BI_RLE4 = 0x0002,
|
||||
BI_BITFIELDS = 0x0003,
|
||||
BI_JPEG = 0x0004,
|
||||
BI_PNG = 0x0005,
|
||||
BI_CMYK = 0x000B,
|
||||
BI_CMYKRLE8 = 0x000C,
|
||||
BI_CMYKRLE4 = 0x000D
|
||||
} Compression;*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 headerSize; // Size of this header. 40 bytes.
|
||||
s32 width;
|
||||
s32 height; // If >=0, pixel lines are in order bottom to top. Otherwise top to bottom.
|
||||
u16 colorPlanes; // Must be 1.
|
||||
u16 bitsPerPixel; // 1, 4, 8, 16, 24, 32.
|
||||
u32 compression;
|
||||
u32 imageSize; // Can be 0 if compression is 0.
|
||||
s32 xPixelsPerMeter;
|
||||
s32 yPixelsPerMeter;
|
||||
u32 colorsUsed;
|
||||
u32 colorsImportant;
|
||||
} PACKED Bitmapinfoheader;
|
||||
static_assert(sizeof(Bitmapinfoheader) == 0x28);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BmpHeader header;
|
||||
Bitmapinfoheader dib;
|
||||
u32 rMask; // Optional.
|
||||
u32 gMask; // Optional.
|
||||
u32 bMask; // Optional.
|
||||
} PACKED BmpV1WithMasks;
|
||||
static_assert(sizeof(BmpV1WithMasks) == 0x42);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BmpHeader header;
|
||||
Bitmapinfoheader dib;
|
||||
} PACKED BmpV1;
|
||||
static_assert(sizeof(BmpV1) == 0x36);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -22,6 +22,11 @@
|
|||
#include "oaf_error_codes.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// [general]
|
||||
|
@ -58,3 +63,7 @@ typedef struct
|
|||
|
||||
|
||||
Result parseOafConfig(const char *const path, OafConfig *const cfg, const bool newCfgOnError);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -22,4 +22,13 @@
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result browseFiles(const char *const basePath, char selected[512]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -21,6 +21,11 @@
|
|||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define GPU_RENDER_BUF_ADDR (0x18180000)
|
||||
#define GBA_INIT_LIST_SIZE (1136)
|
||||
#define GBA_LIST2_SIZE (448)
|
||||
|
@ -32,3 +37,7 @@ extern u8 gbaGpuList2[GBA_LIST2_SIZE];
|
|||
|
||||
|
||||
void patchGbaGpuCmdList(u8 scaleType);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -22,8 +22,17 @@
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result oafParseConfigEarly(void);
|
||||
void changeBacklight(s16 amount);
|
||||
Result oafInitAndRun(void);
|
||||
void oafUpdate(void);
|
||||
void oafFinish(void);
|
||||
void oafFinish(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -18,4 +18,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
Result patchRom(const char *const gamePath, u32 *romSize);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result patchRom(const char *const gamePath, u32 *romSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -23,6 +23,11 @@
|
|||
#include "arm11/config.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 sha1[20];
|
||||
|
@ -34,4 +39,8 @@ static_assert(sizeof(GbaDbEntry) == 28, "Error: GBA DB entry struct is not packe
|
|||
|
||||
|
||||
u16 detectSaveType(const u32 romSize, const u16 defaultSave);
|
||||
u16 getSaveType(const OafConfig *const cfg, const u32 romSize, const char *const savePath);
|
||||
u16 getSaveType(const OafConfig *const cfg, const u32 romSize, const char *const savePath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -21,6 +21,11 @@
|
|||
#include "error_codes.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define MAKE_CUSTOM_ERR(e) (CUSTOM_ERR_OFFSET + (e))
|
||||
|
||||
// Keep errors in the range of 0-CUSTOM_ERR_OFFSET - 1.
|
||||
|
@ -38,7 +43,11 @@ enum
|
|||
|
||||
|
||||
const char* oafResult2String(Result res);
|
||||
#ifdef ARM11
|
||||
#ifdef __ARM11__
|
||||
void printError(Result res);
|
||||
void printErrorWaitInput(Result res, u32 waitKeys);
|
||||
#endif // ifdef ARM11
|
||||
#endif // ifdef __ARM11__
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -165,4 +165,4 @@ Result parseOafConfig(const char *const path, OafConfig *const cfg, const bool n
|
|||
free(iniBuf);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -240,4 +240,4 @@ end:
|
|||
ee_printf("\x1b[2J");
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -72,7 +72,7 @@ alignas(16) u8 gbaGpuInitList[GBA_INIT_LIST_SIZE] =
|
|||
0x18, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x00, 0x4F, 0x80, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, // Last 4 bytes: GPUREG_TEXUNIT0_PARAM.
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, // Last 4 bytes: GPUREG_TEXUNIT0_TYPE.
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, // Last 4 bytes: GPUREG_TEXUNIT0_TYPE.
|
||||
0x8E, 0x00, 0x0F, 0x00, 0x01, 0x10, 0x01, 0x00, 0x80, 0x00, 0x0B, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00,
|
||||
|
@ -213,4 +213,4 @@ void patchGbaGpuCmdList(u8 scaleType)
|
|||
|
||||
flushDCacheRange(gbaGpuInitList, sizeof(gbaGpuInitList));
|
||||
flushDCacheRange(gbaGpuList2, sizeof(gbaGpuList2));
|
||||
}
|
||||
}
|
|
@ -30,11 +30,10 @@
|
|||
|
||||
int main(void)
|
||||
{
|
||||
Result res = fMount(FS_DRIVE_SDMC);
|
||||
if(res == RES_OK) res = oafParseConfigEarly();
|
||||
GFX_init(GFX_BGR8, GFX_RGB565);
|
||||
Result res = oafParseConfigEarly();
|
||||
GFX_init(GFX_BGR8, GFX_R5G6B5, GFX_TOP_2D);
|
||||
changeBacklight(0); // Apply backlight config.
|
||||
consoleInit(SCREEN_BOT, NULL);
|
||||
consoleInit(GFX_LCD_BOT, NULL);
|
||||
//CODEC_init();
|
||||
|
||||
if(res == RES_OK && (res = oafInitAndRun()) == RES_OK)
|
||||
|
@ -53,9 +52,9 @@ int main(void)
|
|||
|
||||
CODEC_deinit();
|
||||
GFX_deinit();
|
||||
fUnmount(FS_DRIVE_SDMC);
|
||||
fUnmount(FS_DRIVE_SDMC); // TODO: Move elsewhere. __systemDeinit() already calls it.
|
||||
|
||||
power_off();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@
|
|||
#include "fs.h"
|
||||
#include "fsutil.h"
|
||||
#include "arm11/fmt.h"
|
||||
#include "arm11/drivers/lcd.h"
|
||||
#include "arm11/drivers/lgyfb.h"
|
||||
#include "arm11/drivers/gx.h"
|
||||
#include "arm11/drivers/lgycap.h"
|
||||
#include "drivers/gfx.h"
|
||||
#include "arm11/drivers/mcu.h"
|
||||
#include "kernel.h"
|
||||
|
@ -41,10 +41,12 @@
|
|||
#include "arm11/drivers/codec.h"
|
||||
#include "arm11/save_type.h"
|
||||
#include "arm11/patch.h"
|
||||
#include "arm11/bitmap.h"
|
||||
|
||||
|
||||
#define OAF_WORK_DIR "sdmc:/3ds/open_agb_firm"
|
||||
#define OAF_SAVE_DIR "saves" // Relative to work dir.
|
||||
#define OAF_WORK_DIR "sdmc:/3ds/open_agb_firm"
|
||||
#define OAF_SAVE_DIR "saves" // Relative to work dir.
|
||||
#define OAF_SCREENSHOT_DIR "screenshots" // Relative to work dir.
|
||||
|
||||
|
||||
|
||||
|
@ -164,6 +166,7 @@ static void adjustGammaTableForGba(void)
|
|||
const float contrast = g_oafConfig.contrast;
|
||||
const float brightness = g_oafConfig.brightness / contrast;
|
||||
const float contrastInTargetGamma = powf(contrast, targetGamma);
|
||||
vu32 *const color_lut_data = &getGxRegs()->pdc0.color_lut_data;
|
||||
for(u32 i = 0; i < 256; i++)
|
||||
{
|
||||
// Adjust i with brightness and convert to target gamma.
|
||||
|
@ -173,40 +176,79 @@ static void adjustGammaTableForGba(void)
|
|||
const u32 res = clamp_s32(lroundf(powf(contrastInTargetGamma * adjusted, lcdGamma) * 255), 0, 255);
|
||||
|
||||
// Same adjustment for red/green/blue.
|
||||
REG_LCD_PDC0_GTBL_FIFO = res<<16 | res<<8 | res;
|
||||
*color_lut_data = res<<16 | res<<8 | res;
|
||||
}
|
||||
}
|
||||
|
||||
static Result dumpFrameTex(void)
|
||||
{
|
||||
// Stop LgyFb before dumping the frame to prevent glitches.
|
||||
LGYFB_stop();
|
||||
// Stop LgyCap before dumping the frame to prevent glitches.
|
||||
LGYCAP_stop(LGYCAP_DEV_TOP);
|
||||
|
||||
// 512x-512 (hight negative to flip vertically).
|
||||
// Pixels at offset 0x40.
|
||||
alignas(4) static const u8 bmpHeader[54] =
|
||||
// A1BGR5 format (alpha ignored).
|
||||
constexpr u32 alignment = 0x80; // Make PPF happy.
|
||||
alignas(4) static BmpV1WithMasks bmpHeaders =
|
||||
{
|
||||
0x42, 0x4D, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFE,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x13, 0x0B,
|
||||
0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
{
|
||||
.magic = 0x4D42,
|
||||
.fileSize = alignment + 240 * 160 * 2,
|
||||
.reserved = 0,
|
||||
.reserved2 = 0,
|
||||
.pixelOffset = alignment
|
||||
},
|
||||
{
|
||||
.headerSize = sizeof(Bitmapinfoheader),
|
||||
.width = 240,
|
||||
.height = -160,
|
||||
.colorPlanes = 1,
|
||||
.bitsPerPixel = 16,
|
||||
.compression = 3, // Bitfields.
|
||||
.imageSize = 240 * 160 * 2,
|
||||
.xPixelsPerMeter = 0,
|
||||
.yPixelsPerMeter = 0,
|
||||
.colorsUsed = 0,
|
||||
.colorsImportant = 0
|
||||
},
|
||||
.rMask = 0xF800,
|
||||
.gMask = 0x07C0,
|
||||
.bMask = 0x003E
|
||||
};
|
||||
|
||||
GX_displayTransfer((u32*)0x18200000, 240u<<16 | 512, (u32*)0x18400040, 240u<<16 | 512, 1u<<12 | 1u<<8);
|
||||
u32 outDim = PPF_DIM(240, 160);
|
||||
u32 fileSize = alignment + 240 * 160 * 2;
|
||||
if(g_oafConfig.scaler > 1)
|
||||
{
|
||||
outDim = PPF_DIM(360, 240);
|
||||
fileSize = alignment + 360 * 240 * 2;
|
||||
|
||||
bmpHeaders.header.fileSize = fileSize;
|
||||
bmpHeaders.dib.width = 360;
|
||||
bmpHeaders.dib.height = -240;
|
||||
bmpHeaders.dib.imageSize = 360 * 240 * 2;
|
||||
}
|
||||
|
||||
// Transfer frame data out of the 512x512 texture.
|
||||
// We will use the currently hidden frame buffer as temporary buffer.
|
||||
// Note: This is a race with the currently displaying frame buffer
|
||||
// because we just swapped buffers in the gfx handler function.
|
||||
u32 *const tmpBuf = GFX_getBuffer(GFX_LCD_TOP, GFX_SIDE_LEFT);
|
||||
GX_displayTransfer((u32*)0x18200000, PPF_DIM(512, 240), tmpBuf + (alignment / 4), outDim,
|
||||
PPF_O_FMT(GX_RGB5A1) | PPF_I_FMT(GX_RGB5A1) | PPF_CROP_EN);
|
||||
memcpy(tmpBuf, &bmpHeaders, sizeof(bmpHeaders));
|
||||
GFX_waitForPPF();
|
||||
memcpy((void*)0x18400000, bmpHeader, sizeof(bmpHeader));
|
||||
|
||||
// Get current date & time.
|
||||
RtcTimeDate td;
|
||||
char fn[32];
|
||||
MCU_getRtcTimeDate(&td);
|
||||
ee_sprintf(fn, "texture_dump_%04X%02X%02X%02X%02X%02X.bmp", td.y + 0x2000, td.mon, td.d, td.h, td.min, td.s);
|
||||
const Result res = fsQuickWrite(fn, (void*)0x18400000, 0x40 + 512 * 512 * 3);
|
||||
|
||||
// Restart LgyFb.
|
||||
LGYFB_start();
|
||||
// Construct file path from date & time. Then write the file.
|
||||
char fn[36];
|
||||
ee_sprintf(fn, OAF_SCREENSHOT_DIR "/%04X_%02X_%02X_%02X_%02X_%02X.bmp",
|
||||
td.y + 0x2000, td.mon, td.d, td.h, td.min, td.s);
|
||||
const Result res = fsQuickWrite(fn, tmpBuf, fileSize);
|
||||
|
||||
// Restart LgyCap.
|
||||
LGYCAP_start(LGYCAP_DEV_TOP);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -220,10 +262,17 @@ static void gbaGfxHandler(void *args)
|
|||
if(waitForEvent(event) != KRES_OK) break;
|
||||
clearEvent(event);
|
||||
|
||||
// Rotate the frame using the GPU.
|
||||
// 240x160 no scaling: 184 µs
|
||||
// 240x160 bilinear x1.5: 408 µs
|
||||
// 360x240 no scaling: 437 µs
|
||||
// All measurements are the worst timings in ~30 seconds of runtime.
|
||||
// Measured with timer prescaler 1.
|
||||
// BGR8:
|
||||
// 240x160 no scaling: ~184 µs
|
||||
// 240x160 bilinear x1.5: ~408 µs
|
||||
// 360x240 no scaling: ~437 µs
|
||||
//
|
||||
// A1BGR5:
|
||||
// 240x160 no scaling: ~188 µs (25300 ticks)
|
||||
// 240x160 bilinear x1.5: ~407 µs (54619 ticks)
|
||||
// 360x240 no scaling: ~400 µs (53725 ticks)
|
||||
static bool inited = false;
|
||||
u32 listSize;
|
||||
const u32 *list;
|
||||
|
@ -241,9 +290,10 @@ static void gbaGfxHandler(void *args)
|
|||
}
|
||||
GX_processCommandList(listSize, list);
|
||||
GFX_waitForP3D();
|
||||
GX_displayTransfer((u32*)GPU_RENDER_BUF_ADDR, 400u<<16 | 240, GFX_getFramebuffer(SCREEN_TOP), 400u<<16 | 240, 1u<<12 | 1u<<8);
|
||||
GX_displayTransfer((u32*)GPU_RENDER_BUF_ADDR, PPF_DIM(240, 400), GFX_getBuffer(GFX_LCD_TOP, GFX_SIDE_LEFT),
|
||||
PPF_DIM(240, 400), PPF_O_FMT(GX_BGR8) | PPF_I_FMT(GX_BGR8));
|
||||
GFX_waitForPPF();
|
||||
GFX_swapFramebufs();
|
||||
GFX_swapBuffers();
|
||||
|
||||
// Trigger only if both are held and at least one is detected as newly pressed down.
|
||||
if(hidKeysHeld() == (KEY_Y | KEY_SELECT) && hidKeysDown() != 0)
|
||||
|
@ -272,7 +322,7 @@ void changeBacklight(s16 amount)
|
|||
newVal = (newVal < min ? min : newVal);
|
||||
g_oafConfig.backlight = (u8)newVal;
|
||||
|
||||
GFX_setBrightness((u8)newVal, (u8)newVal);
|
||||
GFX_setLcdLuminance(newVal);
|
||||
}
|
||||
|
||||
static void updateBacklight(void)
|
||||
|
@ -292,23 +342,23 @@ static void updateBacklight(void)
|
|||
changeBacklight(-steps);
|
||||
|
||||
// Disable backlight switching in debug builds on 2DS.
|
||||
const GfxBlight lcd = (MCU_getSystemModel() != 3 ? GFX_BLIGHT_TOP : GFX_BLIGHT_BOT);
|
||||
const GfxBl lcd = (MCU_getSystemModel() != SYS_MODEL_2DS ? GFX_BL_TOP : GFX_BL_BOT);
|
||||
#ifndef NDEBUG
|
||||
if(lcd != GFX_BLIGHT_BOT)
|
||||
if(lcd != GFX_BL_BOT)
|
||||
#endif
|
||||
{
|
||||
// Turn off backlight.
|
||||
if(backlightOn && kHeld == (KEY_X | KEY_DLEFT))
|
||||
{
|
||||
backlightOn = false;
|
||||
GFX_powerOffBacklights(lcd);
|
||||
GFX_powerOffBacklight(lcd);
|
||||
}
|
||||
|
||||
// Turn on backlight.
|
||||
if(!backlightOn && kHeld == (KEY_X | KEY_DRIGHT))
|
||||
{
|
||||
backlightOn = true;
|
||||
GFX_powerOnBacklights(lcd);
|
||||
GFX_powerOnBacklight(lcd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -407,6 +457,10 @@ Result oafParseConfigEarly(void)
|
|||
res = fMkdir(OAF_SAVE_DIR);
|
||||
if(res != RES_OK && res != RES_FR_EXIST) break;
|
||||
|
||||
// Create screenshots folder.
|
||||
res = fMkdir(OAF_SCREENSHOT_DIR);
|
||||
if(res != RES_OK && res != RES_FR_EXIST) break;
|
||||
|
||||
// Parse the config.
|
||||
res = parseOafConfig("config.ini", &g_oafConfig, true);
|
||||
} while(0);
|
||||
|
@ -436,31 +490,18 @@ KHandle setupFrameCapture(const u8 scaler)
|
|||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
ScalerCfg gbaCfg;
|
||||
LgyCapCfg gbaCfg;
|
||||
gbaCfg.cnt = LGYCAP_OUT_SWIZZLE | LGYCAP_ROT_NONE | LGYCAP_OUT_FMT_A1BGR5 | (is240x160 ? 0 : LGYCAP_HSCALE_EN | LGYCAP_VSCALE_EN);
|
||||
gbaCfg.w = (is240x160 ? 240 : 360);
|
||||
gbaCfg.h = (is240x160 ? 160 : 240);
|
||||
gbaCfg.vLen = 6;
|
||||
gbaCfg.vPatt = 0b00011011;
|
||||
memcpy(gbaCfg.vMatrix, matrix, 6 * 8 * 2);
|
||||
gbaCfg.hLen = 6;
|
||||
gbaCfg.hPatt = (is240x160 ? 0b00111111 : 0b00011011);
|
||||
gbaCfg.hPatt = 0b00011011;
|
||||
memcpy(gbaCfg.hMatrix, &matrix[6 * 8], 6 * 8 * 2);
|
||||
|
||||
if(is240x160)
|
||||
{
|
||||
memset(gbaCfg.hMatrix, 0, 6 * 8 * 2);
|
||||
s16 *const identityRow = &gbaCfg.hMatrix[3 * 8];
|
||||
for(unsigned i = 0; i < 6; i++)
|
||||
{
|
||||
// Set identity entries.
|
||||
identityRow[i] = 0x4000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(gbaCfg.hMatrix, &matrix[6 * 8], 6 * 8 * 2);
|
||||
}
|
||||
|
||||
return LGYFB_init(&gbaCfg);
|
||||
return LGYCAP_init(LGYCAP_DEV_TOP, &gbaCfg);
|
||||
}
|
||||
|
||||
Result oafInitAndRun(void)
|
||||
|
@ -522,7 +563,8 @@ Result oafInitAndRun(void)
|
|||
// Force black and turn the backlight off on the bottom screen.
|
||||
// Don't turn the backlight off on 2DS (1 panel).
|
||||
GFX_setForceBlack(false, true);
|
||||
if(MCU_getSystemModel() != 3) GFX_powerOffBacklights(GFX_BLIGHT_BOT);
|
||||
if(MCU_getSystemModel() != SYS_MODEL_2DS)
|
||||
GFX_powerOffBacklight(GFX_BL_BOT);
|
||||
#endif
|
||||
|
||||
// Initialize frame capture and frame handler.
|
||||
|
@ -543,16 +585,17 @@ Result oafInitAndRun(void)
|
|||
if(g_oafConfig.scaler == 0) // No borders for scaled modes.
|
||||
{
|
||||
// Abuse currently invisible frame buffer as temporary buffer.
|
||||
void *const borderBuf = GFX_getFramebuffer(SCREEN_TOP);
|
||||
void *const borderBuf = GFX_getBuffer(GFX_LCD_TOP, GFX_SIDE_LEFT);
|
||||
if(fsQuickRead("border.bgr", borderBuf, 400 * 240 * 3) == RES_OK)
|
||||
{
|
||||
// Copy border in swizzled form to GPU render buffer.
|
||||
GX_displayTransfer(borderBuf, 400u<<16 | 240, (u32*)GPU_RENDER_BUF_ADDR, 400u<<16 | 240, 1u<<12 | 1u<<8 | 1u<<1);
|
||||
GX_displayTransfer(borderBuf, PPF_DIM(240, 400), (u32*)GPU_RENDER_BUF_ADDR,
|
||||
PPF_DIM(240, 400), PPF_O_FMT(GX_BGR8) | PPF_I_FMT(GX_BGR8) | PPF_OUT_TILED);
|
||||
GFX_waitForPPF();
|
||||
}
|
||||
}
|
||||
|
||||
// Sync LgyFb start with LCD VBlank.
|
||||
// Sync LgyCap start with LCD VBlank.
|
||||
GFX_waitForVBlank0();
|
||||
LGY11_switchMode();
|
||||
}
|
||||
|
@ -586,7 +629,7 @@ void oafFinish(void)
|
|||
{
|
||||
// frameReadyEvent deleted by this function.
|
||||
// gbaGfxHandler() will automatically terminate.
|
||||
LGYFB_deinit();
|
||||
LGYCAP_deinit(LGYCAP_DEV_TOP);
|
||||
g_frameReadyEvent = 0;
|
||||
LGY11_deinit();
|
||||
}
|
||||
}
|
|
@ -27,4 +27,4 @@ int main(void)
|
|||
while(1) __wfi();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
#include "oaf_error_codes.h"
|
||||
#include "drivers/gfx.h"
|
||||
#ifdef ARM11
|
||||
#include "arm11/fmt.h"
|
||||
#include "arm11/drivers/hid.h"
|
||||
#endif
|
||||
#ifdef __ARM11__
|
||||
#include "arm11/fmt.h"
|
||||
#include "arm11/drivers/hid.h"
|
||||
#endif // #ifdef __ARM11__
|
||||
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ const char* oafResult2String(Result res)
|
|||
return (res < CUSTOM_ERR_OFFSET ? result2String(res) : oafResultStrings[res - CUSTOM_ERR_OFFSET]);
|
||||
}
|
||||
|
||||
#ifdef ARM11
|
||||
#ifdef __ARM11__
|
||||
void printError(Result res)
|
||||
{
|
||||
ee_printf("Error: %s.\n", oafResult2String(res));
|
||||
|
@ -63,4 +63,4 @@ void printErrorWaitInput(Result res, u32 waitKeys)
|
|||
if(hidGetExtraKeys(0) & (KEY_POWER_HELD | KEY_POWER)) break;
|
||||
}
|
||||
}
|
||||
#endif // ifdef ARM11
|
||||
#endif // ifdef __ARM11__
|
Loading…
Reference in New Issue