Files
game-and-watch-retro-go/linux/gb/main.c
2021-07-15 23:08:47 +02:00

222 lines
5.0 KiB
C

#include <odroid_system.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <odroid_system.h>
#include "porting.h"
#include "crc32.h"
#include "gw_lcd.h"
#include "gnuboy/loader.h"
#include "gnuboy/hw.h"
#include "gnuboy/lcd.h"
#include "gnuboy/cpu.h"
#include "gnuboy/mem.h"
#include "gnuboy/sound.h"
#include "gnuboy/regs.h"
#include "gnuboy/rtc.h"
#include "gnuboy/defs.h"
#define APP_ID 20
#define NVS_KEY_SAVE_SRAM "sram"
#define WIDTH GB_WIDTH
#define HEIGHT GB_HEIGHT
#define BPP 2
#define SCALE 4
#define AUDIO_SAMPLE_RATE (48000)
#define AUDIO_BUFFER_LENGTH (AUDIO_SAMPLE_RATE / 60)
// Use 60Hz for GB
#define AUDIO_BUFFER_LENGTH_GB (AUDIO_SAMPLE_RATE / 60)
#define AUDIO_BUFFER_LENGTH_DMA_GB ((2 * AUDIO_SAMPLE_RATE) / 60)
static odroid_video_frame_t update1 = {GB_WIDTH, GB_HEIGHT, GB_WIDTH * 2, 2, 0xFF, -1, NULL, NULL, 0, {}};
static odroid_video_frame_t update2 = {GB_WIDTH, GB_HEIGHT, GB_WIDTH * 2, 2, 0xFF, -1, NULL, NULL, 0, {}};
static odroid_video_frame_t *currentUpdate = &update1;
static bool fullFrame = false;
static uint skipFrames = 0;
static bool saveSRAM = false;
// 3 pages
uint8_t state_save_buffer[192 * 1024];
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *fb_texture;
uint16_t fb_data[WIDTH * HEIGHT * BPP];
SDL_AudioSpec wanted;
void fill_audio(void *udata, Uint8 *stream, int len);
extern unsigned char cart_rom[];
extern unsigned int cart_rom_len;
void odroid_display_force_refresh(void)
{
// forceVideoRefresh = true;
}
static inline void blit(void) {
// we want 60 Hz for NTSC
int wantedTime = 1000 / 60;
SDL_Delay(wantedTime); // rendering takes basically "0ms"
memcpy(fb_data, currentUpdate->buffer, sizeof(fb_data));
SDL_UpdateTexture(fb_texture, NULL, fb_data, WIDTH * BPP);
SDL_RenderCopy(renderer, fb_texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void fill_audio(void *udata, Uint8 *stream, int len)
{
}
int init_window(int width, int height)
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
return 0;
window = SDL_CreateWindow("emulator",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width * SCALE, height * SCALE,
0);
if (!window)
return 0;
renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_PRESENTVSYNC);
if (!renderer)
return 0;
fb_texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING,
width, height);
if (!fb_texture)
return 0;
#if 0
/* Set the audio format */
wanted.freq = AUDIO_SAMPLE_RATE;
wanted.format = AUDIO_S16;
wanted.channels = 1; /* 1 = mono, 2 = stereo */
wanted.samples = AUDIO_BUFFER_LENGTH * 2; /* Good low-latency value for callback */
wanted.callback = fill_audio;
wanted.userdata = NULL;
/* Open the audio device, forcing the desired format */
if (SDL_OpenAudio(&wanted, NULL) < 0) {
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
return(-1);
}
SDL_PauseAudio(0);
#endif
return 0;
}
static void netplay_callback(netplay_event_t event, void *arg)
{
// Where we're going we don't need netplay!
}
static bool SaveState(char *pathName)
{
return 0;
}
static bool LoadState(char *pathName)
{
return true;
}
void pcm_submit(void)
{
}
void init(void)
{
odroid_system_init(APP_ID, AUDIO_SAMPLE_RATE);
odroid_system_emu_init(&LoadState, &SaveState, &netplay_callback);
// Hack: Use the same buffer twice
update1.buffer = fb_data;
update2.buffer = fb_data;
//saveSRAM = odroid_settings_app_int32_get(NVS_KEY_SAVE_SRAM, 0);
saveSRAM = false;
// Load ROM
loader_init(NULL);
// RTC
memset(&rtc, 0, sizeof(rtc));
// Video
memset(fb_data, 0, sizeof(fb_data));
memset(&fb, 0, sizeof(fb));
fb.w = GB_WIDTH;
fb.h = GB_HEIGHT;
fb.format = GB_PIXEL_565_LE;
fb.pitch = update1.stride;
fb.ptr = currentUpdate->buffer;
fb.enabled = 1;
fb.blit_func = &blit;
emu_init();
//pal_set_dmg(odroid_settings_Palette_get());
pal_set_dmg(2);
}
int main(int argc, char *argv[])
{
init_window(WIDTH, HEIGHT);
init();
odroid_gamepad_state_t joystick = {0};
while (true)
{
odroid_input_read_gamepad(&joystick);
uint startTime = get_elapsed_time();
bool drawFrame = !skipFrames;
pad_set(PAD_UP, joystick.values[ODROID_INPUT_UP]);
pad_set(PAD_RIGHT, joystick.values[ODROID_INPUT_RIGHT]);
pad_set(PAD_DOWN, joystick.values[ODROID_INPUT_DOWN]);
pad_set(PAD_LEFT, joystick.values[ODROID_INPUT_LEFT]);
pad_set(PAD_SELECT, joystick.values[ODROID_INPUT_SELECT]);
pad_set(PAD_START, joystick.values[ODROID_INPUT_START]);
pad_set(PAD_A, joystick.values[ODROID_INPUT_A]);
pad_set(PAD_B, joystick.values[ODROID_INPUT_B]);
emu_run(drawFrame);
// Tick before submitting audio/syncing
odroid_system_tick(!drawFrame, fullFrame, get_elapsed_time_since(startTime));
}
SDL_Quit();
return 0;
}