#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;
*(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
*(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
*(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;
#include <ctr9/io.h>
#include <ctr9/ctr_screen.h>
+#include <ctr9/i2c.h>
+#include "common.h"
#include "std/fs.h"
#include "patch_format.h"
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);
- }
+// }
}
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;
#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);
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;
}
}
}
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);
}
}
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++)
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) {
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) {
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;
}
_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.
}
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;
}
}
}