Merge branch 'master' into JoyKit

This commit is contained in:
Lior Halphon 2020-01-03 23:42:25 +02:00
commit 0737655753
23 changed files with 183 additions and 89 deletions

View File

@ -1185,6 +1185,23 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@try { @try {
if (!cameraSession) { if (!cameraSession) {
if (@available(macOS 10.14, *)) {
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) {
case AVAuthorizationStatusAuthorized:
break;
case AVAuthorizationStatusNotDetermined: {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
[self cameraRequestUpdate];
}];
return;
}
case AVAuthorizationStatusDenied:
case AVAuthorizationStatusRestricted:
GB_camera_updated(&gb);
return;
}
}
NSError *error; NSError *error;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error]; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error];

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDisplayName</key>
<string>SameBoy</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
@ -70,7 +72,7 @@
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>10.9</string> <string>10.9</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright © 2015-2019 Lior Halphon</string> <string>Copyright © 2015-2020 Lior Halphon</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
@ -116,6 +118,8 @@
</dict> </dict>
</dict> </dict>
</array> </array>
<key>NSCameraUsageDescription</key>
<string>SameBoy needs to access your camera to emulate the Game Boy Camera</string>
<key>NSSupportsAutomaticGraphicsSwitching</key> <key>NSSupportsAutomaticGraphicsSwitching</key>
<true/> <true/>
</dict> </dict>

View File

@ -30,7 +30,7 @@
<h1>SameBoy</h1> <h1>SameBoy</h1>
<h2>MIT License</h2> <h2>MIT License</h2>
<h3>Copyright © 2015-2019 Lior Halphon</h3> <h3>Copyright © 2015-2020 Lior Halphon</h3>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy <p>Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1008,7 +1008,7 @@ void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate)
GB_apu_update_cycles_per_sample(gb); GB_apu_update_cycles_per_sample(gb);
} }
void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample) void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, double cycles_per_sample)
{ {
if (cycles_per_sample == 0) { if (cycles_per_sample == 0) {

View File

@ -148,7 +148,7 @@ typedef struct {
} GB_apu_output_t; } GB_apu_output_t;
void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate); void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate);
void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample); /* Cycles are in 8MHz units */ void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, double cycles_per_sample); /* Cycles are in 8MHz units */
void GB_set_highpass_filter_mode(GB_gameboy_t *gb, GB_highpass_mode_t mode); void GB_set_highpass_filter_mode(GB_gameboy_t *gb, GB_highpass_mode_t mode);
void GB_apu_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback); void GB_apu_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback);
#ifdef GB_INTERNAL #ifdef GB_INTERNAL

View File

@ -819,7 +819,7 @@ static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const
GB_log(gb, "AF = $%04x (%c%c%c%c)\n", gb->registers[GB_REGISTER_AF], /* AF can't really be an address */ GB_log(gb, "AF = $%04x (%c%c%c%c)\n", gb->registers[GB_REGISTER_AF], /* AF can't really be an address */
(gb->f & GB_CARRY_FLAG)? 'C' : '-', (gb->f & GB_CARRY_FLAG)? 'C' : '-',
(gb->f & GB_HALF_CARRY_FLAG)? 'H' : '-', (gb->f & GB_HALF_CARRY_FLAG)? 'H' : '-',
(gb->f & GB_SUBSTRACT_FLAG)? 'N' : '-', (gb->f & GB_SUBTRACT_FLAG)? 'N' : '-',
(gb->f & GB_ZERO_FLAG)? 'Z' : '-'); (gb->f & GB_ZERO_FLAG)? 'Z' : '-');
GB_log(gb, "BC = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_BC], false)); GB_log(gb, "BC = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_BC], false));
GB_log(gb, "DE = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_DE], false)); GB_log(gb, "DE = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_DE], false));

View File

@ -18,6 +18,13 @@
#define GB_rewind_push(...) #define GB_rewind_push(...)
#endif #endif
static inline uint32_t state_magic(void)
{
if (sizeof(bool) == 1) return 'SAME';
return 'S4ME';
}
void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args) void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args)
{ {
char *string = NULL; char *string = NULL;
@ -660,7 +667,7 @@ void GB_disconnect_serial(GB_gameboy_t *gb)
bool GB_is_inited(GB_gameboy_t *gb) bool GB_is_inited(GB_gameboy_t *gb)
{ {
return gb->magic == 'SAME'; return gb->magic == state_magic();
} }
bool GB_is_cgb(GB_gameboy_t *gb) bool GB_is_cgb(GB_gameboy_t *gb)
@ -929,7 +936,7 @@ void GB_reset(GB_gameboy_t *gb)
gb->nontrivial_jump_state = NULL; gb->nontrivial_jump_state = NULL;
} }
gb->magic = (uintptr_t)'SAME'; gb->magic = state_magic();
} }
void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model) void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)

View File

@ -98,7 +98,7 @@ enum {
enum { enum {
GB_CARRY_FLAG = 16, GB_CARRY_FLAG = 16,
GB_HALF_CARRY_FLAG = 32, GB_HALF_CARRY_FLAG = 32,
GB_SUBSTRACT_FLAG = 64, GB_SUBTRACT_FLAG = 64,
GB_ZERO_FLAG = 128, GB_ZERO_FLAG = 128,
}; };
@ -278,10 +278,6 @@ typedef struct {
This struct is not packed, but dumped sections exclusively use types that have the same alignment in both 32 and 64 This struct is not packed, but dumped sections exclusively use types that have the same alignment in both 32 and 64
bit platforms. */ bit platforms. */
/* We make sure bool is 1 for cross-platform save state compatibility. */
/* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */
_Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1");
#ifdef GB_INTERNAL #ifdef GB_INTERNAL
struct GB_gameboy_s { struct GB_gameboy_s {
#else #else

View File

@ -422,6 +422,11 @@ static GB_read_function_t * const read_map[] =
read_ram, read_high_memory, /* EXXX FXXX */ read_ram, read_high_memory, /* EXXX FXXX */
}; };
void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback)
{
gb->read_memory_callback = callback;
}
uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr) uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
{ {
if (gb->n_watchpoints) { if (gb->n_watchpoints) {
@ -745,7 +750,11 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
return; return;
case GB_IO_JOYP: case GB_IO_JOYP:
if ((gb->io_registers[GB_IO_JOYP] & 0x30) != (value & 0x30)) { if (gb->joyp_write_callback) {
gb->joyp_write_callback(gb, value);
GB_update_joyp(gb);
}
else if ((gb->io_registers[GB_IO_JOYP] & 0x30) != (value & 0x30)) {
GB_sgb_write(gb, value); GB_sgb_write(gb, value);
gb->io_registers[GB_IO_JOYP] = value & 0xF0; gb->io_registers[GB_IO_JOYP] = value & 0xF0;
GB_update_joyp(gb); GB_update_joyp(gb);

View File

@ -385,11 +385,7 @@ static void command_ready(GB_gameboy_t *gb)
} }
void GB_sgb_write(GB_gameboy_t *gb, uint8_t value) void GB_sgb_write(GB_gameboy_t *gb, uint8_t value)
{ {
if (gb->joyp_write_callback) {
gb->joyp_write_callback(gb, value);
}
if (!GB_is_sgb(gb)) return; if (!GB_is_sgb(gb)) return;
if (!GB_is_hle_sgb(gb)) { if (!GB_is_hle_sgb(gb)) {
/* Notify via callback */ /* Notify via callback */

View File

@ -318,7 +318,7 @@ static void inc_hr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
register_id = ((opcode >> 4) + 1) & 0x03; register_id = ((opcode >> 4) + 1) & 0x03;
gb->registers[register_id] += 0x100; gb->registers[register_id] += 0x100;
gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
if ((gb->registers[register_id] & 0x0F00) == 0) { if ((gb->registers[register_id] & 0x0F00) == 0) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
@ -334,7 +334,7 @@ static void dec_hr(GB_gameboy_t *gb, uint8_t opcode)
register_id = ((opcode >> 4) + 1) & 0x03; register_id = ((opcode >> 4) + 1) & 0x03;
gb->registers[register_id] -= 0x100; gb->registers[register_id] -= 0x100;
gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG;
if ((gb->registers[register_id] & 0x0F00) == 0xF00) { if ((gb->registers[register_id] & 0x0F00) == 0xF00) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
@ -396,7 +396,7 @@ static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode)
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
rr = gb->registers[register_id]; rr = gb->registers[register_id];
gb->registers[GB_REGISTER_HL] = hl + rr; gb->registers[GB_REGISTER_HL] = hl + rr;
gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_CARRY_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_CARRY_FLAG | GB_HALF_CARRY_FLAG);
/* The meaning of the Half Carry flag is really hard to track -_- */ /* The meaning of the Half Carry flag is really hard to track -_- */
if (((hl & 0xFFF) + (rr & 0xFFF)) & 0x1000) { if (((hl & 0xFFF) + (rr & 0xFFF)) & 0x1000) {
@ -432,7 +432,7 @@ static void inc_lr(GB_gameboy_t *gb, uint8_t opcode)
value = (gb->registers[register_id] & 0xFF) + 1; value = (gb->registers[register_id] & 0xFF) + 1;
gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value;
gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
if ((gb->registers[register_id] & 0x0F) == 0) { if ((gb->registers[register_id] & 0x0F) == 0) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
@ -452,7 +452,7 @@ static void dec_lr(GB_gameboy_t *gb, uint8_t opcode)
gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value;
gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG;
if ((gb->registers[register_id] & 0x0F) == 0xF) { if ((gb->registers[register_id] & 0x0F) == 0xF) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
@ -533,7 +533,7 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode)
gb->registers[GB_REGISTER_AF] &= ~(0xFF00 | GB_ZERO_FLAG); gb->registers[GB_REGISTER_AF] &= ~(0xFF00 | GB_ZERO_FLAG);
if (gb->registers[GB_REGISTER_AF] & GB_SUBSTRACT_FLAG) { if (gb->registers[GB_REGISTER_AF] & GB_SUBTRACT_FLAG) {
if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) { if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) {
result = (result - 0x06) & 0xFF; result = (result - 0x06) & 0xFF;
} }
@ -567,19 +567,19 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode)
static void cpl(GB_gameboy_t *gb, uint8_t opcode) static void cpl(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->registers[GB_REGISTER_AF] ^= 0xFF00; gb->registers[GB_REGISTER_AF] ^= 0xFF00;
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG;
} }
static void scf(GB_gameboy_t *gb, uint8_t opcode) static void scf(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG;
gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG);
} }
static void ccf(GB_gameboy_t *gb, uint8_t opcode) static void ccf(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG; gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG;
gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG);
} }
static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode)
@ -610,7 +610,7 @@ static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode)
value = cycle_read(gb, gb->registers[GB_REGISTER_HL]) + 1; value = cycle_read(gb, gb->registers[GB_REGISTER_HL]) + 1;
cycle_write(gb, gb->registers[GB_REGISTER_HL], value); cycle_write(gb, gb->registers[GB_REGISTER_HL], value);
gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
if ((value & 0x0F) == 0) { if ((value & 0x0F) == 0) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
} }
@ -627,7 +627,7 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode)
cycle_write(gb, gb->registers[GB_REGISTER_HL], value); cycle_write(gb, gb->registers[GB_REGISTER_HL], value);
gb->registers[GB_REGISTER_AF] &= ~( GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~( GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG;
if ((value & 0x0F) == 0x0F) { if ((value & 0x0F) == 0x0F) {
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG;
} }
@ -763,7 +763,7 @@ static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value, a; uint8_t value, a;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBTRACT_FLAG;
if (a == value) { if (a == value) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
} }
@ -781,7 +781,7 @@ static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode)
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBTRACT_FLAG;
if ((uint8_t) (a - value - carry) == 0) { if ((uint8_t) (a - value - carry) == 0) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
@ -833,7 +833,7 @@ static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode)
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG;
if (a == value) { if (a == value) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
} }
@ -962,7 +962,7 @@ static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value, a; uint8_t value, a;
value = cycle_read_inc_oam_bug(gb, gb->pc++); value = cycle_read_inc_oam_bug(gb, gb->pc++);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBTRACT_FLAG;
if (a == value) { if (a == value) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
} }
@ -980,7 +980,7 @@ static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode)
value = cycle_read_inc_oam_bug(gb, gb->pc++); value = cycle_read_inc_oam_bug(gb, gb->pc++);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBTRACT_FLAG;
if ((uint8_t) (a - value - carry) == 0) { if ((uint8_t) (a - value - carry) == 0) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
@ -1032,7 +1032,7 @@ static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode)
value = cycle_read_inc_oam_bug(gb, gb->pc++); value = cycle_read_inc_oam_bug(gb, gb->pc++);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG;
if (a == value) { if (a == value) {
gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG;
} }

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2015-2019 Lior Halphon Copyright (c) 2015-2020 Lior Halphon
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -34,7 +34,7 @@ ifeq ($(MAKECMDGOALS),)
MAKECMDGOALS := $(DEFAULT) MAKECMDGOALS := $(DEFAULT)
endif endif
VERSION := 0.12.2 VERSION := 0.12.3
export VERSION export VERSION
CONF ?= debug CONF ?= debug
@ -51,10 +51,15 @@ endif
# Use clang if it's available. # Use clang if it's available.
ifeq ($(origin CC),default) ifeq ($(origin CC),default)
ifneq (, $(shell which clang)) ifneq (, $(shell which clang))
CC := clang CC := clang
endif endif
endif endif
# Find libraries with pkg-config if available.
ifneq (, $(shell which pkg-config))
PKG_CONFIG := pkg-config
endif
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
# To force use of the Unix version instead of the Windows version # To force use of the Unix version instead of the Windows version
MKDIR := $(shell which mkdir) MKDIR := $(shell which mkdir)
@ -71,9 +76,11 @@ endif
# Set compilation and linkage flags based on target, platform and configuration # Set compilation and linkage flags based on target, platform and configuration
OPEN_DIALOG = OpenDialog/gtk.c OPEN_DIALOG = OpenDialog/gtk.c
NULL := /dev/null
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
OPEN_DIALOG = OpenDialog/windows.c OPEN_DIALOG = OpenDialog/windows.c
NULL := NUL
endif endif
ifeq ($(PLATFORM),Darwin) ifeq ($(PLATFORM),Darwin)
@ -82,21 +89,35 @@ endif
CFLAGS += -Werror -Wall -Wno-unused-result -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES CFLAGS += -Werror -Wall -Wno-unused-result -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES
SDL_LDFLAGS := -lSDL2 -lGL ifeq (,$(PKG_CONFIG))
SDL_CFLAGS := $(shell sdl2-config --cflags)
SDL_LDFLAGS := $(shell sdl2-config --libs)
else
SDL_CFLAGS := $(shell $(PKG_CONFIG) --cflags sdl2)
SDL_LDFLAGS := $(shell $(PKG_CONFIG) --libs sdl2)
endif
ifeq (,$(PKG_CONFIG))
GL_LDFLAGS := -lGL
else
GL_CFLAGS := $(shell $(PKG_CONFIG) --cflags gl)
GL_LDFLAGS := $(shell $(PKG_CONFIG) --libs gl || echo -lGL)
endif
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
CFLAGS += -IWindows -Drandom=rand CFLAGS += -IWindows -Drandom=rand
LDFLAGS += -lmsvcrt -lcomdlg32 -lSDL2main -Wl,/MANIFESTFILE:NUL LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lSDL2main -Wl,/MANIFESTFILE:NUL
SDL_LDFLAGS := -lSDL2 -lopengl32 SDL_LDFLAGS := -lSDL2
GL_LDFLAGS := -lopengl32
else else
LDFLAGS += -lc -lm -ldl LDFLAGS += -lc -lm -ldl
endif endif
ifeq ($(PLATFORM),Darwin) ifeq ($(PLATFORM),Darwin)
SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> /dev/null) SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> $(NULL))
CFLAGS += -F/Library/Frameworks CFLAGS += -F/Library/Frameworks -mmacosx-version-min=10.9
OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) -mmacosx-version-min=10.9 OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT)
LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9
SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2 -framework OpenGL SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2
GL_LDFLAGS := -framework OpenGL
endif endif
CFLAGS += -Wno-deprecated-declarations CFLAGS += -Wno-deprecated-declarations
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
@ -108,10 +129,16 @@ ifeq ($(CONF),debug)
CFLAGS += -g CFLAGS += -g
else ifeq ($(CONF), release) else ifeq ($(CONF), release)
CFLAGS += -O3 -DNDEBUG CFLAGS += -O3 -DNDEBUG
STRIP := strip
ifeq ($(PLATFORM),Darwin)
LDFLAGS += -Wl,-exported_symbols_list,$(NULL)
STRIP := -@true
endif
ifneq ($(PLATFORM),windows32) ifneq ($(PLATFORM),windows32)
LDFLAGS += -flto LDFLAGS += -flto
CFLAGS += -flto CFLAGS += -flto
endif endif
else else
$(error Invalid value for CONF: $(CONF). Use "debug", "release" or "native_release") $(error Invalid value for CONF: $(CONF). Use "debug", "release" or "native_release")
endif endif
@ -169,6 +196,10 @@ ifneq ($(filter $(MAKECMDGOALS),cocoa),)
endif endif
endif endif
$(OBJ)/SDL/%.dep: SDL/%
-@$(MKDIR) -p $(dir $@)
$(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@
$(OBJ)/%.dep: % $(OBJ)/%.dep: %
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $(CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ $(CC) $(CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@
@ -179,6 +210,10 @@ $(OBJ)/Core/%.c.o: Core/%.c
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $(CFLAGS) -DGB_INTERNAL -c $< -o $@ $(CC) $(CFLAGS) -DGB_INTERNAL -c $< -o $@
$(OBJ)/SDL/%.c.o: SDL/%.c
-@$(MKDIR) -p $(dir $@)
$(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -c $< -o $@
$(OBJ)/%.c.o: %.c $(OBJ)/%.c.o: %.c
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
@ -220,7 +255,7 @@ $(BIN)/SameBoy.app/Contents/MacOS/SameBoy: $(CORE_OBJECTS) $(COCOA_OBJECTS)
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) -framework OpenGL -framework AudioUnit -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework IOKit $(CC) $^ -o $@ $(LDFLAGS) -framework OpenGL -framework AudioUnit -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework IOKit
ifeq ($(CONF), release) ifeq ($(CONF), release)
strip $@ $(STRIP) $@
endif endif
$(BIN)/SameBoy.app/Contents/Resources/Base.lproj/%.nib: Cocoa/%.xib $(BIN)/SameBoy.app/Contents/Resources/Base.lproj/%.nib: Cocoa/%.xib
@ -240,10 +275,7 @@ $(BIN)/SameBoy.qlgenerator: $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL
# once in the QL Generator. It should probably become a dylib instead. # once in the QL Generator. It should probably become a dylib instead.
$(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL: $(CORE_OBJECTS) $(QUICKLOOK_OBJECTS) $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL: $(CORE_OBJECTS) $(QUICKLOOK_OBJECTS)
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) -bundle -framework Cocoa -framework Quicklook $(CC) $^ -o $@ $(LDFLAGS) -Wl,-exported_symbols_list,QuickLook/exports.sym -bundle -framework Cocoa -framework Quicklook
ifeq ($(CONF), release)
strip -u -r -s QuickLook/exports.sym $@
endif
# cgb_boot_fast.bin is not a standard boot ROM, we don't expect it to exist in the user-provided # cgb_boot_fast.bin is not a standard boot ROM, we don't expect it to exist in the user-provided
# boot ROM directory. # boot ROM directory.
@ -256,19 +288,19 @@ $(BIN)/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin: $(BIN)/BootROMs
# Unix versions build only one binary # Unix versions build only one binary
$(BIN)/SDL/sameboy: $(CORE_OBJECTS) $(SDL_OBJECTS) $(BIN)/SDL/sameboy: $(CORE_OBJECTS) $(SDL_OBJECTS)
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS)
ifeq ($(CONF), release) ifeq ($(CONF), release)
strip $@ $(STRIP) $@
endif endif
# Windows version builds two, one with a conole and one without it # Windows version builds two, one with a conole and one without it
$(BIN)/SDL/sameboy.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o $(BIN)/SDL/sameboy.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) -Wl,/subsystem:windows $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:windows
$(BIN)/SDL/sameboy_debugger.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o $(BIN)/SDL/sameboy_debugger.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) -Wl,/subsystem:console $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:console
ifneq ($(USE_WINDRES),) ifneq ($(USE_WINDRES),)
$(OBJ)/%.o: %.rc $(OBJ)/%.o: %.rc
@ -294,7 +326,7 @@ $(BIN)/tester/sameboy_tester: $(CORE_OBJECTS) $(TESTER_OBJECTS)
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
$(CC) $^ -o $@ $(LDFLAGS) $(CC) $^ -o $@ $(LDFLAGS)
ifeq ($(CONF), release) ifeq ($(CONF), release)
strip $@ $(STRIP) $@
endif endif
$(BIN)/tester/sameboy_tester.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(BIN)/tester/sameboy_tester.exe: $(CORE_OBJECTS) $(SDL_OBJECTS)
@ -345,7 +377,7 @@ $(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.pb8
-@$(MKDIR) -p $(dir $@) -@$(MKDIR) -p $(dir $@)
rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $< rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $<
rgblink -o $@.tmp2 $@.tmp rgblink -o $@.tmp2 $@.tmp
dd if=$@.tmp2 of=$@ count=1 bs=$(if $(findstring dmg,$@)$(findstring sgb,$@),256,2304) dd if=$@.tmp2 of=$@ count=1 bs=$(if $(findstring dmg,$@)$(findstring sgb,$@),256,2304) 2> $(NULL)
@rm $@.tmp $@.tmp2 @rm $@.tmp $@.tmp2
# Libretro Core (uses its own build system) # Libretro Core (uses its own build system)

View File

@ -47,7 +47,7 @@
<key>CFPlugInUnloadFunction</key> <key>CFPlugInUnloadFunction</key>
<string></string> <string></string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright © 2015-2019 Lior Halphon</string> <string>Copyright © 2015-2020 Lior Halphon</string>
<key>QLNeedsToBeRunInMainThread</key> <key>QLNeedsToBeRunInMainThread</key>
<false/> <false/>
<key>QLPreviewHeight</key> <key>QLPreviewHeight</key>

View File

@ -1,3 +1,3 @@
_DeallocQuickLookGeneratorPluginType _DeallocQuickLookGeneratorPluginType
_QuickLookGeneratorQueryInterface _QuickLookGeneratorQueryInterface
_QuickLookGeneratorPluginFactory _QuickLookGeneratorPluginFactory

View File

@ -1,5 +1,5 @@
#include <SDL2/SDL.h>
#include <OpenDialog/open_dialog.h> #include <OpenDialog/open_dialog.h>
#include <SDL.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -792,6 +792,7 @@ void connect_joypad(void)
void run_gui(bool is_running) void run_gui(bool is_running)
{ {
SDL_ShowCursor(SDL_ENABLE);
connect_joypad(); connect_joypad();
/* Draw the background screen */ /* Draw the background screen */
@ -1011,6 +1012,15 @@ void run_gui(bool is_running)
} }
case SDL_KEYDOWN: case SDL_KEYDOWN:
if (event.key.keysym.scancode == SDL_SCANCODE_F && event.key.keysym.mod & MODIFIER) {
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == false) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
else {
SDL_SetWindowFullscreen(window, 0);
}
update_viewport();
}
if (event.key.keysym.scancode == SDL_SCANCODE_O) { if (event.key.keysym.scancode == SDL_SCANCODE_O) {
if (event.key.keysym.mod & MODIFIER) { if (event.key.keysym.mod & MODIFIER) {
char *filename = do_open_rom_dialog(); char *filename = do_open_rom_dialog();

View File

@ -1,7 +1,7 @@
#ifndef gui_h #ifndef gui_h
#define gui_h #define gui_h
#include <SDL2/SDL.h> #include <SDL.h>
#include <Core/gb.h> #include <Core/gb.h>
#include <stdbool.h> #include <stdbool.h>
#include "shader.h" #include "shader.h"

17
SDL/main.c Executable file → Normal file
View File

@ -2,7 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <OpenDialog/open_dialog.h> #include <OpenDialog/open_dialog.h>
#include <SDL2/SDL.h> #include <SDL.h>
#include <Core/gb.h> #include <Core/gb.h>
#include "utils.h" #include "utils.h"
#include "gui.h" #include "gui.h"
@ -12,6 +12,7 @@
#ifndef _WIN32 #ifndef _WIN32
#define AUDIO_FREQUENCY 96000 #define AUDIO_FREQUENCY 96000
#else #else
#include <Windows.h>
/* Windows (well, at least my VM) can't handle 96KHz sound well :( */ /* Windows (well, at least my VM) can't handle 96KHz sound well :( */
/* felsqualle says: For SDL 2.0.6+ using the WASAPI driver, the highest freq. /* felsqualle says: For SDL 2.0.6+ using the WASAPI driver, the highest freq.
@ -98,6 +99,7 @@ static void open_menu(void)
SDL_PauseAudioDevice(device_id, 1); SDL_PauseAudioDevice(device_id, 1);
} }
run_gui(true); run_gui(true);
SDL_ShowCursor(SDL_DISABLE);
if (audio_playing) { if (audio_playing) {
SDL_ClearQueuedAudio(device_id); SDL_ClearQueuedAudio(device_id);
SDL_PauseAudioDevice(device_id, 0); SDL_PauseAudioDevice(device_id, 0);
@ -123,7 +125,7 @@ static void handle_events(GB_gameboy_t *gb)
} }
case SDL_WINDOWEVENT: { case SDL_WINDOWEVENT: {
if (event.window.event == SDL_WINDOWEVENT_RESIZED) { if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
update_viewport(); update_viewport();
} }
break; break;
@ -273,6 +275,7 @@ static void handle_events(GB_gameboy_t *gb)
else { else {
SDL_SetWindowFullscreen(window, 0); SDL_SetWindowFullscreen(window, 0);
} }
update_viewport();
} }
break; break;
@ -406,14 +409,12 @@ static bool handle_pending_command(void)
return false; return false;
} }
case GB_SDL_RESET_COMMAND:
GB_save_battery(&gb, battery_save_path_ptr);
return true;
case GB_SDL_NO_COMMAND: case GB_SDL_NO_COMMAND:
return false; return false;
case GB_SDL_RESET_COMMAND:
case GB_SDL_NEW_FILE_COMMAND: case GB_SDL_NEW_FILE_COMMAND:
GB_save_battery(&gb, battery_save_path_ptr);
return true; return true;
case GB_SDL_QUIT_COMMAND: case GB_SDL_QUIT_COMMAND:
@ -425,6 +426,7 @@ static bool handle_pending_command(void)
static void run(void) static void run(void)
{ {
SDL_ShowCursor(SDL_DISABLE);
GB_model_t model; GB_model_t model;
pending_command = GB_SDL_NO_COMMAND; pending_command = GB_SDL_NO_COMMAND;
restart: restart:
@ -550,6 +552,9 @@ static bool get_arg_flag(const char *flag, int *argc, char **argv)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#ifdef _WIN32
SetProcessDPIAware();
#endif
#define str(x) #x #define str(x) #x
#define xstr(x) str(x) #define xstr(x) str(x)
fprintf(stderr, "SameBoy v" xstr(VERSION) "\n"); fprintf(stderr, "SameBoy v" xstr(VERSION) "\n");

View File

@ -1,5 +1,5 @@
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include <SDL2/SDL_opengl.h> #include <SDL_opengl.h>
#ifndef __APPLE__ #ifndef __APPLE__
#define GL_COMPAT_NAME(func) gl_compat_##func #define GL_COMPAT_NAME(func) gl_compat_##func

View File

@ -2,8 +2,8 @@
#define opengl_compat_h #define opengl_compat_h
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include <SDL2/SDL_opengl.h> #include <SDL_opengl.h>
#include <SDL2/SDL_video.h> #include <SDL_video.h>
#ifndef __APPLE__ #ifndef __APPLE__
#define GL_COMPAT_NAME(func) gl_compat_##func #define GL_COMPAT_NAME(func) gl_compat_##func

View File

@ -1,4 +1,4 @@
#include <SDL2/SDL.h> #include <SDL.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "utils.h" #include "utils.h"

Binary file not shown.

View File

@ -92,6 +92,7 @@ static unsigned emulated_devices = 1;
static bool initialized = false; static bool initialized = false;
static unsigned screen_layout = 0; static unsigned screen_layout = 0;
static unsigned audio_out = 0; static unsigned audio_out = 0;
static unsigned sgb_border = 1;
static bool geometry_updated = false; static bool geometry_updated = false;
static bool link_cable_emulation = false; static bool link_cable_emulation = false;
@ -209,6 +210,7 @@ static const struct retro_variable vars_single[] = {
{ "sameboy_color_correction_mode", "Color correction; off|correct curves|emulate hardware|preserve brightness" }, { "sameboy_color_correction_mode", "Color correction; off|correct curves|emulate hardware|preserve brightness" },
{ "sameboy_high_pass_filter_mode", "High-pass filter; off|accurate|remove dc offset" }, { "sameboy_high_pass_filter_mode", "High-pass filter; off|accurate|remove dc offset" },
{ "sameboy_model", "Emulated model; Auto|Game Boy|Game Boy Color|Game Boy Advance|Super Game Boy|Super Game Boy 2" }, { "sameboy_model", "Emulated model; Auto|Game Boy|Game Boy Color|Game Boy Advance|Super Game Boy|Super Game Boy 2" },
{ "sameboy_border", "Super Game Boy border; enabled|disabled" },
{ NULL } { NULL }
}; };
@ -430,21 +432,20 @@ static void init_for_current_model(unsigned id)
descs[7].len = 0x4000; descs[7].len = 0x4000;
descs[7].flags = RETRO_MEMDESC_CONST; descs[7].flags = RETRO_MEMDESC_CONST;
descs[8].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_OAM, &size, &bank); descs[8].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_OAM, &size, &bank);
descs[8].start = 0xFE00; descs[8].start = 0xFE00;
descs[8].select = 0xFFFFFF00; descs[8].len = 0x00A0;
descs[8].len = 0x00A0; descs[8].select= 0xFFFFFF00;
descs[9].ptr = descs[2].ptr + 0x2000; /* GBC RAM bank 2 */ descs[9].ptr = descs[2].ptr + 0x2000; /* GBC RAM bank 2 */
descs[9].start = 0x10000; descs[9].start = 0x10000;
descs[9].select = 0xFFFF0000; descs[9].len = GB_is_cgb(&gameboy[i]) ? 0x6000 : 0; /* 0x1000 per bank (2-7), unmapped on GB */
descs[9].len = GB_is_cgb(&gameboy[i]) ? 0x6000 : 0; /* 0x1000 per bank (2-7), unmapped on GB */ descs[9].select= 0xFFFF0000;
descs[10].ptr = descs[8].ptr; descs[10].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_IO, &size, &bank);
descs[10].offset = 0x100; descs[10].start = 0xFF00;
descs[10].start = 0xFF00; descs[10].len = 0x0080;
descs[10].select = 0xFFFFFF00; descs[10].select= 0xFFFFFF00;
descs[10].len = 0x0080;
struct retro_memory_map mmaps; struct retro_memory_map mmaps;
mmaps.descriptors = descs; mmaps.descriptors = descs;
@ -493,7 +494,7 @@ static void check_variables()
{ {
var.key = "sameboy_color_correction_mode"; var.key = "sameboy_color_correction_mode";
var.value = NULL; var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[0])) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{ {
if (strcmp(var.value, "off") == 0) if (strcmp(var.value, "off") == 0)
GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED); GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED);
@ -542,12 +543,22 @@ static void check_variables()
init_for_current_model(0); init_for_current_model(0);
} }
} }
var.key = "sameboy_border";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "enabled") == 0)
sgb_border = 1;
else if (strcmp(var.value, "disabled") == 0)
sgb_border = 0;
}
} }
else else
{ {
var.key = "sameboy_color_correction_mode_1"; var.key = "sameboy_color_correction_mode_1";
var.value = NULL; var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[0])) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{ {
if (strcmp(var.value, "off") == 0) if (strcmp(var.value, "off") == 0)
GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED); GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED);
@ -561,7 +572,7 @@ static void check_variables()
var.key = "sameboy_color_correction_mode_2"; var.key = "sameboy_color_correction_mode_2";
var.value = NULL; var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[1])) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{ {
if (strcmp(var.value, "off") == 0) if (strcmp(var.value, "off") == 0)
GB_set_color_correction_mode(&gameboy[1], GB_COLOR_CORRECTION_DISABLED); GB_set_color_correction_mode(&gameboy[1], GB_COLOR_CORRECTION_DISABLED);
@ -887,8 +898,15 @@ void retro_run(void)
} }
else else
{ {
if (model[0] == MODEL_SGB || model[0] == MODEL_SGB2) if (model[0] == MODEL_SGB || model[0] == MODEL_SGB2) {
video_cb(frame_buf, SGB_VIDEO_WIDTH, SGB_VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t)); if (sgb_border == 1)
video_cb(frame_buf, SGB_VIDEO_WIDTH, SGB_VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t));
else {
int crop = SGB_VIDEO_WIDTH * ((SGB_VIDEO_HEIGHT - VIDEO_HEIGHT) / 2) + ((SGB_VIDEO_WIDTH - VIDEO_WIDTH) / 2);
video_cb(frame_buf + crop, VIDEO_WIDTH, VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t));
}
}
else else
video_cb(frame_buf, VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_WIDTH * sizeof(uint32_t)); video_cb(frame_buf, VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_WIDTH * sizeof(uint32_t));
} }