2017-07-16 18:53:03 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include "../emulibc/emulibc.h"
|
|
|
|
#include "../emulibc/waterboxcore.h"
|
2017-07-18 21:46:21 +00:00
|
|
|
#include "blip_buf/blip_buf.h"
|
2017-07-16 18:53:03 +00:00
|
|
|
|
|
|
|
#define _Static_assert static_assert
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include "gb.h"
|
|
|
|
#include "joypad.h"
|
|
|
|
#include "apu.h"
|
|
|
|
}
|
|
|
|
|
|
|
|
static GB_gameboy_t GB;
|
|
|
|
|
|
|
|
static void VBlankCallback(GB_gameboy_t *gb)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void LogCallback(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes)
|
|
|
|
{
|
|
|
|
fputs(string, stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t RgbEncodeCallback(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
|
|
|
{
|
2017-07-18 21:46:21 +00:00
|
|
|
return b | g << 8 | r << 16 | 0xff000000;
|
2017-07-16 18:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void InfraredCallback(GB_gameboy_t *gb, bool on, long cycles_since_last_update)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void RumbleCallback(GB_gameboy_t *gb, bool rumble_on)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SerialStartCallback(GB_gameboy_t *gb, uint8_t byte_to_send)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t SerialEndCallback(GB_gameboy_t *gb)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-18 21:46:21 +00:00
|
|
|
static blip_t *leftblip;
|
|
|
|
static blip_t *rightblip;
|
|
|
|
const int SOUND_RATE_GB = 2097152;
|
|
|
|
const int SOUND_RATE_SGB = 2147727;
|
|
|
|
static uint64_t sound_start_clock;
|
|
|
|
static GB_sample_t sample_gb;
|
|
|
|
|
|
|
|
static void SampleCallback(GB_gameboy_t *gb, GB_sample_t sample, uint64_t clock)
|
|
|
|
{
|
|
|
|
int l = sample.left - sample_gb.left;
|
|
|
|
int r = sample.right - sample_gb.right;
|
|
|
|
if (l)
|
|
|
|
blip_add_delta(leftblip, clock - sound_start_clock, l);
|
|
|
|
if (r)
|
|
|
|
blip_add_delta(rightblip, clock - sound_start_clock, r);
|
|
|
|
sample_gb = sample;
|
|
|
|
}
|
|
|
|
|
2017-07-16 18:53:03 +00:00
|
|
|
ECL_EXPORT bool Init(bool cgb)
|
|
|
|
{
|
2017-07-18 21:46:21 +00:00
|
|
|
if (cgb)
|
|
|
|
GB_init_cgb(&GB);
|
|
|
|
else
|
|
|
|
GB_init(&GB);
|
|
|
|
if (GB_load_boot_rom(&GB, "boot.rom") != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (GB_load_rom(&GB, "game.rom") != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
GB_set_vblank_callback(&GB, VBlankCallback);
|
|
|
|
GB_set_log_callback(&GB, LogCallback);
|
|
|
|
GB_set_rgb_encode_callback(&GB, RgbEncodeCallback);
|
|
|
|
GB_set_infrared_callback(&GB, InfraredCallback);
|
|
|
|
GB_set_rumble_callback(&GB, RumbleCallback);
|
|
|
|
GB_set_sample_callback(&GB, SampleCallback);
|
|
|
|
|
|
|
|
leftblip = blip_new(1024);
|
|
|
|
rightblip = blip_new(1024);
|
|
|
|
blip_set_rates(leftblip, SOUND_RATE_GB, 44100);
|
|
|
|
blip_set_rates(rightblip, SOUND_RATE_GB, 44100);
|
|
|
|
|
|
|
|
return true;
|
2017-07-16 18:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct MyFrameInfo : public FrameInfo
|
|
|
|
{
|
2017-07-18 22:19:51 +00:00
|
|
|
int64_t Time;
|
|
|
|
uint32_t Keys;
|
2017-07-16 18:53:03 +00:00
|
|
|
};
|
|
|
|
|
2017-07-18 21:46:21 +00:00
|
|
|
static int FrameOverflow;
|
|
|
|
|
2017-07-16 18:53:03 +00:00
|
|
|
ECL_EXPORT void FrameAdvance(MyFrameInfo &f)
|
|
|
|
{
|
2017-07-18 21:46:21 +00:00
|
|
|
GB_set_pixels_output(&GB, f.VideoBuffer);
|
2017-07-18 22:19:51 +00:00
|
|
|
GB_set_key_state(&GB, f.Keys & 0xff);
|
2017-07-18 21:46:21 +00:00
|
|
|
|
|
|
|
sound_start_clock = GB_epoch(&GB);
|
|
|
|
|
|
|
|
uint32_t target = 35112 - FrameOverflow;
|
|
|
|
f.Cycles = GB_run_cycles(&GB, target);
|
|
|
|
FrameOverflow = f.Cycles - target;
|
|
|
|
blip_end_frame(leftblip, f.Cycles);
|
|
|
|
blip_end_frame(rightblip, f.Cycles);
|
|
|
|
f.Samples = blip_read_samples(leftblip, f.SoundBuffer, 2048, 1);
|
|
|
|
blip_read_samples(rightblip, f.SoundBuffer + 1, 2048, 1);
|
2017-07-16 18:53:03 +00:00
|
|
|
f.Width = 160;
|
|
|
|
f.Height = 144;
|
|
|
|
}
|
|
|
|
|
2017-07-18 21:46:21 +00:00
|
|
|
static void SetMemoryArea(MemoryArea *m, GB_direct_access_t access, const char *name, int32_t flags)
|
2017-07-16 18:53:03 +00:00
|
|
|
{
|
2017-07-18 21:46:21 +00:00
|
|
|
size_t size;
|
|
|
|
m->Name = name;
|
|
|
|
m->Data = GB_get_direct_access(&GB, access, &size, nullptr);
|
|
|
|
m->Size = size;
|
|
|
|
m->Flags = flags;
|
2017-07-16 18:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ECL_EXPORT void GetMemoryAreas(MemoryArea *m)
|
|
|
|
{
|
|
|
|
// TODO: "System Bus"
|
|
|
|
SetMemoryArea(m + 0, GB_DIRECT_ACCESS_RAM, "WRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY);
|
|
|
|
SetMemoryArea(m + 1, GB_DIRECT_ACCESS_ROM, "ROM", MEMORYAREA_FLAGS_WORDSIZE1);
|
|
|
|
SetMemoryArea(m + 2, GB_DIRECT_ACCESS_VRAM, "VRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
SetMemoryArea(m + 3, GB_DIRECT_ACCESS_CART_RAM, "CartRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
SetMemoryArea(m + 4, GB_DIRECT_ACCESS_OAM, "OAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
SetMemoryArea(m + 5, GB_DIRECT_ACCESS_HRAM, "HRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
SetMemoryArea(m + 6, GB_DIRECT_ACCESS_IO, "IO", MEMORYAREA_FLAGS_WORDSIZE1);
|
|
|
|
SetMemoryArea(m + 7, GB_DIRECT_ACCESS_BOOTROM, "BOOTROM", MEMORYAREA_FLAGS_WORDSIZE1);
|
|
|
|
SetMemoryArea(m + 8, GB_DIRECT_ACCESS_BGP, "BGP", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
2017-07-17 00:36:58 +00:00
|
|
|
SetMemoryArea(m + 9, GB_DIRECT_ACCESS_OBP, "OBP", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE);
|
2017-07-16 18:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ECL_EXPORT void SetInputCallback(void (*callback)())
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|