Skip to content

Commit 4f08fa4

Browse files
Rebase the mcp_recovery branch and merge it to main (#59)
* Rebase the mcp_recovery branch on v0.6. FIXME: Graphical issues. - Framebuffer seems to be 1280x720, even though the output is 480p. - Some of the colors are incorrect. * gfx.c: Fix color issues in mcp_recovery. mcp_recovery uses XRGB, same as the DC_INIT builds (but not regular builds). This *was* in the original mcp_recovery branch, but I missed it when manually rebasing. * gfx.c: Use TV scaling for rects and text. Even though it's using 480p output, it seems the framebuffer is still internally 1280x720. ----------------------------- Co-authored-by: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com>
1 parent 837690b commit 4f08fa4

File tree

10 files changed

+150
-9
lines changed

10 files changed

+150
-9
lines changed

ios_kernel/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ LDFLAGS := -nostartfiles -nodefaultlibs -mbig-endian -flto \
5050

5151
LIBS := -lgcc
5252

53+
ifeq ($(MCP_RECOVERY), 1)
54+
CFLAGS += -DMCP_RECOVERY
55+
endif
56+
5357
#---------------------------------------------------------------------------------
5458
# list of directories containing libraries, this must be the top level
5559
# containing include and lib

ios_kernel/source/main.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,13 @@ int _main(void* arg)
6363
// redirect __sys_write0 to lolserial
6464
*(volatile uint32_t*) 0x0812dd68 = ARM_B(0x0812dd68, (uint32_t) &svcAB_handler);
6565

66+
#ifdef MCP_RECOVERY
67+
// hook memcpy called on every /dev/mcp_recovery ioctl to start menu thread
68+
*(volatile uint32_t*) (0x0510f4a0 - 0x05100000 + 0x13d80000) = THUMB_BL(0x0510f4a0, _MCP_recovery_ioctl_memcpy_hook);
69+
#else /* !MCP_RECOVERY */
6670
// add mcp ioctl hook to start mcp thread
6771
*(volatile uint32_t*) (0x05025242 - 0x05000000 + 0x081c0000) = THUMB_BL(0x05025242, _MCP_ioctl100_patch);
72+
#endif /* MCP_RECOVERY */
6873

6974
// replace custom kernel syscall
7075
*(volatile uint32_t*) 0x0812cd2c = ARM_B(0x0812cd2c, kernel_syscall_0x81);
@@ -94,10 +99,19 @@ int _main(void* arg)
9499
setClientCapabilities(currentThreadContext->pid, 0xd, 0xffffffffffffffffllu);
95100

96101
// start mcp thread
102+
#ifdef MCP_RECOVERY
103+
int mcpHandle = IOS_Open("/dev/mcp_recovery", 0);
104+
#else /* !MCP_RECOVERY */
97105
int mcpHandle = IOS_Open("/dev/mcp", 0);
106+
#endif /* MCP_RECOVERY */
98107
if (mcpHandle > 0) {
99108
lolserial_printf("Starting MCP thread...\n");
109+
#ifdef MCP_RECOVERY
110+
// send any ioctl to /dev/mcp_recovery to trigger hook
111+
IOS_Ioctl(mcpHandle, 0, NULL, 0, NULL, 0);
112+
#else /* !MCP_RECOVERY */
100113
IOS_Ioctl(mcpHandle, 100, NULL, 0, NULL, 0);
114+
#endif /* MCP_RECOVERY */
101115

102116
IOS_Close(mcpHandle);
103117
} else {

ios_mcp/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ LIBS := -lgcc
5555
ifeq ($(DC_INIT), 1)
5656
CFLAGS += -DDC_INIT
5757
endif
58+
ifeq ($(MCP_RECOVERY), 1)
59+
CFLAGS += -DMCP_RECOVERY
60+
SOURCES += source/mcp_recovery
61+
else
62+
SOURCES += source/mcp_normal
63+
endif
5864

5965
#---------------------------------------------------------------------------------
6066
# list of directories containing libraries, this must be the top level

ios_mcp/source/gfx.c

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
#include <stdio.h>
55
#include <stdarg.h>
66

7+
#ifdef MCP_RECOVERY
8+
// mcp_recovery does something different with framebuffer handling.
9+
// Only TV is usable; DRC isn't initialized.
10+
static uint32_t* framebuffer;
11+
static uint32_t width;
12+
static uint32_t height;
13+
#else /* !MCP_RECOVERY */
14+
715
static uint32_t* const TV_FRAMEBUFFER = (uint32_t*)(0x14000000 + 0x3500000);
816
#define TV_HEIGHT 720
917
#define TV_STRIDE 1280
@@ -12,6 +20,8 @@ static uint32_t* const DRC_FRAMEBUFFER = (uint32_t*)(0x14000000 + 0x38c0000);
1220
#define DRC_HEIGHT 480
1321
#define DRC_STRIDE 896
1422

23+
#endif /* MCP_RECOVERY */
24+
1525
#define CHAR_SIZE_TV_X 12
1626
#define CHAR_SIZE_TV_Y 24
1727

@@ -50,53 +60,90 @@ int gfx_init_font(void)
5060
return 0;
5161
}
5262

63+
#ifdef MCP_RECOVERY
64+
void gfx_init(void* fb, uint32_t w, uint32_t h)
65+
{
66+
framebuffer = (uint32_t*) fb;
67+
width = w;
68+
height = h;
69+
}
70+
#endif /* MCP_RECOVERY */
71+
5372
void gfx_clear(uint32_t col)
5473
{
55-
#ifdef DC_INIT
74+
#if defined(DC_INIT) || defined(MCP_RECOVERY)
5675
// both DC configurations use XRGB instead of RGBX
5776
col >>= 8;
58-
#endif
77+
#endif /* DC_INIT || MCP_RECOVERY */
5978

79+
#ifdef MCP_RECOVERY
80+
for (uint32_t i = 0; i < width * height; i++) {
81+
framebuffer[i] = col;
82+
}
83+
#else /* !MCP_RECOVERY */
6084
for (uint32_t i = 0; i < TV_STRIDE * TV_HEIGHT; i++) {
6185
TV_FRAMEBUFFER[i] = col;
6286
}
6387

6488
for (uint32_t i = 0; i < DRC_STRIDE * DRC_HEIGHT; i++) {
6589
DRC_FRAMEBUFFER[i] = col;
6690
}
91+
#endif /* MCP_RECOVERY */
6792
}
6893

6994
void gfx_draw_pixel(uint32_t x, uint32_t y, uint32_t col)
7095
{
71-
#ifdef DC_INIT
96+
#if defined(DC_INIT) || defined(MCP_RECOVERY)
7297
// both DC configurations use XRGB instead of RGBX
7398
col >>= 8;
74-
#endif
99+
#endif /* DC_INIT || MCP_RECOVERY */
75100

101+
#ifndef MCP_RECOVERY
76102
// put pixel in the drc buffer
77103
uint32_t i = x + y * DRC_STRIDE;
78104
if (i < DRC_STRIDE * DRC_HEIGHT) {
79105
DRC_FRAMEBUFFER[i] = col;
80106
}
107+
#endif /* !MCP_RECOVERY */
81108

82109
// scale and put pixel in the tv buffer
83110
for (uint32_t yy = (y * 1.5f); yy < ((y * 1.5f) + 1); yy++) {
84111
for (uint32_t xx = (x * 1.5f); xx < ((x * 1.5f) + 1); xx++) {
112+
#ifdef MCP_RECOVERY
113+
uint32_t i = xx + yy * width;
114+
if (i < width * height) {
115+
framebuffer[i] = col;
116+
}
117+
#else /* !MCP_RECOVERY */
85118
uint32_t i = xx + yy * TV_STRIDE;
86119
if (i < TV_STRIDE * TV_HEIGHT) {
87120
TV_FRAMEBUFFER[i] = col;
88121
}
122+
#endif /* MCP_RECOVERY */
89123
}
90124
}
91125
}
92126

93127
void gfx_draw_rect_filled(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t col)
94128
{
95-
#ifdef DC_INIT
129+
#if defined(DC_INIT) || defined(MCP_RECOVERY)
96130
// both DC configurations use XRGB instead of RGBX
97131
col >>= 8;
98-
#endif
132+
#endif /* DC_INIT || MCP_RECOVERY */
133+
134+
#ifdef MCP_RECOVERY
135+
// mcp_recovery: Using TV scale because mcp_recovery seems to have a
136+
// 1280x720 framebuffer, even though the output mode is usually 480p.
137+
uint32_t* p = framebuffer + ((uint32_t)(y * 1.5f) * width) + (uint32_t)(x * 1.5f);
138+
uint32_t stride_diff = width - (w * 1.5f);
99139

140+
for (uint32_t hcnt = (h * 1.5f); hcnt > 0; hcnt--) {
141+
for (uint32_t wcnt = (w * 1.5f); wcnt > 0; wcnt--) {
142+
*p++ = col;
143+
}
144+
p += stride_diff;
145+
}
146+
#else /* !MCP_RECOVERY */
100147
// DRC fill: normal scale
101148
uint32_t* p = DRC_FRAMEBUFFER + (y * DRC_STRIDE) + x;
102149
uint32_t stride_diff = DRC_STRIDE - w;
@@ -118,6 +165,7 @@ void gfx_draw_rect_filled(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32
118165
}
119166
p += stride_diff;
120167
}
168+
#endif /* MCP_RECOVERY */
121169
}
122170

123171
void gfx_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t borderSize, uint32_t col)
@@ -130,10 +178,10 @@ void gfx_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t bord
130178

131179
void gfx_set_font_color(uint32_t col)
132180
{
133-
#ifdef DC_INIT
181+
#if defined(DC_INIT) || defined(MCP_RECOVERY)
134182
// both DC configurations use XRGB instead of RGBX
135183
col >>= 8;
136-
#endif
184+
#endif /* DC_INIT || MCP_RECOVERY */
137185

138186
font_color = col;
139187
}
@@ -152,6 +200,25 @@ static void gfx_draw_char(uint32_t x, uint32_t y, char c)
152200
return;
153201
c -= 32;
154202

203+
#ifdef MCP_RECOVERY
204+
// mcp_recovery: Terminus 12x24 bold
205+
// Using TV scale because mcp_recovery seems to have a 1280x720
206+
// framebuffer, even though the output mode is usually 480p.
207+
const uint16_t* charMCP = font->ter_u24b[(unsigned char)c];
208+
uint32_t *p = framebuffer + ((uint32_t)(y * 1.5f) * width) + (uint32_t)(x * 1.5f);
209+
unsigned int stride_diff = width - CHAR_SIZE_TV_X;
210+
211+
for (uint32_t hcnt = CHAR_SIZE_TV_Y; hcnt > 0; hcnt--) {
212+
uint16_t v = *charMCP++;
213+
for (uint32_t wcnt = CHAR_SIZE_TV_X; wcnt > 0; wcnt--, v >>= 1) {
214+
if (v & 1) {
215+
*p = font_color;
216+
}
217+
p++;
218+
}
219+
p += stride_diff;
220+
}
221+
#else /* !MCP_RECOVERY */
155222
// DRC blit: Terminus 8x16 bold
156223
const uint8_t* charDRC = font->ter_u16b[(unsigned char)c];
157224
uint32_t *p = DRC_FRAMEBUFFER + (y * DRC_STRIDE) + x;
@@ -183,6 +250,7 @@ static void gfx_draw_char(uint32_t x, uint32_t y, char c)
183250
}
184251
p += stride_diff;
185252
}
253+
#endif /* !MCP_RECOVERY */
186254
}
187255

188256
/**

ios_mcp/source/gfx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121

2222
int gfx_init_font(void);
2323

24+
#ifdef MCP_RECOVERY
25+
void gfx_init(void* fb, uint32_t w, uint32_t h);
26+
#endif /* MCP_RECOVERY */
27+
2428
void gfx_clear(uint32_t color);
2529

2630
void gfx_draw_pixel(uint32_t x, uint32_t y, uint32_t color);
File renamed without changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include "imports.h"
2+
#include "menu.h"
3+
4+
#include <string.h>
5+
6+
static int threadStarted = 0;
7+
static uint8_t threadStack[0x1000] __attribute__((aligned(0x20)));
8+
9+
void* MCP_recovery_ioctl_memcpy_hook(void* dst, void* src, uint32_t size)
10+
{
11+
printf("MCP_recovery_ioctl_memcpy_hook\n");
12+
13+
// start the menu thread
14+
if (!threadStarted) {
15+
int tid = IOS_CreateThread(menuThread, NULL, threadStack + sizeof(threadStack), sizeof(threadStack), IOS_GetThreadPriority(0), 1);
16+
if (tid > 0) {
17+
IOS_StartThread(tid);
18+
}
19+
20+
threadStarted = 1;
21+
}
22+
23+
// perform the original copy
24+
return memcpy(dst, src, size);
25+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.extern MCP_recovery_ioctl_memcpy_hook
2+
.global _MCP_recovery_ioctl_memcpy_hook
3+
_MCP_recovery_ioctl_memcpy_hook:
4+
.thumb
5+
bx pc
6+
nop
7+
.arm
8+
ldr r12, =MCP_recovery_ioctl_memcpy_hook
9+
bx r12

ios_mcp/source/menu.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ int menuThread(void* arg)
368368
// Initialize utils
369369
initializeUtils();
370370

371-
#ifdef DC_INIT
371+
#if defined(DC_INIT)
372372
// (re-)init the graphics subsystem
373373
GFX_SubsystemInit(0);
374374

@@ -383,6 +383,17 @@ int menuThread(void* arg)
383383
Writing to the hardcoded addresses in gfx.c works for HDMI though */
384384
DC_Config dc_config;
385385
DISPLAY_ReadDCConfig(&dc_config);
386+
#elif defined(MCP_RECOVERY)
387+
// init display output (already initialized in recovery mode)
388+
DISPLAY_DCInit(DC_CONFIGURATION_1);
389+
390+
// MCP is doing something different in recovery mode to make display configuration work properly
391+
// this doesn't work usually
392+
DC_Config dc_config;
393+
DISPLAY_ReadDCConfig(&dc_config);
394+
395+
printf("DC Config: %p %ux%u\n", dc_config.framebuffer, dc_config.width, dc_config.height);
396+
gfx_init(dc_config.framebuffer, dc_config.width, dc_config.height);
386397
#endif
387398

388399
// initialize the font

0 commit comments

Comments
 (0)