Mass name and type changes. Save states are now compatible between 32- and 64-bit systems. Maybe.

This commit is contained in:
Lior Halphon 2016-06-18 20:29:11 +03:00
parent 32a1ad87b7
commit 70bd90740a
20 changed files with 948 additions and 936 deletions

View File

@ -17,7 +17,7 @@
@property GBAudioClient *audioClient;
- (void) vblank;
- (void) log: (const char *) log withAttributes: (gb_log_attributes) attributes;
- (void) log: (const char *) log withAttributes: (GB_log_attributes) attributes;
- (const char *) getDebuggerInput;
@end
@ -27,7 +27,7 @@ static void vblank(GB_gameboy_t *gb)
[self vblank];
}
static void consoleLog(GB_gameboy_t *gb, const char *string, gb_log_attributes attributes)
static void consoleLog(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes)
{
Document *self = (__bridge Document *)(gb->user_data);
[self log:string withAttributes: attributes];
@ -39,7 +39,7 @@ static char *consoleInput(GB_gameboy_t *gb)
return strdup([self getDebuggerInput]);
}
static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, unsigned char b)
static uint32_t rgbEncode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
{
return (r << 0) | (g << 8) | (b << 16);
}
@ -71,47 +71,47 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
- (void) initDMG
{
gb_init(&gb);
gb_load_bios(&gb, [[[NSBundle mainBundle] pathForResource:@"dmg_boot" ofType:@"bin"] UTF8String]);
gb_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
gb_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
gb_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
gb_set_rgb_encode_callback(&gb, rgbEncode);
GB_init(&gb);
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"dmg_boot" ofType:@"bin"] UTF8String]);
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
GB_set_rgb_encode_callback(&gb, rgbEncode);
gb.user_data = (__bridge void *)(self);
}
- (void) initCGB
{
gb_init_cgb(&gb);
gb_load_bios(&gb, [[[NSBundle mainBundle] pathForResource:@"cgb_boot" ofType:@"bin"] UTF8String]);
gb_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
gb_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
gb_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
gb_set_rgb_encode_callback(&gb, rgbEncode);
GB_init_cgb(&gb);
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"cgb_boot" ofType:@"bin"] UTF8String]);
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
GB_set_rgb_encode_callback(&gb, rgbEncode);
gb.user_data = (__bridge void *)(self);
}
- (void) vblank
{
[self.view flip];
gb_set_pixels_output(&gb, self.view.pixels);
GB_set_pixels_output(&gb, self.view.pixels);
}
- (void) run
{
running = true;
gb_set_pixels_output(&gb, self.view.pixels);
GB_set_pixels_output(&gb, self.view.pixels);
self.view.gb = &gb;
gb_set_sample_rate(&gb, 96000);
GB_set_sample_rate(&gb, 96000);
self.audioClient = [[GBAudioClient alloc] initWithRendererBlock:^(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer) {
apu_copy_buffer(&gb, buffer, nFrames);
GB_apu_copy_buffer(&gb, buffer, nFrames);
} andSampleRate:96000];
[self.audioClient start];
while (running) {
gb_run(&gb);
GB_run(&gb);
}
[self.audioClient stop];
gb_save_battery(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]);
GB_save_battery(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]);
stopping = false;
}
@ -137,7 +137,7 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
{
bool was_cgb = gb.is_cgb;
[self stop];
gb_free(&gb);
GB_free(&gb);
is_inited = false;
if (([sender tag] == 0 && was_cgb) || [sender tag] == 2) {
[self initCGB];
@ -165,7 +165,7 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
- (void)dealloc
{
gb_free(&gb);
GB_free(&gb);
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController {
@ -198,8 +198,8 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
if (is_inited++) {
return YES;
}
gb_load_rom(&gb, [fileName UTF8String]);
gb_load_battery(&gb, [[[fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]);
GB_load_rom(&gb, [fileName UTF8String]);
GB_load_battery(&gb, [[[fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]);
return YES;
}
@ -283,7 +283,7 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
return rect;
}
- (void) log: (const char *) string withAttributes: (gb_log_attributes) attributes
- (void) log: (const char *) string withAttributes: (GB_log_attributes) attributes
{
if (pendingLogLines > 128) {
/* The ROM causes so many errors in such a short time, and we can't handle it. */
@ -367,7 +367,7 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
if (!gb.debug_stopped) {
[self stop];
}
gb_save_state(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]] UTF8String]);
GB_save_state(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]] UTF8String]);
if (was_running) {
[self start];
}
@ -379,7 +379,7 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, unsigned char r, unsigned char g, un
if (!gb.debug_stopped) {
[self stop];
}
gb_load_state(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]] UTF8String]);
GB_load_state(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]] UTF8String]);
if (was_running) {
[self start];
}

View File

@ -27,7 +27,7 @@ static int16_t generate_square(double phase, int16_t amplitude, double duty)
return 0;
}
static int16_t generate_wave(double phase, int16_t amplitude, signed char *wave, unsigned char shift)
static int16_t generate_wave(double phase, int16_t amplitude, int8_t *wave, uint8_t shift)
{
phase = fmod(phase, 2 * M_PI);
return ((wave[(int)(phase / (2 * M_PI) * 32)]) >> shift) * (int)amplitude / 0xF;
@ -60,7 +60,7 @@ static int16_t step_lfsr(uint16_t lfsr, bool uses_7_bit)
/* General Todo: The APU emulation seems to fail many accuracy tests. It might require a rewrite with
these tests in mind. */
void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_samples, GB_sample_t *samples)
void GB_apu_render(GB_gameboy_t *gb, unsigned int sample_rate, unsigned int n_samples, GB_sample_t *samples)
{
for (; n_samples--; samples++) {
samples->left = samples->right = 0;
@ -112,7 +112,7 @@ void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_sam
samples->left *= gb->apu.left_volume;
samples->right *= gb->apu.right_volume;
for (unsigned char i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
/* Phase */
gb->apu.wave_channels[i].phase += 2 * M_PI * gb->apu.wave_channels[i].frequency / sample_rate;
while (gb->apu.wave_channels[i].phase >= 2 * M_PI) {
@ -137,7 +137,7 @@ void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_sam
gb->apu.envelope_step_timer += 1.0 / sample_rate;
if (gb->apu.envelope_step_timer >= 1.0 / 64) {
gb->apu.envelope_step_timer -= 1.0 / 64;
for (unsigned char i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
if (gb->apu.wave_channels[i].envelope_steps && !--gb->apu.wave_channels[i].cur_envelope_steps) {
gb->apu.wave_channels[i].amplitude = min(max(gb->apu.wave_channels[i].amplitude + gb->apu.wave_channels[i].envelope_direction * CH_STEP, 0), MAX_CH_AMP);
gb->apu.wave_channels[i].cur_envelope_steps = gb->apu.wave_channels[i].envelope_steps;
@ -151,7 +151,7 @@ void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_sam
if (gb->apu.wave_channels[0].sweep_steps && !--gb->apu.wave_channels[0].cur_sweep_steps) {
// Convert back to GB format
unsigned short temp = (unsigned short) (2048 - 131072 / gb->apu.wave_channels[0].frequency);
uint16_t temp = (uint16_t) (2048 - 131072 / gb->apu.wave_channels[0].frequency);
// Apply sweep
temp = temp + gb->apu.wave_channels[0].sweep_direction *
@ -169,19 +169,19 @@ void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_sam
}
}
void apu_run(GB_gameboy_t *gb)
void GB_apu_run(GB_gameboy_t *gb)
{
static bool should_log_overflow = true;
while (gb->audio_copy_in_progress);
double ticks_per_sample = (double) CPU_FREQUENCY / gb->sample_rate;
while (gb->apu_cycles > ticks_per_sample) {
GB_sample_t sample = {0, };
apu_render(gb, gb->sample_rate, 1, &sample);
GB_apu_render(gb, gb->sample_rate, 1, &sample);
gb->apu_cycles -= ticks_per_sample;
if (gb->audio_position == gb->buffer_size) {
/*
if (should_log_overflow && !gb->turbo) {
gb_log(gb, "Audio overflow\n");
GB_log(gb, "Audio overflow\n");
should_log_overflow = false;
}
*/
@ -193,7 +193,7 @@ void apu_run(GB_gameboy_t *gb)
}
}
void apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count)
void GB_apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count)
{
gb->audio_copy_in_progress = true;
@ -204,7 +204,7 @@ void apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count)
}
if (count > gb->audio_position) {
// gb_log(gb, "Audio underflow: %d\n", count - gb->audio_position);
// GB_log(gb, "Audio underflow: %d\n", count - gb->audio_position);
memset(dest + gb->audio_position, 0, (count - gb->audio_position) * sizeof(*gb->audio_buffer));
count = gb->audio_position;
}
@ -215,7 +215,7 @@ void apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count)
gb->audio_copy_in_progress = false;
}
void apu_init(GB_gameboy_t *gb)
void GB_apu_init(GB_gameboy_t *gb)
{
memset(&gb->apu, 0, sizeof(gb->apu));
gb->apu.wave_channels[0].duty = gb->apu.wave_channels[1].duty = 0.5;
@ -227,12 +227,12 @@ void apu_init(GB_gameboy_t *gb)
}
}
unsigned char apu_read(GB_gameboy_t *gb, unsigned char reg)
uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg)
{
/* Todo: what happens when reading from the wave from while it's playing? */
if (reg == GB_IO_NR52) {
unsigned char value = 0;
uint8_t value = 0;
for (int i = 0; i < 4; i++) {
value >>= 1;
if (gb->apu.wave_channels[i].is_playing) {
@ -260,17 +260,17 @@ unsigned char apu_read(GB_gameboy_t *gb, unsigned char reg)
};
if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END && gb->apu.wave_channels[2].is_playing) {
return (unsigned char)((gb->display_cycles * 22695477 * reg) >> 8); // Semi-random but deterministic
return (uint8_t)((gb->display_cycles * 22695477 * reg) >> 8); // Semi-random but deterministic
}
return gb->io_registers[reg] | read_mask[reg - GB_IO_NR10];
}
void apu_write(GB_gameboy_t *gb, unsigned char reg, unsigned char value)
void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
{
static const double duties[] = {0.125, 0.25, 0.5, 0.75};
static uint16_t NRX3_X4_temp[3] = {0};
unsigned char channel = 0;
uint8_t channel = 0;
if (!gb->apu.global_enable && reg != GB_IO_NR52) {
return;
@ -376,7 +376,7 @@ void apu_write(GB_gameboy_t *gb, unsigned char reg, unsigned char value)
{
double r = value & 0x7;
if (r == 0) r = 0.5;
unsigned char s = value >> 4;
uint8_t s = value >> 4;
gb->apu.wave_channels[3].frequency = 524288.0 / r / (1 << (s + 1));
gb->apu.lfsr_7_bit = value & 0x8;
break;
@ -406,7 +406,7 @@ void apu_write(GB_gameboy_t *gb, unsigned char reg, unsigned char value)
case GB_IO_NR52:
if ((value & 0x80) && !gb->apu.global_enable) {
apu_init(gb);
GB_apu_init(gb);
gb->apu.global_enable = true;
}
else if (!(value & 0x80) && gb->apu.global_enable) {

View File

@ -7,6 +7,7 @@
#define MAX_CH_AMP 0x1E00
#define CH_STEP (0x1E00/0xF)
#include "save_struct.h"
struct GB_gameboy_s;
typedef struct GB_gameboy_s GB_gameboy_t;
@ -20,30 +21,30 @@ typedef struct
/* Not all used on all channels */
typedef struct
{
double phase;
double frequency;
GB_aligned_double phase;
GB_aligned_double frequency;
GB_aligned_double duty;
GB_aligned_double sound_length; /* In seconds */
int16_t amplitude;
int16_t start_amplitude;
double duty;
double sound_length; /* In seconds */
bool stop_on_length;
unsigned char envelope_steps;
unsigned char cur_envelope_steps;
uint8_t envelope_steps;
uint8_t cur_envelope_steps;
signed int envelope_direction;
unsigned char sweep_steps;
unsigned char cur_sweep_steps;
uint8_t sweep_steps;
uint8_t cur_sweep_steps;
signed int sweep_direction;
unsigned char sweep_shift;
uint8_t sweep_shift;
bool is_playing;
} GB_apu_channel_t;
typedef struct
{
GB_apu_channel_t wave_channels[4];
double envelope_step_timer; /* In seconds */
double sweep_step_timer; /* In seconds */
signed char wave_form[32];
unsigned char wave_shift;
GB_aligned_double envelope_step_timer; /* In seconds */
GB_aligned_double sweep_step_timer; /* In seconds */
int8_t wave_form[32];
uint8_t wave_shift;
bool wave_enable;
uint16_t lfsr;
bool lfsr_7_bit;
@ -54,11 +55,11 @@ typedef struct
bool global_enable;
} GB_apu_t;
void apu_render(GB_gameboy_t *gb, unsigned long sample_rate, unsigned long n_samples, GB_sample_t *samples);
void apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count);
void apu_write(GB_gameboy_t *gb, unsigned char reg, unsigned char value);
unsigned char apu_read(GB_gameboy_t *gb, unsigned char reg);
void apu_init(GB_gameboy_t *gb);
void apu_run(GB_gameboy_t *gb);
void GB_apu_render(GB_gameboy_t *gb, unsigned int sample_rate, unsigned int n_samples, GB_sample_t *samples);
void GB_apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count);
void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value);
uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg);
void GB_apu_init(GB_gameboy_t *gb);
void GB_apu_run(GB_gameboy_t *gb);
#endif /* apu_h */

View File

@ -15,17 +15,17 @@ typedef struct {
LVALUE_REG_L,
} kind;
union {
unsigned short *register_address;
unsigned short memory_address;
uint16_t *register_address;
uint16_t memory_address;
};
} lvalue_t;
static unsigned short read_lvalue(GB_gameboy_t *gb, lvalue_t lvalue)
static uint16_t read_lvalue(GB_gameboy_t *gb, lvalue_t lvalue)
{
/* Not used until we add support for operators like += */
switch (lvalue.kind) {
case LVALUE_MEMORY:
return read_memory(gb, lvalue.memory_address);
return GB_read_memory(gb, lvalue.memory_address);
case LVALUE_REG16:
return *lvalue.register_address;
@ -38,11 +38,11 @@ static unsigned short read_lvalue(GB_gameboy_t *gb, lvalue_t lvalue)
}
}
static void write_lvalue(GB_gameboy_t *gb, lvalue_t lvalue, unsigned short value)
static void write_lvalue(GB_gameboy_t *gb, lvalue_t lvalue, uint16_t value)
{
switch (lvalue.kind) {
case LVALUE_MEMORY:
write_memory(gb, lvalue.memory_address, value);
GB_write_memory(gb, lvalue.memory_address, value);
return;
case LVALUE_REG16:
@ -61,27 +61,27 @@ static void write_lvalue(GB_gameboy_t *gb, lvalue_t lvalue, unsigned short value
}
}
static unsigned short add(unsigned short a, unsigned short b) {return a + b;};
static unsigned short sub(unsigned short a, unsigned short b) {return a - b;};
static unsigned short mul(unsigned short a, unsigned short b) {return a * b;};
static unsigned short _div(unsigned short a, unsigned short b) {
static uint16_t add(uint16_t a, uint16_t b) {return a + b;};
static uint16_t sub(uint16_t a, uint16_t b) {return a - b;};
static uint16_t mul(uint16_t a, uint16_t b) {return a * b;};
static uint16_t _div(uint16_t a, uint16_t b) {
if (b == 0) {
return 0;
}
return a / b;
};
static unsigned short mod(unsigned short a, unsigned short b) {
static uint16_t mod(uint16_t a, uint16_t b) {
if (b == 0) {
return 0;
}
return a % b;
};
static unsigned short and(unsigned short a, unsigned short b) {return a & b;};
static unsigned short or(unsigned short a, unsigned short b) {return a | b;};
static unsigned short xor(unsigned short a, unsigned short b) {return a ^ b;};
static unsigned short shleft(unsigned short a, unsigned short b) {return a << b;};
static unsigned short shright(unsigned short a, unsigned short b) {return a >> b;};
static unsigned short assign(GB_gameboy_t *gb, lvalue_t a, unsigned short b)
static uint16_t and(uint16_t a, uint16_t b) {return a & b;};
static uint16_t or(uint16_t a, uint16_t b) {return a | b;};
static uint16_t xor(uint16_t a, uint16_t b) {return a ^ b;};
static uint16_t shleft(uint16_t a, uint16_t b) {return a << b;};
static uint16_t shright(uint16_t a, uint16_t b) {return a >> b;};
static uint16_t assign(GB_gameboy_t *gb, lvalue_t a, uint16_t b)
{
write_lvalue(gb, a, b);
return read_lvalue(gb, a);
@ -90,8 +90,8 @@ static unsigned short assign(GB_gameboy_t *gb, lvalue_t a, unsigned short b)
static struct {
const char *string;
char priority;
unsigned short (*operator)(unsigned short, unsigned short);
unsigned short (*lvalue_operator)(GB_gameboy_t *, lvalue_t, unsigned short);
uint16_t (*operator)(uint16_t, uint16_t);
uint16_t (*lvalue_operator)(GB_gameboy_t *, lvalue_t, uint16_t);
} operators[] =
{
// Yes. This is not C-like. But it makes much more sense.
@ -109,7 +109,7 @@ static struct {
{"=", 2, NULL, assign},
};
unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned int length, bool *error);
uint16_t debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned int length, bool *error);
static lvalue_t debugger_evaluate_lvalue(GB_gameboy_t *gb, const char *string, unsigned int length, bool *error)
{
@ -124,7 +124,7 @@ static lvalue_t debugger_evaluate_lvalue(GB_gameboy_t *gb, const char *string, u
}
if (length == 0)
{
gb_log(gb, "Expected expression.\n");
GB_log(gb, "Expected expression.\n");
*error = true;
return (lvalue_t){0,};
}
@ -183,17 +183,17 @@ static lvalue_t debugger_evaluate_lvalue(GB_gameboy_t *gb, const char *string, u
case 'p': if (string[2] == 'c') return (lvalue_t){LVALUE_REG16, .register_address = &gb->pc};
}
}
gb_log(gb, "Unknown register: %.*s\n", length, string);
GB_log(gb, "Unknown register: %.*s\n", length, string);
*error = true;
return (lvalue_t){0,};
}
gb_log(gb, "Expression is not an lvalue: %.*s\n", length, string);
GB_log(gb, "Expression is not an lvalue: %.*s\n", length, string);
*error = true;
return (lvalue_t){0,};
}
unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned int length, bool *error)
uint16_t debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned int length, bool *error)
{
*error = false;
// Strip whitespace
@ -206,7 +206,7 @@ unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned
}
if (length == 0)
{
gb_log(gb, "Expected expression.\n");
GB_log(gb, "Expected expression.\n");
*error = true;
return -1;
}
@ -236,7 +236,7 @@ unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned
}
if (string[i] == ']') depth--;
}
if (depth == 0) return read_memory(gb, debugger_evaluate(gb, string + 1, length - 2, error));
if (depth == 0) return GB_read_memory(gb, debugger_evaluate(gb, string + 1, length - 2, error));
}
// Search for lowest priority operator
signed int depth = 0;
@ -262,14 +262,14 @@ unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned
}
if (operator_index != -1) {
unsigned int right_start = (unsigned int)(operator_pos + strlen(operators[operator_index].string));
unsigned short right = debugger_evaluate(gb, string + right_start, length - right_start, error);
uint16_t right = debugger_evaluate(gb, string + right_start, length - right_start, error);
if (*error) return -1;
if (operators[operator_index].lvalue_operator) {
lvalue_t left = debugger_evaluate_lvalue(gb, string, operator_pos, error);
if (*error) return -1;
return operators[operator_index].lvalue_operator(gb, left, right);
}
unsigned short left = debugger_evaluate(gb, string, operator_pos, error);
uint16_t left = debugger_evaluate(gb, string, operator_pos, error);
if (*error) return -1;
return operators[operator_index].operator(left, right);
}
@ -300,15 +300,15 @@ unsigned short debugger_evaluate(GB_gameboy_t *gb, const char *string, unsigned
case 'p': if (string[2] == 'c') return gb->pc;
}
}
gb_log(gb, "Unknown register: %.*s\n", length, string);
GB_log(gb, "Unknown register: %.*s\n", length, string);
*error = true;
return -1;
}
char *end;
unsigned short literal = (unsigned short) (strtol(string, &end, 16));
uint16_t literal = (uint16_t) (strtol(string, &end, 16));
if (end != string + length) {
gb_log(gb, "Failed to parse: %.*s\n", length, string);
GB_log(gb, "Failed to parse: %.*s\n", length, string);
*error = true;
return -1;
}
@ -319,7 +319,7 @@ typedef bool debugger_command_imp_t(GB_gameboy_t *gb, char *arguments);
typedef struct {
const char *command;
unsigned char min_length;
uint8_t min_length;
debugger_command_imp_t *implementation;
const char *help_string; // Null if should not appear in help
} debugger_command_t;
@ -335,7 +335,7 @@ static const char *lstrip(const char *str)
static bool cont(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: continue\n");
GB_log(gb, "Usage: continue\n");
return true;
}
gb->debug_stopped = false;
@ -345,7 +345,7 @@ static bool cont(GB_gameboy_t *gb, char *arguments)
static bool next(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: next\n");
GB_log(gb, "Usage: next\n");
return true;
}
@ -358,7 +358,7 @@ static bool next(GB_gameboy_t *gb, char *arguments)
static bool step(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: step\n");
GB_log(gb, "Usage: step\n");
return true;
}
@ -368,7 +368,7 @@ static bool step(GB_gameboy_t *gb, char *arguments)
static bool finish(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: finish\n");
GB_log(gb, "Usage: finish\n");
return true;
}
@ -381,7 +381,7 @@ static bool finish(GB_gameboy_t *gb, char *arguments)
static bool stack_leak_detection(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: sld\n");
GB_log(gb, "Usage: sld\n");
return true;
}
@ -394,23 +394,23 @@ static bool stack_leak_detection(GB_gameboy_t *gb, char *arguments)
static bool registers(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: registers\n");
GB_log(gb, "Usage: registers\n");
return true;
}
gb_log(gb, "AF = %04x\n", gb->registers[GB_REGISTER_AF]);
gb_log(gb, "BC = %04x\n", gb->registers[GB_REGISTER_BC]);
gb_log(gb, "DE = %04x\n", gb->registers[GB_REGISTER_DE]);
gb_log(gb, "HL = %04x\n", gb->registers[GB_REGISTER_HL]);
gb_log(gb, "SP = %04x\n", gb->registers[GB_REGISTER_SP]);
gb_log(gb, "PC = %04x\n", gb->pc);
gb_log(gb, "TIMA = %d/%lu\n", gb->io_registers[GB_IO_TIMA], gb->tima_cycles);
gb_log(gb, "Display Controller: LY = %d/%lu\n", gb->io_registers[GB_IO_LY], gb->display_cycles % 456);
GB_log(gb, "AF = %04x\n", gb->registers[GB_REGISTER_AF]);
GB_log(gb, "BC = %04x\n", gb->registers[GB_REGISTER_BC]);
GB_log(gb, "DE = %04x\n", gb->registers[GB_REGISTER_DE]);
GB_log(gb, "HL = %04x\n", gb->registers[GB_REGISTER_HL]);
GB_log(gb, "SP = %04x\n", gb->registers[GB_REGISTER_SP]);
GB_log(gb, "PC = %04x\n", gb->pc);
GB_log(gb, "TIMA = %d/%u\n", gb->io_registers[GB_IO_TIMA], gb->tima_cycles);
GB_log(gb, "Display Controller: LY = %d/%u\n", gb->io_registers[GB_IO_LY], gb->display_cycles % 456);
return true;
}
/* Find the index of the closest breakpoint equal or greater to addr */
static unsigned short find_breakpoint(GB_gameboy_t *gb, unsigned short addr)
static uint16_t find_breakpoint(GB_gameboy_t *gb, uint16_t addr)
{
if (!gb->breakpoints) {
return 0;
@ -418,7 +418,7 @@ static unsigned short find_breakpoint(GB_gameboy_t *gb, unsigned short addr)
int min = 0;
int max = gb->n_breakpoints;
while (min < max) {
unsigned short pivot = (min + max) / 2;
uint16_t pivot = (min + max) / 2;
if (gb->breakpoints[pivot] == addr) return pivot;
if (gb->breakpoints[pivot] > addr) {
max = pivot - 1;
@ -427,24 +427,24 @@ static unsigned short find_breakpoint(GB_gameboy_t *gb, unsigned short addr)
min = pivot + 1;
}
}
return (unsigned short) min;
return (uint16_t) min;
}
static bool breakpoint(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments)) == 0) {
gb_log(gb, "Usage: breakpoint <expression>\n");
GB_log(gb, "Usage: breakpoint <expression>\n");
return true;
}
bool error;
unsigned short result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
uint16_t result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
if (error) return true;
unsigned short index = find_breakpoint(gb, result);
uint16_t index = find_breakpoint(gb, result);
if (index < gb->n_breakpoints && gb->breakpoints[index] == result) {
gb_log(gb, "Breakpoint already set at %04x\n", result);
GB_log(gb, "Breakpoint already set at %04x\n", result);
return true;
}
@ -453,14 +453,14 @@ static bool breakpoint(GB_gameboy_t *gb, char *arguments)
gb->breakpoints[index] = result;
gb->n_breakpoints++;
gb_log(gb, "Breakpoint set at %04x\n", result);
GB_log(gb, "Breakpoint set at %04x\n", result);
return true;
}
static bool delete(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments)) == 0) {
gb_log(gb, "Delete all breakpoints? ");
GB_log(gb, "Delete all breakpoints? ");
char *answer = gb->input_callback(gb);
if (answer[0] == 'Y' || answer[0] == 'y') {
free(gb->breakpoints);
@ -471,13 +471,13 @@ static bool delete(GB_gameboy_t *gb, char *arguments)
}
bool error;
unsigned short result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
uint16_t result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
if (error) return true;
unsigned short index = find_breakpoint(gb, result);
uint16_t index = find_breakpoint(gb, result);
if (index >= gb->n_breakpoints || gb->breakpoints[index] != result) {
gb_log(gb, "No breakpoint set at %04x\n", result);
GB_log(gb, "No breakpoint set at %04x\n", result);
return true;
}
@ -485,33 +485,33 @@ static bool delete(GB_gameboy_t *gb, char *arguments)
gb->n_breakpoints--;
gb->breakpoints = realloc(gb->breakpoints, gb->n_breakpoints * sizeof(gb->breakpoints[0]));
gb_log(gb, "Breakpoint removed from %04x\n", result);
GB_log(gb, "Breakpoint removed from %04x\n", result);
return true;
}
static bool list(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: list\n");
GB_log(gb, "Usage: list\n");
return true;
}
if (gb->n_breakpoints == 0) {
gb_log(gb, "No breakpoints set.\n");
GB_log(gb, "No breakpoints set.\n");
return true;
}
gb_log(gb, "%d breakpoint(s) set:\n", gb->n_breakpoints);
for (unsigned short i = 0; i < gb->n_breakpoints; i++) {
gb_log(gb, " %d. %04x\n", i + 1, gb->breakpoints[i]);
GB_log(gb, "%d breakpoint(s) set:\n", gb->n_breakpoints);
for (uint16_t i = 0; i < gb->n_breakpoints; i++) {
GB_log(gb, " %d. %04x\n", i + 1, gb->breakpoints[i]);
}
return true;
}
static bool should_break(GB_gameboy_t *gb, unsigned short addr)
static bool should_break(GB_gameboy_t *gb, uint16_t addr)
{
unsigned short index = find_breakpoint(gb, addr);
uint16_t index = find_breakpoint(gb, addr);
if (index < gb->n_breakpoints && gb->breakpoints[index] == addr) {
return true;
}
@ -521,14 +521,14 @@ static bool should_break(GB_gameboy_t *gb, unsigned short addr)
static bool print(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments)) == 0) {
gb_log(gb, "Usage: print <expression>\n");
GB_log(gb, "Usage: print <expression>\n");
return true;
}
bool error;
unsigned short result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
uint16_t result = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
if (!error) {
gb_log(gb, "=%04x\n", result);
GB_log(gb, "=%04x\n", result);
}
return true;
}
@ -536,18 +536,18 @@ static bool print(GB_gameboy_t *gb, char *arguments)
static bool examine(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments)) == 0) {
gb_log(gb, "Usage: examine <expression>\n");
GB_log(gb, "Usage: examine <expression>\n");
return true;
}
bool error;
unsigned short addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
uint16_t addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error);
if (!error) {
gb_log(gb, "%4x: ", addr);
GB_log(gb, "%4x: ", addr);
for (int i = 0; i < 16; i++) {
gb_log(gb, "%02x ", read_memory(gb, addr + i));
GB_log(gb, "%02x ", GB_read_memory(gb, addr + i));
}
gb_log(gb, "\n");
GB_log(gb, "\n");
}
return true;
}
@ -555,41 +555,41 @@ static bool examine(GB_gameboy_t *gb, char *arguments)
static bool mbc(GB_gameboy_t *gb, char *arguments)
{
if (strlen(lstrip(arguments))) {
gb_log(gb, "Usage: mbc\n");
GB_log(gb, "Usage: mbc\n");
return true;
}
const GB_cartridge_t *cartridge = gb->cartridge_type;
if (cartridge->has_ram) {
gb_log(gb, "Cartrdige includes%s RAM: %zx\n", cartridge->has_battery? " battery-backed": "", gb->mbc_ram_size);
GB_log(gb, "Cartrdige includes%s RAM: %x\n", cartridge->has_battery? " battery-backed": "", gb->mbc_ram_size);
}
else {
gb_log(gb, "No cartridge RAM\n");
GB_log(gb, "No cartridge RAM\n");
}
if (cartridge->mbc_type) {
gb_log(gb, "MBC%d\n", cartridge->mbc_type);
gb_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank);
GB_log(gb, "MBC%d\n", cartridge->mbc_type);
GB_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank);
if (cartridge->has_ram) {
gb_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank);
gb_log(gb, "RAM is curently %s\n", gb->mbc_ram_enable? "enabled" : "disabled");
GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank);
GB_log(gb, "RAM is curently %s\n", gb->mbc_ram_enable? "enabled" : "disabled");
}
if (cartridge->mbc_type == MBC1) {
gb_log(gb, "MBC1 banking mode is %s\n", gb->mbc_ram_banking? "RAM" : "ROM");
GB_log(gb, "MBC1 banking mode is %s\n", gb->mbc_ram_banking? "RAM" : "ROM");
}
}
else {
gb_log(gb, "No MBC\n");
GB_log(gb, "No MBC\n");
}
if (cartridge->has_rumble) {
gb_log(gb, "Cart contains a rumble pak\n");
GB_log(gb, "Cart contains a rumble pak\n");
}
if (cartridge->has_rtc) {
gb_log(gb, "Cart contains a real time clock\n");
GB_log(gb, "Cart contains a real time clock\n");
}
@ -622,8 +622,8 @@ static bool help(GB_gameboy_t *gb, char *arguments)
const debugger_command_t *command = commands;
for (size_t i = sizeof(commands) / sizeof(*command); i--; command++) {
if (command->help_string) {
gb_attributed_log(gb, GB_LOG_BOLD, "%s", command->command);
gb_log(gb, ": %s\n", command->help_string);
GB_attributed_log(gb, GB_LOG_BOLD, "%s", command->command);
GB_log(gb, ": %s\n", command->help_string);
}
}
return true;
@ -643,13 +643,13 @@ static const debugger_command_t *find_command(const char *string)
return NULL;
}
void debugger_call_hook(GB_gameboy_t *gb)
void GB_debugger_call_hook(GB_gameboy_t *gb)
{
/* Called just after the CPU calls a function/enters an interrupt/etc... */
if (gb->stack_leak_detection) {
if (gb->debug_call_depth >= sizeof(gb->sp_for_call_depth) / sizeof(gb->sp_for_call_depth[0])) {
gb_log(gb, "Potential stack overflow detected (Functions nest too much). \n");
GB_log(gb, "Potential stack overflow detected (Functions nest too much). \n");
gb->debug_stopped = true;
}
else {
@ -661,7 +661,7 @@ void debugger_call_hook(GB_gameboy_t *gb)
gb->debug_call_depth++;
}
void debugger_ret_hook(GB_gameboy_t *gb)
void GB_debugger_ret_hook(GB_gameboy_t *gb)
{
/* Called just before the CPU runs ret/reti */
@ -669,13 +669,13 @@ void debugger_ret_hook(GB_gameboy_t *gb)
if (gb->stack_leak_detection) {
if (gb->debug_call_depth < 0) {
gb_log(gb, "Function finished without a stack leak.\n");
GB_log(gb, "Function finished without a stack leak.\n");
gb->debug_stopped = true;
}
else {
if (gb->registers[GB_REGISTER_SP] != gb->sp_for_call_depth[gb->debug_call_depth]) {
gb_log(gb, "Stack leak detected for function %04x!\n", gb->addr_for_call_depth[gb->debug_call_depth]);
gb_log(gb, "SP is %04x, should be %04x.\n", gb->registers[GB_REGISTER_SP],
GB_log(gb, "Stack leak detected for function %04x!\n", gb->addr_for_call_depth[gb->debug_call_depth]);
GB_log(gb, "SP is %04x, should be %04x.\n", gb->registers[GB_REGISTER_SP],
gb->sp_for_call_depth[gb->debug_call_depth]);
gb->debug_stopped = true;
}
@ -683,7 +683,7 @@ void debugger_ret_hook(GB_gameboy_t *gb)
}
}
void debugger_run(GB_gameboy_t *gb)
void GB_debugger_run(GB_gameboy_t *gb)
{
char *input = NULL;
if (gb->debug_next_command && gb->debug_call_depth <= 0) {
@ -693,7 +693,7 @@ void debugger_run(GB_gameboy_t *gb)
gb->debug_stopped = true;
}
if (gb->debug_stopped) {
cpu_disassemble(gb, gb->pc, 5);
GB_cpu_disassemble(gb, gb->pc, 5);
}
next_command:
if (input) {
@ -701,8 +701,8 @@ next_command:
}
if (!gb->debug_stopped && should_break(gb, gb->pc)) {
gb->debug_stopped = true;
gb_log(gb, "Breakpoint: PC = %04x\n", gb->pc);
cpu_disassemble(gb, gb->pc, 5);
GB_log(gb, "Breakpoint: PC = %04x\n", gb->pc);
GB_cpu_disassemble(gb, gb->pc, 5);
}
if (gb->debug_stopped) {
gb->debug_next_command = false;
@ -731,7 +731,7 @@ next_command:
}
}
else {
gb_log(gb, "%s: no such command.\n", command_string);
GB_log(gb, "%s: no such command.\n", command_string);
goto next_command;
}

View File

@ -2,8 +2,8 @@
#define debugger_h
#include "gb.h"
void debugger_run(GB_gameboy_t *gb);
void debugger_call_hook(GB_gameboy_t *gb);
void debugger_ret_hook(GB_gameboy_t *gb);
void GB_debugger_run(GB_gameboy_t *gb);
void GB_debugger_call_hook(GB_gameboy_t *gb);
void GB_debugger_ret_hook(GB_gameboy_t *gb);
#endif /* debugger_h */

View File

@ -9,14 +9,14 @@
#pragma pack(push, 1)
typedef struct {
unsigned char y;
unsigned char x;
unsigned char tile;
unsigned char flags;
uint8_t y;
uint8_t x;
uint8_t tile;
uint8_t flags;
} GB_sprite_t;
#pragma pack(pop)
static uint32_t get_pixel(GB_gameboy_t *gb, unsigned char x, unsigned char y)
static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
{
/*
Bit 7 - LCD Display Enable (0=Off, 1=On)
@ -28,17 +28,17 @@ static uint32_t get_pixel(GB_gameboy_t *gb, unsigned char x, unsigned char y)
Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On)
Bit 0 - BG Display (for CGB see below) (0=Off, 1=On)
*/
unsigned short map = 0x1800;
unsigned char tile = 0;
unsigned char attributes = 0;
unsigned char sprite_palette = 0;
unsigned short tile_address = 0;
unsigned char background_pixel = 0, sprite_pixel = 0;
uint16_t map = 0x1800;
uint8_t tile = 0;
uint8_t attributes = 0;
uint8_t sprite_palette = 0;
uint16_t tile_address = 0;
uint8_t background_pixel = 0, sprite_pixel = 0;
GB_sprite_t *sprite = (GB_sprite_t *) &gb->oam;
unsigned char sprites_in_line = 0;
uint8_t sprites_in_line = 0;
bool lcd_8_16_mode = (gb->io_registers[GB_IO_LCDC] & 4) != 0;
bool sprites_enabled = (gb->io_registers[GB_IO_LCDC] & 2) != 0;
unsigned char lowest_sprite_x = 0xFF;
uint8_t lowest_sprite_x = 0xFF;
bool use_obp1 = false, priority = false;
bool in_window = false;
if (gb->effective_window_enabled && (gb->io_registers[GB_IO_LCDC] & 0x20)) { /* Window Enabled */
@ -49,13 +49,13 @@ static uint32_t get_pixel(GB_gameboy_t *gb, unsigned char x, unsigned char y)
if (sprites_enabled) {
// Loop all sprites
for (unsigned char i = 40; i--; sprite++) {
for (uint8_t i = 40; i--; sprite++) {
int sprite_y = sprite->y - 16;
int sprite_x = sprite->x - 8;
// Is sprite in our line?
if (sprite_y <= y && sprite_y + (lcd_8_16_mode? 16:8) > y) {
unsigned char tile_x, tile_y, current_sprite_pixel;
unsigned short line_address;
uint8_t tile_x, tile_y, current_sprite_pixel;
uint16_t line_address;
// Limit to 10 sprites in one scan line.
if (++sprites_in_line == 11) break;
// Does not overlap our pixel.
@ -129,7 +129,7 @@ static uint32_t get_pixel(GB_gameboy_t *gb, unsigned char x, unsigned char y)
tile_address = tile * 0x10;
}
else {
tile_address = (signed char) tile * 0x10 + 0x1000;
tile_address = (int8_t) tile * 0x10 + 0x1000;
}
if (attributes & 0x8) {
tile_address += 0x2000;
@ -171,7 +171,7 @@ void display_vblank(GB_gameboy_t *gb)
if (gb->turbo) {
struct timeval now;
gettimeofday(&now, NULL);
signed long nanoseconds = (now.tv_usec) * 1000 + now.tv_sec * 1000000000L;
int64_t nanoseconds = (now.tv_usec) * 1000 + now.tv_sec * 1000000000L;
if (nanoseconds <= gb->last_vblank + FRAME_LENGTH) {
return;
}
@ -209,7 +209,7 @@ void display_vblank(GB_gameboy_t *gb)
struct timespec sleep = {0,};
gettimeofday(&now, NULL);
signed long nanoseconds = (now.tv_usec) * 1000 + now.tv_sec * 1000000000L;
if (labs(nanoseconds - gb->last_vblank) < FRAME_LENGTH ) {
if (labs((signed long)(nanoseconds - gb->last_vblank)) < FRAME_LENGTH ) {
sleep.tv_nsec = (FRAME_LENGTH + gb->last_vblank - nanoseconds);
nanosleep(&sleep, NULL);
@ -221,21 +221,21 @@ void display_vblank(GB_gameboy_t *gb)
}
}
static inline unsigned char scale_channel(unsigned char x)
static inline uint8_t scale_channel(uint8_t x)
{
x &= 0x1f;
return (x << 3) | (x >> 2);
}
void palette_changed(GB_gameboy_t *gb, bool background_palette, unsigned char index)
void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index)
{
unsigned char *palette_data = background_palette? gb->background_palletes_data : gb->sprite_palletes_data;
unsigned short color = palette_data[index & ~1] | (palette_data[index | 1] << 8);
uint8_t *palette_data = background_palette? gb->background_palletes_data : gb->sprite_palletes_data;
uint16_t color = palette_data[index & ~1] | (palette_data[index | 1] << 8);
// No need to &, scale channel does that.
unsigned char r = scale_channel(color);
unsigned char g = scale_channel(color >> 5);
unsigned char b = scale_channel(color >> 10);
uint8_t r = scale_channel(color);
uint8_t g = scale_channel(color >> 5);
uint8_t b = scale_channel(color >> 10);
assert (gb->rgb_encode_callback);
(background_palette? gb->background_palletes_rgb : gb->sprite_palletes_rgb)[index / 2] = gb->rgb_encode_callback(gb, r, g, b);
}
@ -257,7 +257,7 @@ void palette_changed(GB_gameboy_t *gb, bool background_palette, unsigned char in
#define MODE1_LENGTH 204
#define LINE_LENGTH (MODE2_LENGTH + MODE3_LENGTH + MODE1_LENGTH) // = 456
void display_run(GB_gameboy_t *gb)
void GB_display_run(GB_gameboy_t *gb)
{
/*
Display controller bug: For some reason, the OAM STAT interrupt is called, as expected, for LY = 0..143.
@ -271,10 +271,10 @@ void display_run(GB_gameboy_t *gb)
http://board.byuu.org/phpbb3/viewtopic.php?p=25527#p25531
*/
unsigned char previous_stat_interrupt_line = gb->stat_interrupt_line;
uint8_t previous_stat_interrupt_line = gb->stat_interrupt_line;
gb->stat_interrupt_line = false;
unsigned char last_mode = gb->io_registers[GB_IO_STAT] & 3;
uint8_t last_mode = gb->io_registers[GB_IO_STAT] & 3;
gb->io_registers[GB_IO_STAT] &= ~3;
if (gb->display_cycles >= LCDC_PERIOD) {
@ -360,7 +360,7 @@ void display_run(GB_gameboy_t *gb)
/* Render. This chunk is outside the Mode 3 if, because otherwise we might not render some pixels, since this
function only runs between atomic CPU changes, and not every clock. */
signed short current_lcdc_x = ((gb->display_cycles % LINE_LENGTH - MODE2_LENGTH) & ~7) - (gb->effective_scx & 0x7);
int16_t current_lcdc_x = ((gb->display_cycles % LINE_LENGTH - MODE2_LENGTH) & ~7) - (gb->effective_scx & 0x7);
for (;gb->previous_lcdc_x < current_lcdc_x; gb->previous_lcdc_x++) {
if (gb->previous_lcdc_x >= 160) {
continue;

View File

@ -2,6 +2,6 @@
#define display_h
#include "gb.h"
void display_run(GB_gameboy_t *gb);
void palette_changed(GB_gameboy_t *gb, bool background_palette, unsigned char index);
void GB_display_run(GB_gameboy_t *gb);
void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index);
#endif /* display_h */

View File

@ -59,7 +59,7 @@ static const GB_cartridge_t cart_defs[256] = {
{ NO_MBC, true , true , false, false}, // FFh HuC1+RAM+BATTERY
};
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;
vasprintf(&string, fmt, args);
@ -75,19 +75,19 @@ void gb_attributed_logv(GB_gameboy_t *gb, gb_log_attributes attributes, const ch
free(string);
}
void gb_attributed_log(GB_gameboy_t *gb, gb_log_attributes attributes, const char *fmt, ...)
void GB_attributed_log(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
gb_attributed_logv(gb, attributes, fmt, args);
GB_attributed_logv(gb, attributes, fmt, args);
va_end(args);
}
void gb_log(GB_gameboy_t *gb,const char *fmt, ...)
void GB_log(GB_gameboy_t *gb,const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
gb_attributed_logv(gb, 0, fmt, args);
GB_attributed_logv(gb, 0, fmt, args);
va_end(args);
}
@ -109,7 +109,7 @@ static char *default_input_callback(GB_gameboy_t *gb)
return expression;
}
void gb_init(GB_gameboy_t *gb)
void GB_init(GB_gameboy_t *gb)
{
memset(gb, 0, sizeof(*gb));
gb->magic = (uintptr_t)'SAME';
@ -136,7 +136,7 @@ void gb_init(GB_gameboy_t *gb)
gb->io_registers[GB_IO_JOYP] = 0xF;
}
void gb_init_cgb(GB_gameboy_t *gb)
void GB_init_cgb(GB_gameboy_t *gb)
{
memset(gb, 0, sizeof(*gb));
gb->magic = (uintptr_t)'SAME';
@ -160,7 +160,7 @@ void gb_init_cgb(GB_gameboy_t *gb)
gb->io_registers[GB_IO_JOYP] = 0xF;
}
void gb_free(GB_gameboy_t *gb)
void GB_free(GB_gameboy_t *gb)
{
if (gb->ram) {
free(gb->ram);
@ -182,16 +182,16 @@ void gb_free(GB_gameboy_t *gb)
}
}
int gb_load_bios(GB_gameboy_t *gb, const char *path)
int GB_load_boot_rom(GB_gameboy_t *gb, const char *path)
{
FILE *f = fopen(path, "r");
if (!f) return errno;
fread(gb->bios, sizeof(gb->bios), 1, f);
fread(gb->boot_rom, sizeof(gb->boot_rom), 1, f);
fclose(f);
return 0;
}
int gb_load_rom(GB_gameboy_t *gb, const char *path)
int GB_load_rom(GB_gameboy_t *gb, const char *path)
{
FILE *f = fopen(path, "r");
if (!f) return errno;
@ -228,7 +228,7 @@ static bool dump_section(FILE *f, const void *src, uint32_t size)
#define DUMP_SECTION(gb, f, section) dump_section(f, GB_GET_SECTION(gb, section), GB_SECTION_SIZE(section))
/* Todo: we need a sane and protable save state format. */
int gb_save_state(GB_gameboy_t *gb, const char *path)
int GB_save_state(GB_gameboy_t *gb, const char *path)
{
FILE *f = fopen(path, "w");
if (!f) {
@ -290,7 +290,7 @@ static bool read_section(FILE *f, void *dest, uint32_t size)
#define READ_SECTION(gb, f, section) read_section(f, GB_GET_SECTION(gb, section), GB_SECTION_SIZE(section))
int gb_load_state(GB_gameboy_t *gb, const char *path)
int GB_load_state(GB_gameboy_t *gb, const char *path)
{
GB_gameboy_t save;
@ -313,31 +313,31 @@ int gb_load_state(GB_gameboy_t *gb, const char *path)
if (!READ_SECTION(&save, f, video )) goto error;
if (gb->magic != save.magic) {
gb_log(gb, "File is not a save state, or is from an incompatible operating system.\n");
GB_log(gb, "File is not a save state, or is from an incompatible operating system.\n");
errno = -1;
goto error;
}
if (gb->version != save.version) {
gb_log(gb, "Save state is for a different version of SameBoy.\n");
GB_log(gb, "Save state is for a different version of SameBoy.\n");
errno = -1;
goto error;
}
if (gb->mbc_ram_size != save.mbc_ram_size) {
gb_log(gb, "Save state has non-matching MBC RAM size.\n");
GB_log(gb, "Save state has non-matching MBC RAM size.\n");
errno = -1;
goto error;
}
if (gb->ram_size != save.ram_size) {
gb_log(gb, "Save state has non-matching RAM size. Try changing emulated model.\n");
GB_log(gb, "Save state has non-matching RAM size. Try changing emulated model.\n");
errno = -1;
goto error;
}
if (gb->vram_size != save.vram_size) {
gb_log(gb, "Save state has non-matching VRAM size. Try changing emulated model.\n");
GB_log(gb, "Save state has non-matching VRAM size. Try changing emulated model.\n");
errno = -1;
goto error;
}
@ -364,7 +364,7 @@ error:
return errno;
}
int gb_save_battery(GB_gameboy_t *gb, const char *path)
int GB_save_battery(GB_gameboy_t *gb, const char *path)
{
if (!gb->cartridge_type->has_battery) return 0; // Nothing to save.
if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */
@ -395,7 +395,7 @@ int gb_save_battery(GB_gameboy_t *gb, const char *path)
}
/* Loading will silently stop if the format is incomplete */
void gb_load_battery(GB_gameboy_t *gb, const char *path)
void GB_load_battery(GB_gameboy_t *gb, const char *path)
{
FILE *f = fopen(path, "r");
if (!f) {
@ -433,39 +433,39 @@ exit:
return;
}
void gb_run(GB_gameboy_t *gb)
void GB_run(GB_gameboy_t *gb)
{
update_joyp(gb);
debugger_run(gb);
cpu_run(gb);
GB_update_joyp(gb);
GB_debugger_run(gb);
GB_cpu_run(gb);
}
void gb_set_pixels_output(GB_gameboy_t *gb, uint32_t *output)
void GB_set_pixels_output(GB_gameboy_t *gb, uint32_t *output)
{
gb->screen = output;
}
void gb_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback)
void GB_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback)
{
gb->vblank_callback = callback;
}
void gb_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback)
void GB_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback)
{
gb->log_callback = callback;
}
void gb_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
{
gb->input_callback = callback;
}
void gb_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
{
gb->rgb_encode_callback = callback;
}
void gb_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate)
void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate)
{
if (gb->audio_buffer) {
free(gb->audio_buffer);

159
Core/gb.h
View File

@ -1,5 +1,5 @@
#ifndef gb_h
#define gb_h
#ifndef GB_h
#define GB_h
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@ -8,7 +8,7 @@
#include "save_struct.h"
#define GB_STRUCT_VERSION 8
#define GB_STRUCT_VERSION 9
enum {
GB_REGISTER_AF,
@ -146,14 +146,14 @@ typedef enum {
GB_LOG_DASHED_UNDERLINE = 2,
GB_LOG_UNDERLINE = 4,
GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE
} gb_log_attributes;
} GB_log_attributes;
struct GB_gameboy_s;
typedef struct GB_gameboy_s GB_gameboy_t;
typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, gb_log_attributes attributes);
typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes);
typedef char *(*GB_input_callback_t)(GB_gameboy_t *gb);
typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, unsigned char r, unsigned char g, unsigned char b);
typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b);
typedef struct {
enum {
@ -172,21 +172,32 @@ typedef struct {
/* When state saving, each section is dumped independently of other sections.
This allows adding data to the end of the section without worrying about future compatibility.
Some other changes might be "safe" as well. */
Some other changes might be "safe" as well.
This struct is not packed, but dumped sections exclusively use types that have the same alignment in both 32 and 64
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");
typedef struct GB_gameboy_s {
GB_SECTION(header,
uintptr_t magic; // States are currently platform dependent
int version; // and version dependent
/* The magic makes sure a state file is:
- Indeed a SameBoy state file.
- Has the same endianess has the current platform. */
uint32_t magic;
/* The version field makes sure we don't load save state files with a completely different structure.
This happens when struct fields are removed/resized in an backward incompatible manner. */
uint32_t version;
);
GB_SECTION(core_state,
/* Registers */
unsigned short pc;
unsigned short registers[GB_REGISTERS_16_BIT];
uint16_t pc;
uint16_t registers[GB_REGISTERS_16_BIT];
bool ime;
unsigned char interrupt_enable;
unsigned char cgb_ram_bank;
uint8_t interrupt_enable;
uint8_t cgb_ram_bank;
/* CPU and General Hardware Flags*/
bool cgb_mode;
@ -194,23 +205,23 @@ typedef struct GB_gameboy_s {
bool cgb_double_speed;
bool halted;
bool stopped;
bool bios_finished;
bool boot_rom_finished;
);
/* HDMA */
GB_SECTION(hdma,
bool hdma_on;
bool hdma_on_hblank;
unsigned char hdma_steps_left;
unsigned short hdma_cycles;
unsigned short hdma_current_src, hdma_current_dest;
uint8_t hdma_steps_left;
uint16_t hdma_cycles;
uint16_t hdma_current_src, hdma_current_dest;
);
/* MBC */
GB_SECTION(mbc,
unsigned short mbc_rom_bank;
unsigned char mbc_ram_bank;
size_t mbc_ram_size;
uint16_t mbc_rom_bank;
uint8_t mbc_ram_bank;
uint32_t mbc_ram_size;
bool mbc_ram_enable;
bool mbc_ram_banking;
);
@ -218,18 +229,18 @@ typedef struct GB_gameboy_s {
/* HRAM and HW Registers */
GB_SECTION(hram,
unsigned char hram[0xFFFF - 0xFF80];
unsigned char io_registers[0x80];
uint8_t hram[0xFFFF - 0xFF80];
uint8_t io_registers[0x80];
);
/* Timing */
GB_SECTION(timing,
signed long last_vblank;
unsigned long display_cycles;
unsigned long div_cycles;
unsigned long tima_cycles;
unsigned long dma_cycles;
double apu_cycles;
int64_t last_vblank;
uint32_t display_cycles;
uint32_t div_cycles;
uint32_t tima_cycles;
uint32_t dma_cycles;
GB_aligned_double apu_cycles;
);
/* APU */
@ -241,47 +252,45 @@ typedef struct GB_gameboy_s {
GB_SECTION(rtc,
union {
struct {
unsigned char rtc_seconds;
unsigned char rtc_minutes;
unsigned char rtc_hours;
unsigned char rtc_days;
unsigned char rtc_high;
uint8_t rtc_seconds;
uint8_t rtc_minutes;
uint8_t rtc_hours;
uint8_t rtc_days;
uint8_t rtc_high;
};
unsigned char rtc_data[5];
uint8_t rtc_data[5];
};
time_t last_rtc_second;
);
/* Video Display */
GB_SECTION(video,
unsigned long vram_size; // Different between CGB and DMG
unsigned char cgb_vram_bank;
unsigned char oam[0xA0];
unsigned char background_palletes_data[0x40];
unsigned char sprite_palletes_data[0x40];
uint32_t vram_size; // Different between CGB and DMG
uint8_t cgb_vram_bank;
uint8_t oam[0xA0];
uint8_t background_palletes_data[0x40];
uint8_t sprite_palletes_data[0x40];
uint32_t background_palletes_rgb[0x20];
uint32_t sprite_palletes_rgb[0x20];
GB_PADDING(bool, ly144_bug_oam);
GB_PADDING(bool, ly144_bug_hblank);
signed short previous_lcdc_x;
unsigned char padding;
int16_t previous_lcdc_x;
uint8_t padding;
bool effective_window_enabled;
unsigned char effective_window_y;
uint8_t effective_window_y;
bool stat_interrupt_line;
unsigned char effective_scx;
uint8_t effective_scx;
);
/* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */
/* ROM */
unsigned char *rom;
size_t rom_size;
uint8_t *rom;
uint32_t rom_size;
const GB_cartridge_t *cartridge_type;
/* Various RAMs */
unsigned char *ram;
unsigned char *vram;
unsigned char *mbc_ram;
uint8_t *ram;
uint8_t *vram;
uint8_t *mbc_ram;
/* I/O */
uint32_t *screen;
@ -305,17 +314,17 @@ typedef struct GB_gameboy_s {
/* Debugger */
int debug_call_depth;
bool debug_fin_command, debug_next_command;
unsigned short n_breakpoints;
unsigned short *breakpoints;
uint16_t n_breakpoints;
uint16_t *breakpoints;
bool stack_leak_detection;
unsigned short sp_for_call_depth[0x200]; /* Should be much more than enough */
unsigned short addr_for_call_depth[0x200];
uint16_t sp_for_call_depth[0x200]; /* Should be much more than enough */
uint16_t addr_for_call_depth[0x200];
bool debug_stopped;
/* Misc */
bool turbo;
unsigned long ram_size; // Different between CGB and DMG
unsigned char bios[0x900];
uint32_t ram_size; // Different between CGB and DMG
uint8_t boot_rom[0x900];
} GB_gameboy_t;
@ -325,23 +334,23 @@ typedef struct GB_gameboy_s {
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#endif
void gb_init(GB_gameboy_t *gb);
void gb_init_cgb(GB_gameboy_t *gb);
void gb_free(GB_gameboy_t *gb);
int gb_load_bios(GB_gameboy_t *gb, const char *path);
int gb_load_rom(GB_gameboy_t *gb, const char *path);
int gb_save_battery(GB_gameboy_t *gb, const char *path);
void gb_load_battery(GB_gameboy_t *gb, const char *path);
int gb_save_state(GB_gameboy_t *gb, const char *path);
int gb_load_state(GB_gameboy_t *gb, const char *path);
void gb_run(GB_gameboy_t *gb);
void gb_set_pixels_output(GB_gameboy_t *gb, uint32_t *output);
void gb_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback);
void gb_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback);
void gb_log(GB_gameboy_t *gb, const char *fmt, ...) __printflike(2, 3);
void gb_attributed_log(GB_gameboy_t *gb, gb_log_attributes attributes, const char *fmt, ...) __printflike(3, 4);
void gb_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback);
void gb_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate);
void gb_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback);
void GB_init(GB_gameboy_t *gb);
void GB_init_cgb(GB_gameboy_t *gb);
void GB_free(GB_gameboy_t *gb);
int GB_load_boot_rom(GB_gameboy_t *gb, const char *path);
int GB_load_rom(GB_gameboy_t *gb, const char *path);
int GB_save_battery(GB_gameboy_t *gb, const char *path);
void GB_load_battery(GB_gameboy_t *gb, const char *path);
int GB_save_state(GB_gameboy_t *gb, const char *path);
int GB_load_state(GB_gameboy_t *gb, const char *path);
void GB_run(GB_gameboy_t *gb);
void GB_set_pixels_output(GB_gameboy_t *gb, uint32_t *output);
void GB_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback);
void GB_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback);
void GB_log(GB_gameboy_t *gb, const char *fmt, ...) __printflike(2, 3);
void GB_attributed_log(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, ...) __printflike(3, 4);
void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback);
void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate);
void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback);
#endif /* gb_h */
#endif /* GB_h */

View File

@ -2,10 +2,10 @@
#include "gb.h"
#include "joypad.h"
void update_joyp(GB_gameboy_t *gb)
void GB_update_joyp(GB_gameboy_t *gb)
{
unsigned char key_selection = 0;
unsigned char previous_state = 0;
uint8_t key_selection = 0;
uint8_t previous_state = 0;
/* Todo: add delay to key selection */
previous_state = gb->io_registers[GB_IO_JOYP] & 0xF;
@ -19,21 +19,21 @@ void update_joyp(GB_gameboy_t *gb)
case 2:
/* Direction keys */
for (unsigned char i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i;
}
break;
case 1:
/* Other keys */
for (unsigned char i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i;
}
break;
case 0:
/* Todo: verifiy this is correct */
for (unsigned char i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i;
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i;
}

View File

@ -2,7 +2,7 @@
#define joypad_h
#include "gb.h"
void update_joyp(GB_gameboy_t *gb);
void update_keys_status(GB_gameboy_t *gb);
void GB_update_joyp(GB_gameboy_t *gb);
void GB_update_keys_status(GB_gameboy_t *gb);
#endif /* joypad_h */

View File

@ -5,17 +5,17 @@
#include "display.h"
#include "memory.h"
typedef unsigned char GB_read_function_t(GB_gameboy_t *gb, unsigned short addr);
typedef void GB_write_function_t(GB_gameboy_t *gb, unsigned short addr, unsigned char value);
typedef uint8_t GB_read_function_t(GB_gameboy_t *gb, uint16_t addr);
typedef void GB_write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value);
static unsigned char read_rom(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_rom(GB_gameboy_t *gb, uint16_t addr)
{
if (addr < 0x100 && !gb->bios_finished) {
return gb->bios[addr];
if (addr < 0x100 && !gb->boot_rom_finished) {
return gb->boot_rom[addr];
}
if (addr >= 0x200 && addr < 0x900 && gb->is_cgb && !gb->bios_finished) {
return gb->bios[addr];
if (addr >= 0x200 && addr < 0x900 && gb->is_cgb && !gb->boot_rom_finished) {
return gb->boot_rom[addr];
}
if (!gb->rom_size) {
@ -24,7 +24,7 @@ static unsigned char read_rom(GB_gameboy_t *gb, unsigned short addr)
return gb->rom[addr];
}
static unsigned char read_mbc_rom(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_mbc_rom(GB_gameboy_t *gb, uint16_t addr)
{
if (gb->mbc_rom_bank >= gb->rom_size / 0x4000) {
return 0xFF;
@ -32,15 +32,15 @@ static unsigned char read_mbc_rom(GB_gameboy_t *gb, unsigned short addr)
return gb->rom[(addr & 0x3FFF) + gb->mbc_rom_bank * 0x4000];
}
static unsigned char read_vram(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr)
{
if ((gb->io_registers[GB_IO_STAT] & 0x3) == 3) {
return 0xFF;
}
return gb->vram[(addr & 0x1FFF) + (unsigned short) gb->cgb_vram_bank * 0x2000];
return gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000];
}
static unsigned char read_mbc_ram(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr)
{
if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) {
/* RTC read */
@ -50,27 +50,27 @@ static unsigned char read_mbc_ram(GB_gameboy_t *gb, unsigned short addr)
unsigned int ram_index = (addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000;
if (!gb->mbc_ram_enable)
{
gb_log(gb, "Read from %02x:%04x (%06x) (Disabled MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
GB_log(gb, "Read from %02x:%04x (%06x) (Disabled MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
return 0xFF;
}
if (ram_index >= gb->mbc_ram_size) {
gb_log(gb, "Read from %02x:%04x (%06x) (Unmapped MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
GB_log(gb, "Read from %02x:%04x (%06x) (Unmapped MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
return 0xFF;
}
return gb->mbc_ram[(addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000];
}
static unsigned char read_ram(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_ram(GB_gameboy_t *gb, uint16_t addr)
{
return gb->ram[addr & 0x0FFF];
}
static unsigned char read_banked_ram(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_banked_ram(GB_gameboy_t *gb, uint16_t addr)
{
return gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000];
}
static unsigned char read_high_memory(GB_gameboy_t *gb, unsigned short addr)
static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
{
if (addr < 0xFE00) {
@ -150,7 +150,7 @@ static unsigned char read_high_memory(GB_gameboy_t *gb, unsigned short addr)
if (!gb->is_cgb) {
return 0xFF;
}
unsigned char index_reg = (addr & 0xFF) - 1;
uint8_t index_reg = (addr & 0xFF) - 1;
return ((addr & 0xFF) == GB_IO_BGPD?
gb->background_palletes_data :
gb->sprite_palletes_data)[gb->io_registers[index_reg] & 0x3F];
@ -165,7 +165,7 @@ static unsigned char read_high_memory(GB_gameboy_t *gb, unsigned short addr)
default:
if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) {
return apu_read(gb, addr & 0xFF);
return GB_apu_read(gb, addr & 0xFF);
}
return 0xFF;
}
@ -192,7 +192,7 @@ static GB_read_function_t * const read_map[] =
read_high_memory, read_high_memory, /* EXXX FXXX */
};
unsigned char read_memory(GB_gameboy_t *gb, unsigned short addr)
uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
{
if (addr < 0xFF00 && gb->dma_cycles) {
/* Todo: can we access IO registers during DMA? */
@ -201,7 +201,7 @@ unsigned char read_memory(GB_gameboy_t *gb, unsigned short addr)
return read_map[addr >> 12](gb, addr);
}
static void write_mbc(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
if (gb->cartridge_type->mbc_type == NO_MBC) return;
switch (addr >> 12) {
@ -223,7 +223,7 @@ static void write_mbc(GB_gameboy_t *gb, unsigned short addr, unsigned char value
case 3:
if (gb->cartridge_type->mbc_type != MBC5) goto bank_low;
if (value > 1) {
gb_log(gb, "Bank overflow: [%x] <- %d\n", addr, value);
GB_log(gb, "Bank overflow: [%x] <- %d\n", addr, value);
}
gb->mbc_rom_bank = (gb->mbc_rom_bank & 0xFF) | value << 8;
break;
@ -274,16 +274,16 @@ static void write_mbc(GB_gameboy_t *gb, unsigned short addr, unsigned char value
}
}
static void write_vram(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
if ((gb->io_registers[GB_IO_STAT] & 0x3) == 3) {
//gb_log(gb, "Wrote %02x to %04x (VRAM) during mode 3\n", value, addr);
//GB_log(gb, "Wrote %02x to %04x (VRAM) during mode 3\n", value, addr);
return;
}
gb->vram[(addr & 0x1FFF) + (unsigned short) gb->cgb_vram_bank * 0x2000] = value;
gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000] = value;
}
static void write_mbc_ram(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
if (gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) {
/* RTC write*/
@ -294,30 +294,30 @@ static void write_mbc_ram(GB_gameboy_t *gb, unsigned short addr, unsigned char v
unsigned int ram_index = (addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000;
if (!gb->mbc_ram_enable)
{
gb_log(gb, "Write to %02x:%04x (%06x) (Disabled MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
GB_log(gb, "Write to %02x:%04x (%06x) (Disabled MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
return;
}
if (ram_index >= gb->mbc_ram_size) {
gb_log(gb, "Write to %02x:%04x (%06x) (Unmapped MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
GB_log(gb, "Write to %02x:%04x (%06x) (Unmapped MBC RAM)\n", gb->mbc_ram_bank, addr, ram_index);
return;
}
gb->mbc_ram[(addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000] = value;
}
static void write_ram(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
gb->ram[addr & 0x0FFF] = value;
}
static void write_banked_ram(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_banked_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000] = value;
}
static void write_high_memory(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
if (addr < 0xFE00) {
gb_log(gb, "Wrote %02x to %04x (RAM Mirror)\n", value, addr);
GB_log(gb, "Wrote %02x to %04x (RAM Mirror)\n", value, addr);
gb->ram[addr & 0x0FFF] = value;
return;
}
@ -331,7 +331,7 @@ static void write_high_memory(GB_gameboy_t *gb, unsigned short addr, unsigned ch
}
if (addr < 0xFF00) {
gb_log(gb, "Wrote %02x to %04x (Unused)\n", value, addr);
GB_log(gb, "Wrote %02x to %04x (Unused)\n", value, addr);
return;
}
@ -386,19 +386,19 @@ static void write_high_memory(GB_gameboy_t *gb, unsigned short addr, unsigned ch
return;
case GB_IO_BIOS:
gb->bios_finished = true;
gb->boot_rom_finished = true;
return;
case GB_IO_DMG_EMULATION:
if (gb->is_cgb && !gb->bios_finished) {
if (gb->is_cgb && !gb->boot_rom_finished) {
gb->cgb_mode = value != 4; /* The real "contents" of this register aren't quite known yet. */
}
return;
case GB_IO_DMA:
if (value <= 0xF1) { /* According to Pan Docs */
for (unsigned char i = 0xA0; i--;) {
gb->oam[i] = read_memory(gb, (value << 8) + i);
for (uint8_t i = 0xA0; i--;) {
gb->oam[i] = GB_read_memory(gb, (value << 8) + i);
}
}
/* else { what? } */
@ -433,11 +433,11 @@ static void write_high_memory(GB_gameboy_t *gb, unsigned short addr, unsigned ch
if (!gb->is_cgb) {
return;
}
unsigned char index_reg = (addr & 0xFF) - 1;
uint8_t index_reg = (addr & 0xFF) - 1;
((addr & 0xFF) == GB_IO_BGPD?
gb->background_palletes_data :
gb->sprite_palletes_data)[gb->io_registers[index_reg] & 0x3F] = value;
palette_changed(gb, (addr & 0xFF) == GB_IO_BGPD, gb->io_registers[index_reg] & 0x3F);
GB_palette_changed(gb, (addr & 0xFF) == GB_IO_BGPD, gb->io_registers[index_reg] & 0x3F);
if (gb->io_registers[index_reg] & 0x80) {
gb->io_registers[index_reg]++;
gb->io_registers[index_reg] |= 0x80;
@ -477,11 +477,11 @@ static void write_high_memory(GB_gameboy_t *gb, unsigned short addr, unsigned ch
default:
if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) {
apu_write(gb, addr & 0xFF, value);
GB_apu_write(gb, addr & 0xFF, value);
return;
}
if (gb->io_registers[addr & 0xFF] != 0x37) {
gb_log(gb, "Wrote %02x to %04x (HW Register)\n", value, addr);
GB_log(gb, "Wrote %02x to %04x (HW Register)\n", value, addr);
}
gb->io_registers[addr & 0xFF] = 0x37;
return;
@ -510,7 +510,7 @@ static GB_write_function_t * const write_map[] =
write_high_memory, write_high_memory, /* EXXX FXXX */
};
void write_memory(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
if (addr < 0xFF00 && gb->dma_cycles) {
/* Todo: can we access IO registers during DMA? */
@ -519,18 +519,18 @@ void write_memory(GB_gameboy_t *gb, unsigned short addr, unsigned char value)
write_map[addr >> 12](gb, addr, value);
}
void hdma_run(GB_gameboy_t *gb)
void GB_hdma_run(GB_gameboy_t *gb)
{
if (!gb->hdma_on) return;
while (gb->hdma_cycles >= 8) {
gb->hdma_cycles -= 8;
// The CGB bios uses the dest in "absolute" space, while some games use it relative to VRAM.
// The CGB boot rom uses the dest in "absolute" space, while some games use it relative to VRAM.
// This "normalizes" the dest to the CGB address space.
gb->hdma_current_dest &= 0x1fff;
gb->hdma_current_dest |= 0x8000;
if ((gb->hdma_current_src < 0x8000 || (gb->hdma_current_src >= 0xa000 && gb->hdma_current_src < 0xe000))) {
for (unsigned char i = 0; i < 0x10; i++) {
write_memory(gb, gb->hdma_current_dest + i, read_memory(gb, gb->hdma_current_src + i));
for (uint8_t i = 0; i < 0x10; i++) {
GB_write_memory(gb, gb->hdma_current_dest + i, GB_read_memory(gb, gb->hdma_current_src + i));
}
}
else {

View File

@ -2,8 +2,8 @@
#define memory_h
#include "gb.h"
unsigned char read_memory(GB_gameboy_t *gb, unsigned short addr);
void write_memory(GB_gameboy_t *gb, unsigned short addr, unsigned char value);
void hdma_run(GB_gameboy_t *gb);
uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr);
void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value);
void GB_hdma_run(GB_gameboy_t *gb);
#endif /* memory_h */

View File

@ -4,9 +4,11 @@
#define GB_PADDING(type, old_usage) type old_usage##__do_not_use
#define GB_SECTION(name, ...) __attribute__ ((aligned (sizeof(void*)))) struct {} name##_section_start; __VA_ARGS__; struct {} name##_section_end
#define GB_SECTION(name, ...) __attribute__ ((aligned (8))) struct {} name##_section_start; __VA_ARGS__; struct {} name##_section_end
#define GB_SECTION_OFFSET(name) (offsetof(GB_gameboy_t, name##_section_start))
#define GB_SECTION_SIZE(name) (offsetof(GB_gameboy_t, name##_section_end) - offsetof(GB_gameboy_t, name##_section_start))
#define GB_GET_SECTION(gb, name) ((void*)&((gb)->name##_section_start))
#define GB_aligned_double __attribute__ ((aligned (8))) double
#endif /* save_struct_h */

View File

@ -3,7 +3,7 @@
#include "memory.h"
#include "display.h"
void advance_cycles(GB_gameboy_t *gb, unsigned char cycles)
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
{
// Affected by speed boost
if (gb->dma_cycles > cycles){
@ -24,16 +24,16 @@ void advance_cycles(GB_gameboy_t *gb, unsigned char cycles)
gb->hdma_cycles += cycles;
gb->display_cycles += cycles;
gb->apu_cycles += cycles;
hdma_run(gb);
timers_run(gb);
apu_run(gb);
display_run(gb);
GB_hdma_run(gb);
GB_timers_run(gb);
GB_apu_run(gb);
GB_display_run(gb);
}
void timers_run(GB_gameboy_t *gb)
void GB_timers_run(GB_gameboy_t *gb)
{
/* Standard Timers */
static const unsigned long GB_TAC_RATIOS[] = {1024, 16, 64, 256};
static const unsigned int GB_TAC_RATIOS[] = {1024, 16, 64, 256};
if (gb->div_cycles >= DIV_CYCLES) {
gb->div_cycles -= DIV_CYCLES;

View File

@ -2,6 +2,6 @@
#define timing_h
#include "gb.h"
void advance_cycles(GB_gameboy_t *gb, unsigned char cycles);
void timers_run(GB_gameboy_t *gb);
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles);
void GB_timers_run(GB_gameboy_t *gb);
#endif /* timing_h */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef z80_cpu_h
#define z80_cpu_h
#include "gb.h"
void cpu_disassemble(GB_gameboy_t *gb, unsigned short pc, unsigned short count);
void cpu_run(GB_gameboy_t *gb);
void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count);
void GB_cpu_run(GB_gameboy_t *gb);
#endif /* z80_cpu_h */

View File

@ -5,161 +5,161 @@
#include "gb.h"
typedef void GB_opcode_t(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc);
typedef void GB_opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc);
static void ill(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ill(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, ".BYTE %02x\n", opcode);
GB_log(gb, ".BYTE %02x\n", opcode);
(*pc)++;
}
static void nop(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void nop(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "NOP\n");
GB_log(gb, "NOP\n");
(*pc)++;
}
static void stop(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void stop(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "STOP\n");
GB_log(gb, "STOP\n");
(*pc)++;
}
static char *register_names[] = {"af", "bc", "de", "hl", "sp"};
static void ld_rr_d16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
unsigned short value;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
value = read_memory(gb, (*pc)++);
value |= read_memory(gb, (*pc)++) << 8;
gb_log(gb, "LD %s, %04x\n", register_names[register_id], value);
uint8_t register_id;
uint16_t value;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
value = GB_read_memory(gb, (*pc)++);
value |= GB_read_memory(gb, (*pc)++) << 8;
GB_log(gb, "LD %s, %04x\n", register_names[register_id], value);
}
static void ld_drr_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_drr_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "LD [%s], a\n", register_names[register_id]);
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
GB_log(gb, "LD [%s], a\n", register_names[register_id]);
}
static void inc_rr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void inc_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "INC %s\n", register_names[register_id]);
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
GB_log(gb, "INC %s\n", register_names[register_id]);
}
static void inc_hr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void inc_hr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
uint8_t register_id;
(*pc)++;
register_id = ((opcode >> 4) + 1) & 0x03;
gb_log(gb, "INC %c\n", register_names[register_id][0]);
GB_log(gb, "INC %c\n", register_names[register_id][0]);
}
static void dec_hr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void dec_hr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
uint8_t register_id;
(*pc)++;
register_id = ((opcode >> 4) + 1) & 0x03;
gb_log(gb, "DEC %c\n", register_names[register_id][0]);
GB_log(gb, "DEC %c\n", register_names[register_id][0]);
}
static void ld_hr_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
uint8_t register_id;
(*pc)++;
register_id = ((opcode >> 4) + 1) & 0x03;
gb_log(gb, "LD %c, %02x\n", register_names[register_id][0], read_memory(gb, (*pc)++));
GB_log(gb, "LD %c, %02x\n", register_names[register_id][0], GB_read_memory(gb, (*pc)++));
}
static void rlca(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rlca(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RLCA\n");
GB_log(gb, "RLCA\n");
}
static void rla(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rla(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RLA\n");
GB_log(gb, "RLA\n");
}
static void ld_da16_sp(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc){
unsigned short addr;
static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc){
uint16_t addr;
(*pc)++;
addr = read_memory(gb, (*pc)++);
addr |= read_memory(gb, (*pc)++) << 8;
gb_log(gb, "LD [%04x], sp\n", addr);
addr = GB_read_memory(gb, (*pc)++);
addr |= GB_read_memory(gb, (*pc)++) << 8;
GB_log(gb, "LD [%04x], sp\n", addr);
}
static void add_hl_rr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
uint8_t register_id;
(*pc)++;
register_id = (opcode >> 4) + 1;
gb_log(gb, "ADD hl, %s\n", register_names[register_id]);
GB_log(gb, "ADD hl, %s\n", register_names[register_id]);
}
static void ld_a_drr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_drr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "LD a, [%s]\n", register_names[register_id]);
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
GB_log(gb, "LD a, [%s]\n", register_names[register_id]);
}
static void dec_rr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void dec_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "DEC %s\n", register_names[register_id]);
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
GB_log(gb, "DEC %s\n", register_names[register_id]);
}
static void inc_lr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void inc_lr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "INC %c\n", register_names[register_id][1]);
GB_log(gb, "INC %c\n", register_names[register_id][1]);
}
static void dec_lr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void dec_lr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "DEC %c\n", register_names[register_id][1]);
GB_log(gb, "DEC %c\n", register_names[register_id][1]);
}
static void ld_lr_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = (read_memory(gb, (*pc)++) >> 4) + 1;
uint8_t register_id;
register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
gb_log(gb, "LD %c, %02x\n", register_names[register_id][1], read_memory(gb, (*pc)++));
GB_log(gb, "LD %c, %02x\n", register_names[register_id][1], GB_read_memory(gb, (*pc)++));
}
static void rrca(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rrca(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "RRCA\n");
GB_log(gb, "RRCA\n");
(*pc)++;
}
static void rra(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rra(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "RRA\n");
GB_log(gb, "RRA\n");
(*pc)++;
}
static void jr_r8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void jr_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_UNDERLINE, "JR %04x\n", *pc + (signed char) read_memory(gb, (*pc)) + 1);
GB_attributed_log(gb, GB_LOG_UNDERLINE, "JR %04x\n", *pc + (int8_t) GB_read_memory(gb, (*pc)) + 1);
(*pc)++;
}
static const char *condition_code(unsigned char opcode)
static const char *condition_code(uint8_t opcode)
{
switch ((opcode >> 3) & 0x3) {
case 0:
@ -175,83 +175,83 @@ static const char *condition_code(unsigned char opcode)
return NULL;
}
static void jr_cc_r8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JR %s, %04x\n", condition_code(opcode), *pc + (signed char)read_memory(gb, (*pc)) + 1);
GB_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JR %s, %04x\n", condition_code(opcode), *pc + (int8_t)GB_read_memory(gb, (*pc)) + 1);
(*pc)++;
}
static void daa(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void daa(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "DAA\n");
GB_log(gb, "DAA\n");
(*pc)++;
}
static void cpl(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void cpl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "CPL\n");
GB_log(gb, "CPL\n");
(*pc)++;
}
static void scf(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void scf(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "SCF\n");
GB_log(gb, "SCF\n");
(*pc)++;
}
static void ccf(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ccf(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "CCF\n");
GB_log(gb, "CCF\n");
(*pc)++;
}
static void ld_dhli_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "LD [hli], a\n");
GB_log(gb, "LD [hli], a\n");
(*pc)++;
}
static void ld_dhld_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "LD [hld], a\n");
GB_log(gb, "LD [hld], a\n");
(*pc)++;
}
static void ld_a_dhli(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "LD a, [hli]\n");
GB_log(gb, "LD a, [hli]\n");
(*pc)++;
}
static void ld_a_dhld(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "LD a, [hld]\n");
GB_log(gb, "LD a, [hld]\n");
(*pc)++;
}
static void inc_dhl(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "INC [hl]\n");
GB_log(gb, "INC [hl]\n");
(*pc)++;
}
static void dec_dhl(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
gb_log(gb, "DEC [hl]\n");
GB_log(gb, "DEC [hl]\n");
(*pc)++;
}
static void ld_dhl_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LD [hl], %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "LD [hl], %02x\n", GB_read_memory(gb, (*pc)++));
}
static const char *get_src_name(unsigned char opcode)
static const char *get_src_name(uint8_t opcode)
{
unsigned char src_register_id;
unsigned char src_low;
uint8_t src_register_id;
uint8_t src_low;
src_register_id = ((opcode >> 1) + 1) & 3;
src_low = !(opcode & 1);
if (src_register_id == GB_REGISTER_AF && src_low) {
@ -265,10 +265,10 @@ static const char *get_src_name(unsigned char opcode)
return high_register_names[src_register_id];
}
static const char *get_dst_name(unsigned char opcode)
static const char *get_dst_name(uint8_t opcode)
{
unsigned char dst_register_id;
unsigned char dst_low;
uint8_t dst_register_id;
uint8_t dst_low;
dst_register_id = ((opcode >> 4) + 1) & 3;
dst_low = opcode & 8;
if (dst_register_id == GB_REGISTER_AF && dst_low) {
@ -282,326 +282,326 @@ static const char *get_dst_name(unsigned char opcode)
return high_register_names[dst_register_id];
}
static void ld_r_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_r_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LD %s, %s\n", get_dst_name(opcode), get_src_name(opcode));
GB_log(gb, "LD %s, %s\n", get_dst_name(opcode), get_src_name(opcode));
}
static void add_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void add_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "ADD %s\n", get_src_name(opcode));
GB_log(gb, "ADD %s\n", get_src_name(opcode));
}
static void adc_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void adc_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "ADC %s\n", get_src_name(opcode));
GB_log(gb, "ADC %s\n", get_src_name(opcode));
}
static void sub_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SUB %s\n", get_src_name(opcode));
GB_log(gb, "SUB %s\n", get_src_name(opcode));
}
static void sbc_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SBC %s\n", get_src_name(opcode));
GB_log(gb, "SBC %s\n", get_src_name(opcode));
}
static void and_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void and_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "AND %s\n", get_src_name(opcode));
GB_log(gb, "AND %s\n", get_src_name(opcode));
}
static void xor_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void xor_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "XOR %s\n", get_src_name(opcode));
GB_log(gb, "XOR %s\n", get_src_name(opcode));
}
static void or_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void or_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "OR %s\n", get_src_name(opcode));
GB_log(gb, "OR %s\n", get_src_name(opcode));
}
static void cp_a_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "CP %s\n", get_src_name(opcode));
GB_log(gb, "CP %s\n", get_src_name(opcode));
}
static void halt(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void halt(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "HALT\n");
GB_log(gb, "HALT\n");
}
static void ret_cc(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ret_cc(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "RET %s\n", condition_code(opcode));
GB_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "RET %s\n", condition_code(opcode));
}
static void pop_rr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void pop_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = ((read_memory(gb, (*pc)++) >> 4) + 1) & 3;
gb_log(gb, "POP %s\n", register_names[register_id]);
uint8_t register_id;
register_id = ((GB_read_memory(gb, (*pc)++) >> 4) + 1) & 3;
GB_log(gb, "POP %s\n", register_names[register_id]);
}
static void jp_cc_a16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JP %s, %04x\n", condition_code(opcode), read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JP %s, %04x\n", condition_code(opcode), GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void jp_a16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void jp_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "JP %04x\n", read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_log(gb, "JP %04x\n", GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void call_cc_a16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void call_cc_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "CALL %s, %04x\n", condition_code(opcode), read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_log(gb, "CALL %s, %04x\n", condition_code(opcode), GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void push_rr(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void push_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char register_id;
register_id = ((read_memory(gb, (*pc)++) >> 4) + 1) & 3;
gb_log(gb, "PUSH %s\n", register_names[register_id]);
uint8_t register_id;
register_id = ((GB_read_memory(gb, (*pc)++) >> 4) + 1) & 3;
GB_log(gb, "PUSH %s\n", register_names[register_id]);
}
static void add_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "ADD %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "ADD %02x\n", GB_read_memory(gb, (*pc)++));
}
static void adc_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "ADC %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "ADC %02x\n", GB_read_memory(gb, (*pc)++));
}
static void sub_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SUB %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "SUB %02x\n", GB_read_memory(gb, (*pc)++));
}
static void sbc_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LBC %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "LBC %02x\n", GB_read_memory(gb, (*pc)++));
}
static void and_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "AND %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "AND %02x\n", GB_read_memory(gb, (*pc)++));
}
static void xor_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "XOR %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "XOR %02x\n", GB_read_memory(gb, (*pc)++));
}
static void or_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "OR %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "OR %02x\n", GB_read_memory(gb, (*pc)++));
}
static void cp_a_d8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "CP %02x\n", read_memory(gb, (*pc)++));
GB_log(gb, "CP %02x\n", GB_read_memory(gb, (*pc)++));
}
static void rst(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rst(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RST %02x\n", opcode ^ 0xC7);
GB_log(gb, "RST %02x\n", opcode ^ 0xC7);
}
static void ret(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ret(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_UNDERLINE, "RET\n");
GB_attributed_log(gb, GB_LOG_UNDERLINE, "RET\n");
}
static void reti(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void reti(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_attributed_log(gb, GB_LOG_UNDERLINE, "RETI\n");
GB_attributed_log(gb, GB_LOG_UNDERLINE, "RETI\n");
}
static void call_a16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void call_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "CALL %04x\n", read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_log(gb, "CALL %04x\n", GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void ld_da8_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
unsigned char temp = read_memory(gb, (*pc)++);
gb_log(gb, "LDH [%02x], a\n", temp);
uint8_t temp = GB_read_memory(gb, (*pc)++);
GB_log(gb, "LDH [%02x], a\n", temp);
}
static void ld_a_da8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
unsigned char temp = read_memory(gb, (*pc)++);
gb_log(gb, "LDH a, [%02x]\n", temp);
uint8_t temp = GB_read_memory(gb, (*pc)++);
GB_log(gb, "LDH a, [%02x]\n", temp);
}
static void ld_dc_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LDH [c], a\n");
GB_log(gb, "LDH [c], a\n");
}
static void ld_a_dc(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_dc(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LDH a, [c]\n");
GB_log(gb, "LDH a, [c]\n");
}
static void add_sp_r8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
signed char temp = read_memory(gb, (*pc)++);
gb_log(gb, "ADD SP, %s%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
int8_t temp = GB_read_memory(gb, (*pc)++);
GB_log(gb, "ADD SP, %s%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
}
static void jp_hl(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void jp_hl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "JP hl\n");
GB_log(gb, "JP hl\n");
}
static void ld_da16_a(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_da16_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LD [%04x], a\n", read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_log(gb, "LD [%04x], a\n", GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void ld_a_da16(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LD a, [%04x]\n", read_memory(gb, *pc) | (read_memory(gb, *pc + 1) << 8));
GB_log(gb, "LD a, [%04x]\n", GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8));
(*pc) += 2;
}
static void di(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void di(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "DI\n");
GB_log(gb, "DI\n");
}
static void ei(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ei(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "EI\n");
GB_log(gb, "EI\n");
}
static void ld_hl_sp_r8(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
signed char temp = read_memory(gb, (*pc)++);
gb_log(gb, "LD hl, sp, %s%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
int8_t temp = GB_read_memory(gb, (*pc)++);
GB_log(gb, "LD hl, sp, %s%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
}
static void ld_sp_hl(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void ld_sp_hl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "LD sp, hl\n");
GB_log(gb, "LD sp, hl\n");
}
static void rlc_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rlc_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RLC %s\n", get_src_name(opcode));
GB_log(gb, "RLC %s\n", get_src_name(opcode));
}
static void rrc_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rrc_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RRC %s\n", get_src_name(opcode));
GB_log(gb, "RRC %s\n", get_src_name(opcode));
}
static void rl_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rl_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RL %s\n", get_src_name(opcode));
GB_log(gb, "RL %s\n", get_src_name(opcode));
}
static void rr_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void rr_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RR %s\n", get_src_name(opcode));
GB_log(gb, "RR %s\n", get_src_name(opcode));
}
static void sla_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sla_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SLA %s\n", get_src_name(opcode));
GB_log(gb, "SLA %s\n", get_src_name(opcode));
}
static void sra_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void sra_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SRA %s\n", get_src_name(opcode));
GB_log(gb, "SRA %s\n", get_src_name(opcode));
}
static void srl_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void srl_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "SRL %s\n", get_src_name(opcode));
GB_log(gb, "SRL %s\n", get_src_name(opcode));
}
static void swap_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void swap_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
(*pc)++;
gb_log(gb, "RLC %s\n", get_src_name(opcode));
GB_log(gb, "RLC %s\n", get_src_name(opcode));
}
static void bit_r(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void bit_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
unsigned char bit;
uint8_t bit;
(*pc)++;
bit = ((opcode >> 3) & 7);
if ((opcode & 0xC0) == 0x40) { /* Bit */
gb_log(gb, "BIT %s, %d\n", get_src_name(opcode), bit);
GB_log(gb, "BIT %s, %d\n", get_src_name(opcode), bit);
}
else if ((opcode & 0xC0) == 0x80) { /* res */
gb_log(gb, "RES %s, %d\n", get_src_name(opcode), bit);
GB_log(gb, "RES %s, %d\n", get_src_name(opcode), bit);
}
else if ((opcode & 0xC0) == 0xC0) { /* set */
gb_log(gb, "SET %s, %d\n", get_src_name(opcode), bit);
GB_log(gb, "SET %s, %d\n", get_src_name(opcode), bit);
}
}
static void cb_prefix(GB_gameboy_t *gb, unsigned char opcode, unsigned short *pc)
static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
{
opcode = read_memory(gb, ++*pc);
opcode = GB_read_memory(gb, ++*pc);
switch (opcode >> 3) {
case 0:
rlc_r(gb, opcode, pc);
@ -670,11 +670,11 @@ static GB_opcode_t *opcodes[256] = {
ld_hl_sp_r8,ld_sp_hl, ld_a_da16, ei, ill, ill, cp_a_d8, rst,
};
void cpu_disassemble(GB_gameboy_t *gb, unsigned short pc, unsigned short count)
void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count)
{
while (count--) {
gb_log(gb, "%s%04x: ", pc == gb->pc? "-> ": " ", pc);
unsigned char opcode = read_memory(gb, pc);
GB_log(gb, "%s%04x: ", pc == gb->pc? "-> ": " ", pc);
uint8_t opcode = GB_read_memory(gb, pc);
opcodes[opcode](gb, opcode, &pc);
}
}

View File

@ -9,7 +9,7 @@
static bool running = false;
void update_keys_status(GB_gameboy_t *gb)
void GB_update_keys_status(GB_gameboy_t *gb)
{
static bool ctrl = false;
SDL_Event event;
@ -74,9 +74,9 @@ void vblank(GB_gameboy_t *gb)
{
SDL_Surface *screen = gb->user_data;
SDL_Flip(screen);
update_keys_status(gb);
GB_update_keys_status(gb);
gb_set_pixels_output(gb, screen->pixels);
GB_set_pixels_output(gb, screen->pixels);
}
#ifdef __APPLE__
@ -123,7 +123,7 @@ static char *executable_relative_path(const char *filename)
}
static SDL_Surface *screen = NULL;
static uint32_t rgb_encode(GB_gameboy_t *gb, unsigned char r, unsigned char g, unsigned char b)
static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
{
return SDL_MapRGB(screen->format, r, g, b);
}
@ -138,7 +138,7 @@ static void debugger_interrupt(int ignore)
static void audio_callback(void *gb, Uint8 *stream, int len)
{
apu_copy_buffer(gb, (GB_sample_t *) stream, len / sizeof(GB_sample_t));
GB_apu_copy_buffer(gb, (GB_sample_t *) stream, len / sizeof(GB_sample_t));
}
#ifdef __APPLE__
@ -169,21 +169,21 @@ usage:
if (dmg) {
gb_init(&gb);
if (gb_load_bios(&gb, executable_relative_path("dmg_boot.bin"))) {
GB_init(&gb);
if (GB_load_boot_rom(&gb, executable_relative_path("dmg_boot.bin"))) {
perror("Failed to load boot ROM");
exit(1);
}
}
else {
gb_init_cgb(&gb);
if (gb_load_bios(&gb, executable_relative_path("cgb_boot.bin"))) {
GB_init_cgb(&gb);
if (GB_load_boot_rom(&gb, executable_relative_path("cgb_boot.bin"))) {
perror("Failed to load boot ROM");
exit(1);
}
}
if (gb_load_rom(&gb, argv[argc - 1])) {
if (GB_load_rom(&gb, argv[argc - 1])) {
perror("Failed to load ROM");
exit(1);
}
@ -198,10 +198,10 @@ usage:
#endif
/* Configure Screen */
SDL_LockSurface(screen);
gb_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
gb.user_data = screen;
gb_set_pixels_output(&gb, screen->pixels);
gb_set_rgb_encode_callback(&gb, rgb_encode);
GB_set_pixels_output(&gb, screen->pixels);
GB_set_rgb_encode_callback(&gb, rgb_encode);
/* Configure battery */
size_t path_length = strlen(argv[argc - 1]);
@ -220,7 +220,7 @@ usage:
/* Add .sav */
strcat(battery_save_path, ".sav");
gb_load_battery(&gb, battery_save_path);
GB_load_battery(&gb, battery_save_path);
/* Configure Audio */
SDL_AudioSpec want, have;
@ -232,7 +232,7 @@ usage:
want.callback = audio_callback;
want.userdata = &gb;
SDL_OpenAudio(&want, &have);
gb_set_sample_rate(&gb, 96000);
GB_set_sample_rate(&gb, 96000);
/* Start Audio */
SDL_PauseAudio(0);
@ -240,11 +240,11 @@ usage:
/* Run emulation */
running = true;
while (running) {
gb_run(&gb);
GB_run(&gb);
}
SDL_CloseAudio();
gb_save_battery(&gb, battery_save_path);
GB_save_battery(&gb, battery_save_path);
return 0;
}