Edge enhancement support

This commit is contained in:
Lior Halphon 2016-10-03 19:39:20 +03:00
parent 8941504863
commit 2d06599a85
2 changed files with 47 additions and 15 deletions

View File

@ -1,5 +1,37 @@
#include "camera.h" #include "camera.h"
/* This is not a completely emulation of the camera chip. Only the features used by the GameBoy Camera ROMs are supported. */
static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y)
{
if (x >= 128) {
x = 0;
}
if (y >= 112) {
y = 0;
}
long color = gb->camera_get_pixel_callback? gb->camera_get_pixel_callback(gb, x, y) : (rand() & 0xFF);
static const double gain_values[] = {0.8809390, 0.9149149, 0.9457498, 0.9739758,
1.0000000, 1.0241412, 1.0466537, 1.0677433,
1.0875793, 1.1240310, 1.1568911, 1.1868043,
1.2142561, 1.2396208, 1.2743837, 1.3157323,
1.3525190, 1.3856512, 1.4157897, 1.4434309,
1.4689574, 1.4926697, 1.5148087, 1.5355703,
1.5551159, 1.5735801, 1.5910762, 1.6077008,
1.6235366, 1.6386550, 1.6531183, 1.6669808};
/* Multiply color by gain value */
color *= gain_values[gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0x1F];
/* Color is multiplied by the exposure register to simulate exposure. */
color = color * ((gb->camera_registers[GB_CAMERA_EXPOSURE_HIGH] << 8) + gb->camera_registers[GB_CAMERA_EXPOSURE_LOW]) / 0x1000;
return color;
}
uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr) uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr)
{ {
if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) { if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) {
@ -14,25 +46,24 @@ uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr)
uint8_t ret = 0; uint8_t ret = 0;
/* This is not a complete emulation of the chip's image proccessing algorithm, it only emulates the features used by
the actual GameBoy Camera ROM. */
for (uint8_t x = tile_x * 8; x < tile_x * 8 + 8; x++) { for (uint8_t x = tile_x * 8; x < tile_x * 8 + 8; x++) {
long color = gb->camera_get_pixel_callback? gb->camera_get_pixel_callback(gb, x,y) : (rand() & 0xFF); long color = get_processed_color(gb, x, y);
static const double gain_values[] = {0.8809390, 0.9149149, 0.9457498, 0.9739758, static const double edge_enhancement_ratios[] = {0.5, 0.75, 1, 1.25, 2, 3, 4, 5};
1.0000000, 1.0241412, 1.0466537, 1.0677433, double edge_enhancement_ratio = edge_enhancement_ratios[(gb->camera_registers[GB_CAMERA_EDGE_ENHANCEMENT_INVERT_AND_VOLTAGE] >> 4) & 0x7];
1.0875793, 1.1240310, 1.1568911, 1.1868043, if ((gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0xE0) == 0xE0) {
1.2142561, 1.2396208, 1.2743837, 1.3157323, color += (color * 4) * edge_enhancement_ratio;
1.3525190, 1.3856512, 1.4157897, 1.4434309, color -= get_processed_color(gb, x - 1, y) * edge_enhancement_ratio;
1.4689574, 1.4926697, 1.5148087, 1.5355703, color -= get_processed_color(gb, x + 1, y) * edge_enhancement_ratio;
1.5551159, 1.5735801, 1.5910762, 1.6077008, color -= get_processed_color(gb, x, y - 1) * edge_enhancement_ratio;
1.6235366, 1.6386550, 1.6531183, 1.6669808}; color -= get_processed_color(gb, x, y + 1) * edge_enhancement_ratio;
/* Multiply color by gain value */ }
color *= gain_values[gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENCHANCEMENT_FLAGS] & 0x1F];
/* Color is multiplied by the exposure register to simulate exposure. */
color = color * ((gb->camera_registers[GB_CAMERA_EXPOSURE_HIGH] << 8) + gb->camera_registers[GB_CAMERA_EXPOSURE_LOW]) / 0x1000;
/* The camera's registers are used as a threshold pattern, which defines the dithering */ /* The camera's registers are used as a threshold pattern, which defines the dithering */
uint8_t pattern_base = ((x & 3) + (y & 3) * 4) * 3 + GB_CAMERA_DITHERING_PATTERN_START; uint8_t pattern_base = ((x & 3) + (y & 3) * 4) * 3 + GB_CAMERA_DITHERING_PATTERN_START;

View File

@ -4,9 +4,10 @@
enum { enum {
GB_CAMERA_SHOOT_AND_1D_FLAGS = 0, GB_CAMERA_SHOOT_AND_1D_FLAGS = 0,
GB_CAMERA_GAIN_AND_EDGE_ENCHANCEMENT_FLAGS = 1, GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS = 1,
GB_CAMERA_EXPOSURE_HIGH = 2, GB_CAMERA_EXPOSURE_HIGH = 2,
GB_CAMERA_EXPOSURE_LOW = 3, GB_CAMERA_EXPOSURE_LOW = 3,
GB_CAMERA_EDGE_ENHANCEMENT_INVERT_AND_VOLTAGE = 4,
GB_CAMERA_DITHERING_PATTERN_START = 6, GB_CAMERA_DITHERING_PATTERN_START = 6,
GB_CAMERA_DITHERING_PATTERN_END = 0x35, GB_CAMERA_DITHERING_PATTERN_END = 0x35,
}; };