Skip to content

Commit 7302105

Browse files
Merge pull request #130 from negativeExponent/updates1
Updates1
2 parents c3db5dc + 1877a48 commit 7302105

File tree

18 files changed

+1781
-1027
lines changed

18 files changed

+1781
-1027
lines changed

src/components/filters_agb/filters_agb.cpp

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,217 @@ void gbafilter_pal32(uint32_t* buf, int count)
332332
final_pix |= (final_red_8bit & 0x07) << (systemRedShift - 3);
333333

334334

335+
// Green component
336+
// 5 MSBs for the 'systemGreenShift' position
337+
final_pix |= ((final_green_8bit >> 3) & 0x1f) << systemGreenShift;
338+
// 3 LSBs for the 'base' position (systemGreenShift - 3)
339+
final_pix |= (final_green_8bit & 0x07) << (systemGreenShift - 3);
340+
341+
// Blue component
342+
// 5 MSBs for the 'systemBlueShift' position
343+
final_pix |= ((final_blue_8bit >> 3) & 0x1f) << systemBlueShift;
344+
// 3 LSBs for the 'base' position (systemBlueShift - 3)
345+
final_pix |= (final_blue_8bit & 0x07) << (systemBlueShift - 3);
346+
347+
// Preserve existing alpha if present (assuming it's at bits 24-31 for 32-bit depth)
348+
if (systemColorDepth == 32) {
349+
final_pix |= (pix & (0xFF << 24));
350+
}
351+
352+
*buf++ = final_pix;
353+
}
354+
}
355+
356+
void gbafilter_update_colors_native(bool lcd) {
357+
switch (systemColorDepth) {
358+
case 8: {
359+
for (int i = 0; i < 0x10000; i++) {
360+
systemColorMap8[i] = (uint8_t)((((i & 0x1f) << 3) & 0xE0) |
361+
((((i & 0x3e0) >> 5) << 0) & 0x1C) |
362+
((((i & 0x7c00) >> 10) >> 3) & 0x3));
363+
}
364+
if (lcd)
365+
gbafilter_pal8(systemColorMap8, 0x10000);
366+
} break;
367+
case 16: {
368+
#ifdef FRONTEND_SUPPORTS_BGR1555
369+
for (int i = 0x0; i < 0x10000; i++) {
370+
// GBA uses BGR555 format: 0BBBBBGGGGGRRRRR
371+
// Red: bits 0-4, Green: bits 5-9, Blue: bits 10-14
372+
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
373+
(((i & 0x3e0) >> 5) << systemGreenShift) |
374+
(((i & 0x7c00) >> 10) << systemBlueShift);
375+
}
376+
if (lcd)
377+
gbafilter_pal(systemColorMap16, 0x10000);
378+
#else
379+
for (int i = 0x0; i < 0x10000; i++) {
380+
// GBA uses BGR555 format: 0BBBBBGGGGGRRRRR
381+
// Red: bits 0-4, Green: bits 5-9, Blue: bits 10-14
382+
// GB/GBC uses BGR555 format: 0BBBBBGGGGGRRRRR
383+
// Red: bits 0-4, Green: bits 5-9, Blue: bits 10-14
384+
int r5 = i & 0x1F;
385+
int g5 = (i >> 5) & 0x1F;
386+
int b5 = (i >> 10) & 0x1F;
387+
388+
// Map to 16-bit RGB565 (5-6-5)
389+
int g6 = (g5 << 1) | (g5 >> 4);
390+
391+
systemColorMap16[i] =
392+
(r5 << systemRedShift) |
393+
(g6 << (systemGreenShift - 1)) |
394+
(b5 << systemBlueShift);
395+
}
396+
if (lcd)
397+
gbafilter_pal_565(systemColorMap16, 0x10000);
398+
#endif
399+
} break;
400+
case 24:
401+
case 32: {
402+
for (int i = 0; i < 0x10000; i++) {
403+
// GBA uses BGR555 format: 0BBBBBGGGGGRRRRR
404+
// Red: bits 0-4, Green: bits 5-9, Blue: bits 10-14
405+
int r5 = i & 0x1F;
406+
int g5 = (i >> 5) & 0x1F;
407+
int b5 = (i >> 10) & 0x1F;
408+
409+
// Expand 5-bit to 8-bit components
410+
uint8_t final_red_8bit = (r5 << 3) | (r5 >> 2);
411+
uint8_t final_green_8bit = (g5 << 3) | (g5 >> 2);
412+
uint8_t final_blue_8bit = (b5 << 3) | (b5 >> 2);
413+
414+
uint32_t final_pix = 0;
415+
416+
// Red component
417+
// 5 most significant bits (MSBs) for the 'systemRedShift' position
418+
final_pix |= ((final_red_8bit >> 3) & 0x1f) << systemRedShift;
419+
// 3 least significant bits (LSBs) for the 'base' position (systemRedShift - 3)
420+
final_pix |= (final_red_8bit & 0x07) << (systemRedShift - 3);
421+
422+
// Green component
423+
// 5 MSBs for the 'systemGreenShift' position
424+
final_pix |= ((final_green_8bit >> 3) & 0x1f) << systemGreenShift;
425+
// 3 LSBs for the 'base' position (systemGreenShift - 3)
426+
final_pix |= (final_green_8bit & 0x07) << (systemGreenShift - 3);
427+
428+
// Blue component
429+
// 5 MSBs for the 'systemBlueShift' position
430+
final_pix |= ((final_blue_8bit >> 3) & 0x1f) << systemBlueShift;
431+
// 3 LSBs for the 'base' position (systemBlueShift - 3)
432+
final_pix |= (final_blue_8bit & 0x07) << (systemBlueShift - 3);
433+
434+
systemColorMap32[i] = final_pix;
435+
}
436+
if (lcd)
437+
gbafilter_pal_888(systemColorMap32, 0x10000);
438+
} break;
439+
}
440+
}
441+
442+
#define APPLY_FILTER(r, g, b) \
443+
do { \
444+
/* 1. Apply initial gamma (including darken_screen as exponent) to convert to linear space. */ \
445+
/* This step will affect non-"white" values. */ \
446+
r = powf(r, target_gamma_exponent); \
447+
g = powf(g, target_gamma_exponent); \
448+
b = powf(b, target_gamma_exponent); \
449+
/* 2. Apply luminance factor and clamp. */ \
450+
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor)); \
451+
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor)); \
452+
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor)); \
453+
/* 3. Apply color profile matrix (using profile[column][row] access) */ \
454+
transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b; \
455+
transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b; \
456+
transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b; \
457+
/* 4. Apply display gamma to convert back for display. */ \
458+
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r); \
459+
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g); \
460+
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b); \
461+
/* Final clamp: ensure values are within 0.0-1.0 range */ \
462+
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r)); \
463+
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g)); \
464+
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b)); \
465+
} while(0)
466+
467+
468+
void gbafilter_pal_565(uint16_t* buf, int count)
469+
{
470+
// Pre-calculate constants for efficiency within function scope
471+
const float target_gamma_exponent = target_gamma + darken_screen;
472+
const float display_gamma_reciprocal = 1.0f / display_gamma;
473+
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
474+
475+
while (count--) {
476+
float transformed_r, transformed_g, transformed_b;
477+
uint16_t pix = *buf;
478+
479+
uint8_t original_r_val_5bit = (uint8_t)((pix >> systemRedShift) & 0x1f);
480+
uint8_t original_g_val_6bit = (uint8_t)((pix >> (systemGreenShift - 1)) & 0x3f);
481+
uint8_t original_b_val_5bit = (uint8_t)((pix >> systemBlueShift) & 0x1f);
482+
483+
// Normalize to 0.0-1.0 for calculations
484+
float r = (float)original_r_val_5bit / 31.0f;
485+
float g = (float)original_g_val_6bit / 63.0f;
486+
float b = (float)original_b_val_5bit / 31.0f;
487+
488+
APPLY_FILTER(r, g, b);
489+
490+
// Convert back to 5-bit (0-31) integer and combine into uint16_t
491+
// Apply 5-bit to 5-bit conversion, as this palette is for 16-bit output.
492+
uint8_t final_red = (uint8_t)(transformed_r * 31.0f + 0.5f);
493+
uint8_t final_green = (uint8_t)(transformed_g * 63.0f + 0.5f);
494+
uint8_t final_blue = (uint8_t)(transformed_b * 31.0f + 0.5f);
495+
496+
// Ensure values are strictly within 0-31 range after rounding
497+
if (final_red > 31) final_red = 31;
498+
if (final_green > 63) final_green = 63;
499+
if (final_blue > 31) final_blue = 31;
500+
501+
*buf++ = (final_red << systemRedShift) |
502+
(final_green << (systemGreenShift - 1)) |
503+
(final_blue << systemBlueShift);
504+
}
505+
}
506+
507+
void gbafilter_pal_888(uint32_t* buf, int count)
508+
{
509+
// Pre-calculate constants for efficiency within function scope
510+
const float target_gamma_exponent = target_gamma + darken_screen;
511+
const float display_gamma_reciprocal = 1.0f / display_gamma;
512+
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
513+
514+
while (count--) {
515+
float transformed_r, transformed_g, transformed_b;
516+
uint32_t pix = *buf;
517+
518+
// Extract original 5-bit R, G, B values from the shifted positions in the 32-bit pixel.
519+
// These shifts pull out the 5-bit value from its shifted position (e.g., bits 3-7 for Red).
520+
uint8_t original_r_val_8bit = (uint8_t)((pix >> (systemRedShift - 3)) & 0xff);
521+
uint8_t original_g_val_8bit = (uint8_t)((pix >> (systemGreenShift - 3)) & 0xff);
522+
uint8_t original_b_val_8bit = (uint8_t)((pix >> (systemBlueShift - 3)) & 0xff);
523+
524+
// Normalize to 0.0-1.0 for calculations
525+
float r = (float)original_r_val_8bit / 255.0f;
526+
float g = (float)original_g_val_8bit / 255.0f;
527+
float b = (float)original_b_val_8bit / 255.0f;
528+
529+
APPLY_FILTER(r, g, b);
530+
531+
// Convert the floating-point values to 8-bit integer components (0-255).
532+
// Values are already guaranteed to be in 0-255 range since they are uint8_t
533+
// and the floating point values are clamped to 0.0-1.0 before conversion.
534+
uint8_t final_red_8bit = (uint8_t)(transformed_r * 255.0f + 0.5f);
535+
uint8_t final_green_8bit = (uint8_t)(transformed_g * 255.0f + 0.5f);
536+
uint8_t final_blue_8bit = (uint8_t)(transformed_b * 255.0f + 0.5f);
537+
538+
uint32_t final_pix = 0;
539+
540+
// Red component
541+
// 5 most significant bits (MSBs) for the 'systemRedShift' position
542+
final_pix |= ((final_red_8bit >> 3) & 0x1f) << systemRedShift;
543+
// 3 least significant bits (LSBs) for the 'base' position (systemRedShift - 3)
544+
final_pix |= (final_red_8bit & 0x07) << (systemRedShift - 3);
545+
335546
// Green component
336547
// 5 MSBs for the 'systemGreenShift' position
337548
final_pix |= ((final_green_8bit >> 3) & 0x1f) << systemGreenShift;

src/components/filters_agb/filters_agb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ void gbafilter_pal(uint16_t* buf, int count);
99
void gbafilter_pal32(uint32_t* buf, int count);
1010
void gbafilter_set_params(int color_mode, float darken_screen);
1111

12+
void gbafilter_update_colors_native(bool lcd = false);
13+
void gbafilter_pal_565(uint16_t* buf, int count);
14+
void gbafilter_pal_888(uint32_t* buf, int count);
15+
1216
#endif // VBAM_COMPONENTS_FILTERS_AGB_FILTERS_AGB_H_

0 commit comments

Comments
 (0)