From 3519ba0d082e73ff3f82c8e839bd05450f7a869b Mon Sep 17 00:00:00 2001 From: root Date: Sat, 16 Jul 2016 21:57:08 -0400 Subject: [PATCH] Multiple again: * Fix #26 * Initialize in RGBA8 mode - I want that alpha channel. * (bug) Screeninit seems to produce screwed up results when partially done. Or I'm doing it wrong. For now, I force a screeninit on all systems. * Fix up drawing functions for RGBA8. * Use a precomputed table for the dimmer. This improves performance somewhat. --- external/screeninit/source/main.c | 58 +++++++++-- external/screeninit/source/start.s | 6 +- external/screeninit/source/types.h | 7 +- source/chain.c | 3 + source/main.c | 2 +- source/screeninit.c | 34 ++++-- source/screeninit.h | 2 +- source/std/draw.c | 159 ++++++++++++----------------- source/std/draw.h | 2 +- 9 files changed, 155 insertions(+), 118 deletions(-) diff --git a/external/screeninit/source/main.c b/external/screeninit/source/main.c index 318911a..932cb7e 100755 --- a/external/screeninit/source/main.c +++ b/external/screeninit/source/main.c @@ -1,12 +1,43 @@ #include "types.h" -void main(void) -{ +#define FB_FMT(col, plx, screen) ((col & 0b111) | ((plx & 1) << 5) | ((screen & 1) << 6) | 0b10000000001100000000) + +#define RGBA8 0 +#define BGR8 1 +#define RGB565_OES 2 +#define RGB5_A1_OES 3 +#define RGBA4_OES 4 + +#define INIT_FULL 0 +#define INIT_PARAMS 1 +#define INIT_DEINIT 2 + +void main(void) { // FIXME - We could use some serious macros here... - u32 brightnessLevel = *(vu32 *)0x24FFFC08; + u32 do_init = *(vu32 *)0x24FFFC08; + u32 brightnessLevel = *(vu32 *)0x24FFFC0C; + u32 mode = *(vu32 *)0x24FFFC10; + + u32 yaw, init_top, init_bottom; + switch(mode) { + case RGBA8: + yaw = 240 * 4; + break; + case BGR8: + case RGB565_OES: + case RGB5_A1_OES: + case RGBA4_OES: + yaw = 240 * 3; + break; + } + + init_top = FB_FMT(mode, 0, 1); + init_bottom = FB_FMT(mode, 0, 0); + vu32 *const arm11 = (u32 *)0x1FFFFFF8; + if (do_init == INIT_FULL) { *(vu32 *)0x10141200 = 0x1007F; *(vu32 *)0x10202014 = 0x00000001; *(vu32 *)0x1020200C &= 0xFFFEFFFE; @@ -35,14 +66,15 @@ void main(void) *(vu32 *)0x10400440 = 0x01960192; *(vu32 *)0x10400444 = 0x00000000; *(vu32 *)0x10400448 = 0x00000000; + *(vu32 *)0x1040045C = 0x00f00190; *(vu32 *)0x10400460 = 0x01c100d1; *(vu32 *)0x10400464 = 0x01920002; *(vu32 *)0x10400468 = 0x18300000; - *(vu32 *)0x10400470 = 0x80341; + *(vu32 *)0x10400470 = init_top; // Format *(vu32 *)0x10400474 = 0x00010501; *(vu32 *)0x10400478 = 0; - *(vu32 *)0x10400490 = 0x000002D0; + *(vu32 *)0x10400490 = yaw; *(vu32 *)0x1040049C = 0x00000000; // Disco register @@ -69,14 +101,15 @@ void main(void) *(vu32 *)0x10400540 = 0x01980194; *(vu32 *)0x10400544 = 0x00000000; *(vu32 *)0x10400548 = 0x00000011; + *(vu32 *)0x1040055C = 0x00f00140; *(vu32 *)0x10400560 = 0x01c100d1; *(vu32 *)0x10400564 = 0x01920052; - *(vu32 *)0x10400568 = 0x18300000 + 0x46500; - *(vu32 *)0x10400570 = 0x80301; + *(vu32 *)0x10400568 = 0x18300000 + (yaw * 400); + *(vu32 *)0x10400570 = init_bottom; // Format *(vu32 *)0x10400574 = 0x00010501; *(vu32 *)0x10400578 = 0; - *(vu32 *)0x10400590 = 0x000002D0; + *(vu32 *)0x10400590 = yaw; *(vu32 *)0x1040059C = 0x00000000; // Disco register @@ -87,13 +120,16 @@ void main(void) *(vu32 *)0x1040046c = 0x18300000; *(vu32 *)0x10400494 = 0x18300000; *(vu32 *)0x10400498 = 0x18300000; - *(vu32 *)0x10400568 = 0x18346500; - *(vu32 *)0x1040056c = 0x18346500; + *(vu32 *)0x10400568 = 0x18300000 + (yaw * 400); + *(vu32 *)0x1040056c = 0x18300000 + (yaw * 400); //Set CakeBrah framebuffers *((vu32 *)0x23FFFE00) = 0x18300000; *((vu32 *)0x23FFFE04) = 0x18300000; - *((vu32 *)0x23FFFE08) = 0x18346500; + *((vu32 *)0x23FFFE08) = 0x18300000 + (yaw * 400); + } else if (do_init == INIT_DEINIT) { + + } //Clear ARM11 entry offset *arm11 = 0; diff --git a/external/screeninit/source/start.s b/external/screeninit/source/start.s index 40392d1..1ce301b 100644 --- a/external/screeninit/source/start.s +++ b/external/screeninit/source/start.s @@ -2,9 +2,11 @@ .align 4 .global _start _start: - @ Disable interrupts + // Disable interrupts CPSID aif b main - .word 0 +do_init_or_deinit: .int 0 +brightness: .int 0 +mode: .int 0 diff --git a/external/screeninit/source/types.h b/external/screeninit/source/types.h index d27412b..f47ac07 100755 --- a/external/screeninit/source/types.h +++ b/external/screeninit/source/types.h @@ -10,4 +10,9 @@ typedef uint64_t u64; typedef volatile u8 vu8; typedef volatile u16 vu16; typedef volatile u32 vu32; -typedef volatile u64 vu64; \ No newline at end of file +typedef volatile u64 vu64; + +extern int do_init_or_deinit; +extern int brightness; +extern int mode; +extern int brightness; diff --git a/source/chain.c b/source/chain.c index 4efa517..6f95a24 100644 --- a/source/chain.c +++ b/source/chain.c @@ -1,6 +1,7 @@ #if defined(CHAINLOADER) && CHAINLOADER == 1 #include "common.h" +#include "screeninit.h" #include "firm/firm.h" #include "firm/headers.h" @@ -67,6 +68,8 @@ void chainload_file(char* chain_file_data) { fprintf(stderr, "Chaining to copy payload...\n"); + screen_mode(1); // TODO - Because RGBA8 screeninit is non-standard...ugh + ((void(*)(void*, uint32_t))0x24F00000)(chain_data, size + 256 + 8); // Size of payload + argv. } diff --git a/source/main.c b/source/main.c index 8a5316e..172d1fc 100644 --- a/source/main.c +++ b/source/main.c @@ -23,7 +23,7 @@ main(int argc, char** argv) std_init(); int c = fmount(); - screen_init(); + screen_mode(0); clear_bg(); load_bg_top(PATH_BITS "/top.bin"); load_bg_bottom(PATH_BITS "/bottom.bin"); // This is basically a menuhax splash (90deg rotated BGR8 pixel data) diff --git a/source/screeninit.c b/source/screeninit.c index 42689fc..1108ff1 100644 --- a/source/screeninit.c +++ b/source/screeninit.c @@ -1,5 +1,7 @@ #include #include +#include +#include "common.h" #include "std/fs.h" #include "patch_format.h" @@ -8,22 +10,36 @@ static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8; void -screen_init() +screen_mode(uint32_t mode) { - if (PDN_GPU_CNT == 1) { - uint32_t *screenInitAddress = (uint32_t *)0x24FFFC00; + uint32_t *screenInitAddress = (uint32_t *)0x24FFFC00; - FILE *f = fopen(PATH_SCREENINIT_CODE, "r"); - fread(screenInitAddress, 1, fsize(f), f); // Read in the screeninit payload. - fclose(f); + FILE *f = fopen(PATH_SCREENINIT_CODE, "r"); + fread(screenInitAddress, 1, fsize(f), f); // Read in the screeninit payload. + fclose(f); + + // FIXME - At the moment, this seems mandatory to do full screeninit. + + // I get very fucked up results from just changing the framebuffer offsets + // and display color mode. Until I figure out WHY a full screeninit has to + // be performed, I have to do a full screeninit. + + // And no, 3dbrew didn't help. Partial init seems to be a superset of what + // I was attempting. + +// if (PDN_GPU_CNT == 1) { + screenInitAddress[2] = 0; // Do a full init. + screenInitAddress[3] = 0xFF; // Brightness + screenInitAddress[4] = mode; // Mode - // Write brightness level for the stub to pick up - screenInitAddress[2] = 0x5F; *a11_entry = (uint32_t)screenInitAddress; while (*a11_entry); // Turn on backlight + i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 1); + + // FIXME - Time to yell at Gelex now. :| ctr_screen_enable_backlight(CTR_SCREEN_BOTH); - } +// } } diff --git a/source/screeninit.h b/source/screeninit.h index 5105774..c616844 100644 --- a/source/screeninit.h +++ b/source/screeninit.h @@ -2,6 +2,6 @@ #define __SCREENINIT_H // Inits the screen if needed. -void screen_init(); +void screen_mode(uint32_t mode); #endif diff --git a/source/std/draw.c b/source/std/draw.c index d2c7ae5..b5f8864 100644 --- a/source/std/draw.c +++ b/source/std/draw.c @@ -30,9 +30,6 @@ static unsigned int text_top_height = 10; static unsigned int text_bottom_width = 20; static unsigned int text_bottom_height = 10; -static int dim_factor_top = 0; -static int dim_factor_bottom = 0; - uint8_t *top_bg; uint8_t *bottom_bg; @@ -42,7 +39,15 @@ int kill_output = 0; #define TRANSP_THRESH 178 +static uint8_t alphamap[256] = {0}; + void std_init() { + for(uint16_t i=0; i < 0x100; i++) { + alphamap[i] = 0; + if (i > 0x7F) + alphamap[i] = i - 0x7F; + } + top_bg = static_allocate(TOP_SIZE); bottom_bg = static_allocate(BOTTOM_SIZE); log_buffer = static_allocate(LOG_BUFFER_SIZE); @@ -86,9 +91,10 @@ void rect(void* channel, int x, int y, int x2, int y2, uint8_t color) { int yDisplacement = ((height - y_a - 1) * SCREEN_DEPTH); int pos = xDisplacement + yDisplacement; - screen[pos] = colors[color & 0xF]; - screen[pos + 1] = colors[color & 0xF] >> 8; - screen[pos + 2] = colors[color & 0xF] >> 16; + screen[pos + 1] = colors[color & 0xF]; + screen[pos + 2] = colors[color & 0xF] >> 8; + screen[pos + 3] = colors[color & 0xF] >> 16; + screen[pos] = 0xFF; } } } @@ -120,9 +126,9 @@ void screenshot() { int yDisplacement = ((240 - y - 1) * SCREEN_DEPTH); int pos = xDisplacement + yDisplacement; + fwrite(& framebuffers->top_left[pos + 3], 1, 1, f); fwrite(& framebuffers->top_left[pos + 2], 1, 1, f); fwrite(& framebuffers->top_left[pos + 1], 1, 1, f); - fwrite(& framebuffers->top_left[pos], 1, 1, f); } } @@ -137,9 +143,9 @@ void screenshot() { int yDisplacement = ((240 - y - 1) * SCREEN_DEPTH); int pos = xDisplacement + yDisplacement; + fwrite(& framebuffers->bottom[pos + 3], 1, 1, f); fwrite(& framebuffers->bottom[pos + 2], 1, 1, f); fwrite(& framebuffers->bottom[pos + 1], 1, 1, f); - fwrite(& framebuffers->bottom[pos], 1, 1, f); } for (int i = 0; i < 40 * 3; i++) @@ -163,18 +169,6 @@ void load_bg_top(char* fname_top) { fread(top_bg, 1, TOP_SIZE, f); fclose(f); - - // TODO - Needs finetuning. Median color intensity isn't exactly accurate. - int max = 0; - for(int i=0; i < TOP_SIZE; i++) { - if (max < top_bg[i]) - max = top_bg[i]; - } - - // See load_bg_bottom for an explanation on the magic value. - dim_factor_top = 0; - if (max > TRANSP_THRESH) - dim_factor_top = max - TRANSP_THRESH; } void load_bg_bottom(char* fname_bottom) { @@ -184,23 +178,6 @@ void load_bg_bottom(char* fname_bottom) { fread(bottom_bg, 1, BOTTOM_SIZE, f); fclose(f); - - // TODO - Needs finetuning. Median color intensity isn't exactly accurate. - // It's good enough for right now, though. - int max = 0; - for(int i=0; i < BOTTOM_SIZE; i++) { - if (max < bottom_bg[i]) - max = bottom_bg[i]; - } - - // Why 178? Quick explanation: - // A pixel color channel is 255 at absolute white here. - // The minimum transparency with pure black overlay (I find) is 70% to be readable. - // 70% of 255 is approximately 178, and 255 - 178 is 77. That's therefore the maximum we want to subtract. - // Thus this is the value for 70% transparency. - dim_factor_bottom = 0; - if (max > TRANSP_THRESH) - dim_factor_bottom = max - TRANSP_THRESH; } void set_font(const char* filename) { @@ -263,27 +240,33 @@ clear_disp(uint8_t *screen) screen = framebuffers->bottom; if (screen == framebuffers->top_left || screen == framebuffers->top_right) { - if (kill_output || !config.options[OPTION_DIM_MODE]) { - memcpy(screen, top_bg, TOP_SIZE); - } else { - for(int i=0; i < TOP_SIZE; i++) { - screen[i] = 0; - if (top_bg[i] > dim_factor_top) - screen[i] = top_bg[i] - dim_factor_top; + for(int i=0, j=0; j < TOP_SIZE; i += 3, j += 4) { + screen[j] = 0xFF; + screen[j + 1] = top_bg[i]; + screen[j + 2] = top_bg[i + 1]; + screen[j + 3] = top_bg[i + 2]; + if (!kill_output && config.options[OPTION_DIM_MODE]) { + screen[j + 1] = alphamap[screen[j + 1]]; + screen[j + 2] = alphamap[screen[j + 2]]; + screen[j + 3] = alphamap[screen[j + 3]]; } } + top_cursor_x = 0; top_cursor_y = 0; } else if (screen == framebuffers->bottom) { - if (kill_output || !config.options[OPTION_DIM_MODE]) { - memcpy(screen, bottom_bg, BOTTOM_SIZE); - } else { - for(int i=0; i < BOTTOM_SIZE; i++) { - screen[i] = 0; - if (bottom_bg[i] >= dim_factor_bottom) - screen[i] = bottom_bg[i] - dim_factor_bottom; + for(int i=0, j=0; j < BOTTOM_SIZE; i += 3, j += 4) { + screen[j] = 0x7F; + screen[j + 1] = bottom_bg[i]; + screen[j + 2] = bottom_bg[i + 1]; + screen[j + 3] = bottom_bg[i + 2]; + if (!kill_output && config.options[OPTION_DIM_MODE]) { + screen[j + 1] = alphamap[screen[j + 1]]; + screen[j + 2] = alphamap[screen[j + 2]]; + screen[j + 3] = alphamap[screen[j + 3]]; } } + bottom_cursor_x = 0; bottom_cursor_y = 0; } @@ -310,17 +293,14 @@ draw_character(uint8_t *screen, const uint32_t character, int ch_x, int ch_y, co _UNUSED int width = 0; int height = 0; uint8_t* buffer_bg; - int dim_factor; if (screen == framebuffers->top_left || screen == framebuffers->top_right) { width = TOP_WIDTH; height = TOP_HEIGHT; buffer_bg = top_bg; - dim_factor = dim_factor_top; } else if (screen == framebuffers->bottom) { width = BOTTOM_WIDTH; height = BOTTOM_HEIGHT; buffer_bg = bottom_bg; - dim_factor = dim_factor_bottom; } else { return; // Invalid buffer. } @@ -334,59 +314,54 @@ draw_character(uint8_t *screen, const uint32_t character, int ch_x, int ch_y, co unsigned int c_font_w = (font_w / 8) + (font_w % 8 ? 1 : 0); for (unsigned int yy = 0; yy < font_h; yy++) { - int xDisplacement = (x * SCREEN_DEPTH * height); - int yDisplacement = ((height - (y + yy) - 1) * SCREEN_DEPTH); - unsigned int pos = xDisplacement + yDisplacement; + int xDisplacement = (x * SCREEN_DEPTH * height); + int yDisplacement = ((height - (y + yy) - 1) * SCREEN_DEPTH); + unsigned int pos = xDisplacement + yDisplacement; + + int xDisplacementBg = (x * 3 * height); + int yDisplacementBg = ((height - (y + yy) - 1) * 3); + unsigned int pos_b = xDisplacementBg + yDisplacementBg; + unsigned char char_dat = ((char*)FCRAM_FONT_LOC)[(character - ' ') * (c_font_w * font_h) + yy]; + for(unsigned int i=0; i < font_w + font_kern; i++) { + screen[pos] = 0xFF; + if (color_bg == 0) { - if (!config.options[OPTION_DIM_MODE]) { - screen[pos] = buffer_bg[pos]; - screen[pos + 1] = buffer_bg[pos + 1]; - screen[pos + 2] = buffer_bg[pos + 2]; - } else { - screen[pos] = 0; - screen[pos + 1] = 0; - screen[pos + 2] = 0; - if (buffer_bg[pos] >= dim_factor) - screen[pos] = buffer_bg[pos] - dim_factor; - if (buffer_bg[pos + 1] >= dim_factor) - screen[pos + 1] = buffer_bg[pos + 1] - dim_factor; - if (buffer_bg[pos + 2] >= dim_factor) - screen[pos + 2] = buffer_bg[pos + 2] - dim_factor; + screen[pos + 1] = buffer_bg[pos_b]; + screen[pos + 2] = buffer_bg[pos_b + 1]; + screen[pos + 3] = buffer_bg[pos_b + 2]; + if (config.options[OPTION_DIM_MODE]) { + screen[pos + 1] = alphamap[screen[pos + 1]]; + screen[pos + 2] = alphamap[screen[pos + 2]]; + screen[pos + 3] = alphamap[screen[pos + 3]]; } } else { - screen[pos] = color_bg; - screen[pos + 1] = color_bg >> 8; - screen[pos + 2] = color_bg >> 16; + screen[pos + 1] = color_bg; + screen[pos + 2] = color_bg >> 8; + screen[pos + 3] = color_bg >> 16; } if (char_dat & 0x80) { if (color_fg == 0) { - if (!config.options[OPTION_DIM_MODE]) { - screen[pos] = buffer_bg[pos]; - screen[pos + 1] = buffer_bg[pos + 1]; - screen[pos + 2] = buffer_bg[pos + 2]; - } else { - screen[pos] = 0; - screen[pos + 1] = 0; - screen[pos + 2] = 0; - if (buffer_bg[pos] >= dim_factor) - screen[pos] = buffer_bg[pos] - dim_factor; - if (buffer_bg[pos + 1] >= dim_factor) - screen[pos + 1] = buffer_bg[pos + 1] - dim_factor; - if (buffer_bg[pos + 2] >= dim_factor) - screen[pos + 2] = buffer_bg[pos + 2] - dim_factor; + screen[pos + 1] = buffer_bg[pos_b]; + screen[pos + 2] = buffer_bg[pos_b + 1]; + screen[pos + 3] = buffer_bg[pos_b + 2]; + if (config.options[OPTION_DIM_MODE]) { + screen[pos + 1] = alphamap[screen[pos + 1]]; + screen[pos + 2] = alphamap[screen[pos + 2]]; + screen[pos + 3] = alphamap[screen[pos + 3]]; } } else { - screen[pos] = color_fg; - screen[pos + 1] = color_fg >> 8; - screen[pos + 2] = color_fg >> 16; + screen[pos + 1] = color_fg; + screen[pos + 2] = color_fg >> 8; + screen[pos + 3] = color_fg >> 16; } } char_dat <<= 1; - pos += SCREEN_DEPTH * height; + pos += SCREEN_DEPTH * height; + pos_b += 3 * height; } } } diff --git a/source/std/draw.h b/source/std/draw.h index fb2b451..28b7ef9 100644 --- a/source/std/draw.h +++ b/source/std/draw.h @@ -13,7 +13,7 @@ #define BOTTOM_WIDTH 320 #define BOTTOM_HEIGHT 240 -#define SCREEN_DEPTH 3 +#define SCREEN_DEPTH 4 #define TOP_SIZE (TOP_WIDTH * TOP_HEIGHT * SCREEN_DEPTH) #define BOTTOM_SIZE (BOTTOM_WIDTH * BOTTOM_HEIGHT * SCREEN_DEPTH) -- 2.39.5