mirror of https://github.com/LIJI32/SameBoy.git
Implement GB Camera timing (when no webcam is connected), misc camera accuracy improvements, use GB_random instead of rand for noise_seed
This commit is contained in:
parent
1b38e8c932
commit
bb8f973fb4
|
@ -3,7 +3,7 @@
|
|||
static uint32_t noise_seed = 0;
|
||||
|
||||
/* This is not a complete emulation of the camera chip. Only the features used by the Game Boy Camera ROMs are supported.
|
||||
We also do not emulate the timing of the real cart, as it might be actually faster than the webcam. */
|
||||
We also do not emulate the timing of the real cart when a webcam is used, as it might be actually faster than the webcam. */
|
||||
|
||||
static uint8_t generate_noise(uint8_t x, uint8_t y)
|
||||
{
|
||||
|
@ -55,10 +55,6 @@ static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
|
||||
uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr)
|
||||
{
|
||||
if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) {
|
||||
/* Forbid reading the image while the camera is busy. */
|
||||
return 0xFF;
|
||||
}
|
||||
uint8_t tile_x = addr / 0x10 % 0x10;
|
||||
uint8_t tile_y = addr / 0x10 / 0x10;
|
||||
|
||||
|
@ -112,6 +108,12 @@ void GB_set_camera_get_pixel_callback(GB_gameboy_t *gb, GB_camera_get_pixel_call
|
|||
|
||||
void GB_set_camera_update_request_callback(GB_gameboy_t *gb, GB_camera_update_request_callback_t callback)
|
||||
{
|
||||
if (gb->camera_countdown > 0 && callback) {
|
||||
GB_log(gb, "Camera update request callback set while camera was proccessing, clearing camera countdown.\n");
|
||||
gb->camera_countdown = 0;
|
||||
GB_camera_updated(gb);
|
||||
}
|
||||
|
||||
gb->camera_update_request_callback = callback;
|
||||
}
|
||||
|
||||
|
@ -125,12 +127,25 @@ void GB_camera_write_register(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
addr &= 0x7F;
|
||||
if (addr == GB_CAMERA_SHOOT_AND_1D_FLAGS) {
|
||||
value &= 0x7;
|
||||
noise_seed = rand();
|
||||
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 */
|
||||
gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] |= 1;
|
||||
gb->camera_update_request_callback(gb);
|
||||
noise_seed = GB_random();
|
||||
if ((value & 1) && !(gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1)) {
|
||||
if (gb->camera_update_request_callback) {
|
||||
gb->camera_update_request_callback(gb);
|
||||
}
|
||||
else {
|
||||
/* If no callback is set, wait the amount of time the real camera would take before clearing the busy bit */
|
||||
uint16_t exposure = (gb->camera_registers[GB_CAMERA_EXPOSURE_HIGH] << 8) | gb->camera_registers[GB_CAMERA_EXPOSURE_LOW];
|
||||
gb->camera_countdown = 129792 + ((gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0x80)? 0 : 2048) + (exposure * 64) + (gb->camera_alignment & 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(value & 1) && (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1)) {
|
||||
/* We don't support cancelling a camera shoot */
|
||||
GB_log(gb, "ROM attempted to cancel camera shoot, which is currently not supported. The camera shoot will not be cancelled.\n");
|
||||
value |= 1;
|
||||
}
|
||||
|
||||
gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] = value;
|
||||
}
|
||||
else {
|
||||
if (addr >= 0x36) {
|
||||
|
|
|
@ -529,6 +529,8 @@ struct GB_gameboy_internal_s {
|
|||
};
|
||||
bool camera_registers_mapped;
|
||||
uint8_t camera_registers[0x36];
|
||||
uint8_t camera_alignment;
|
||||
int32_t camera_countdown;
|
||||
uint8_t rumble_strength;
|
||||
bool cart_ir;
|
||||
)
|
||||
|
|
|
@ -414,8 +414,15 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr)
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_CAMERA && gb->mbc_ram_bank == 0 && addr >= 0xA100 && addr < 0xAF00) {
|
||||
return GB_camera_read_image(gb, addr - 0xA100);
|
||||
if (gb->cartridge_type->mbc_type == GB_CAMERA) {
|
||||
/* Forbid reading RAM while the camera is busy. */
|
||||
if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gb->mbc_ram_bank == 0 && addr >= 0xA100 && addr < 0xAF00) {
|
||||
return GB_camera_read_image(gb, addr - 0xA100);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t effective_bank = gb->mbc_ram_bank;
|
||||
|
@ -1220,7 +1227,12 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
if (!gb->mbc_ram || !gb->mbc_ram_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_CAMERA && (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1)) {
|
||||
/* Forbid writing to RAM while the camera is busy. */
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t effective_bank = gb->mbc_ram_bank;
|
||||
if (gb->cartridge_type->mbc_type == GB_MBC3 && !gb->is_mbc30) {
|
||||
if (gb->cartridge_type->has_rtc) {
|
||||
|
|
|
@ -416,6 +416,9 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode)
|
|||
if (gb->apu.global_enable && gb->cgb_double_speed) {
|
||||
GB_log(gb, "ROM triggered an APU odd mode, which is currently not tested.\n");
|
||||
}
|
||||
if (gb->cartridge_type->mbc_type == GB_CAMERA && (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) && !gb->cgb_double_speed) {
|
||||
GB_log(gb, "ROM entered double speed mode with a camera cartridge, this could damage a real cartridge's camera.\n");
|
||||
}
|
||||
|
||||
if (gb->cgb_double_speed) {
|
||||
gb->cgb_double_speed = false;
|
||||
|
|
|
@ -365,6 +365,29 @@ static void rtc_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
}
|
||||
}
|
||||
|
||||
static void camera_run(GB_gameboy_t *gb, uint8_t cycles)
|
||||
{
|
||||
/* Do we have a camera? */
|
||||
if (likely(gb->cartridge_type->mbc_type != GB_CAMERA)) return;
|
||||
|
||||
/* The camera mapper uses the PHI pin to clock itself */
|
||||
|
||||
/* PHI does not run in halt nor stop mode */
|
||||
if (unlikely(gb->halted || gb->stopped)) return;
|
||||
|
||||
/* Only every other PHI is used (as the camera wants a 512KiHz clock) */
|
||||
gb->camera_alignment += cycles;
|
||||
|
||||
/* Is the camera processing an image? */
|
||||
if (likely(gb->camera_countdown == 0)) return;
|
||||
|
||||
gb->camera_countdown -= cycles;
|
||||
if (gb->camera_countdown <= 0) {
|
||||
gb->camera_countdown = 0;
|
||||
GB_camera_updated(gb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
||||
{
|
||||
|
@ -389,6 +412,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->dma_cycles = cycles;
|
||||
|
||||
timers_run(gb, cycles);
|
||||
camera_run(gb, cycles);
|
||||
|
||||
if (unlikely(gb->speed_switch_halt_countdown)) {
|
||||
gb->speed_switch_halt_countdown -= cycles;
|
||||
|
|
Loading…
Reference in New Issue