The camera's get pixel callback must return the same value for every coordinate until a new photo is taken.

This commit is contained in:
Lior Halphon 2016-10-03 23:05:47 +03:00
parent 2d06599a85
commit 90b7383df7
2 changed files with 33 additions and 14 deletions

View File

@ -766,7 +766,7 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
- (uint8_t)cameraGetPixelAtX:(uint8_t)x andY:(uint8_t) y - (uint8_t)cameraGetPixelAtX:(uint8_t)x andY:(uint8_t) y
{ {
if (!cameraImage) { if (!cameraImage) {
return rand(); return 0;
} }
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(cameraImage); uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(cameraImage);

View File

@ -1,7 +1,27 @@
#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 int noise_seed = 0;
/* This is not a complete emulation of the camera chip. Only the features used by the GameBoy Camera ROMs are supported.
We also do not emulate the timing of the real cart, as it might be actually faster than the webcam. */
static uint8_t generate_noise(uint8_t x, uint8_t y)
{
int value = (x + y * 128 + noise_seed);
uint8_t *data = (uint8_t *) &value;
unsigned hash;
while ((int *) data != &value + 1) {
hash ^= (*data << 8);
if (hash & 0x8000) {
hash ^= 0x8a00;
hash ^= *data;
}
data++;
hash <<= 1;
}
return (hash >> 8);
}
static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y) static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y)
{ {
@ -12,16 +32,17 @@ static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y)
y = 0; y = 0;
} }
long color = gb->camera_get_pixel_callback? gb->camera_get_pixel_callback(gb, x, y) : (rand() & 0xFF); long color = gb->camera_get_pixel_callback? gb->camera_get_pixel_callback(gb, x, y) : (generate_noise(x, y));
static const double gain_values[] = {0.8809390, 0.9149149, 0.9457498, 0.9739758, static const double gain_values[] =
1.0000000, 1.0241412, 1.0466537, 1.0677433, {0.8809390, 0.9149149, 0.9457498, 0.9739758,
1.0875793, 1.1240310, 1.1568911, 1.1868043, 1.0000000, 1.0241412, 1.0466537, 1.0677433,
1.2142561, 1.2396208, 1.2743837, 1.3157323, 1.0875793, 1.1240310, 1.1568911, 1.1868043,
1.3525190, 1.3856512, 1.4157897, 1.4434309, 1.2142561, 1.2396208, 1.2743837, 1.3157323,
1.4689574, 1.4926697, 1.5148087, 1.5355703, 1.3525190, 1.3856512, 1.4157897, 1.4434309,
1.5551159, 1.5735801, 1.5910762, 1.6077008, 1.4689574, 1.4926697, 1.5148087, 1.5355703,
1.6235366, 1.6386550, 1.6531183, 1.6669808}; 1.5551159, 1.5735801, 1.5910762, 1.6077008,
1.6235366, 1.6386550, 1.6531183, 1.6669808};
/* Multiply color by gain value */ /* Multiply color by gain value */
color *= gain_values[gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0x1F]; color *= gain_values[gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0x1F];
@ -46,9 +67,6 @@ 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 = get_processed_color(gb, x, y); long color = get_processed_color(gb, x, y);
@ -107,6 +125,7 @@ void GB_camera_write_register(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
addr &= 0x7F; addr &= 0x7F;
if (addr == GB_CAMERA_SHOOT_AND_1D_FLAGS) { if (addr == GB_CAMERA_SHOOT_AND_1D_FLAGS) {
value &= 0x7; value &= 0x7;
noise_seed = rand();
if ((value & 1) && !(gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) && gb->camera_update_request_callback) { if ((value & 1) && !(gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) && gb->camera_update_request_callback) {
/* If no callback is set, ignore the write as if the camera is instantly done */ /* If no callback is set, ignore the write as if the camera is instantly done */
gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] |= 1; gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] |= 1;