Files
game-and-watch-retro-go/linux/snes/main_snes.cpp
2021-08-07 20:15:13 +02:00

324 lines
7.8 KiB
C++

#include <cstdio>
#include "snes9x.h"
#include "memmap.h"
#include "dma.h"
#include "apu/apu.h"
#include "port.h"
#include "display.h"
#include "controls.h"
////////////
#include <odroid_system.h>
#include <SDL2/SDL.h>
#define WIDTH SNES_WIDTH
#define HEIGHT SNES_HEIGHT_EXTENDED
#define BPP 4
#define SCALE 4
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *fb_texture;
uint16_t fb_data[WIDTH * HEIGHT * BPP];
uint16_t framebuffer1[320 * 240 * 2];
uint16_t framebuffer2[320 * 240 * 2];
static odroid_gamepad_state_t joystick1;
///////////
// Routines the port has to implement even if it doesn't use them
void S9xPutImage (int, int) {
SDL_UpdateTexture(fb_texture, NULL, fb_data, WIDTH * BPP);
SDL_RenderCopy(renderer, fb_texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void S9xInitDisplay (int, char **)
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
return;
window = SDL_CreateWindow("emulator",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WIDTH * SCALE, HEIGHT * SCALE,
0);
if (!window)
return;
renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_PRESENTVSYNC);
if (!renderer)
return;
fb_texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING,
WIDTH, HEIGHT);
if (!fb_texture)
return;
S9xGraphicsInit();
}
void S9xDeinitDisplay (void) { }
void S9xTextMode (void) { }
void S9xGraphicsMode (void) { }
void S9xToggleSoundChannel (int) { }
bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *) { return 0; }
void S9xCloseSnapshotFile (STREAM) { }
const char * S9xStringInput (const char *) { return "STUB"; }
const char * S9xGetDirectory (enum s9x_getdirtype) { return "STUB"; }
const char * S9xGetFilename (const char *, enum s9x_getdirtype) { return "STUB"; }
const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype) { return "STUB"; }
const char * S9xBasename (const char *) { return "STUB"; }
// Routines the port has to implement if it uses command-line
void S9xExtraUsage (void) { }
void S9xParseArg (char **, int &, int) { }
// Routines the port may implement as needed
void S9xExtraDisplayUsage (void) { }
void S9xParseDisplayArg (char **, int &, int) { }
void S9xSetTitle (const char *) { }
void S9xInitInputDevices (void) { }
void S9xProcessEvents (bool8) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
if (event.type == SDL_KEYDOWN) {
// printf("Press %d\n", event.key.keysym.sym);
switch (event.key.keysym.sym) {
case SDLK_x:
joystick1.values[ODROID_INPUT_A] = 1;
break;
case SDLK_z:
joystick1.values[ODROID_INPUT_B] = 1;
break;
case SDLK_LSHIFT:
joystick1.values[ODROID_INPUT_START] = 1;
break;
case SDLK_LCTRL:
joystick1.values[ODROID_INPUT_SELECT] = 1;
break;
case SDLK_UP:
joystick1.values[ODROID_INPUT_UP] = 1;
break;
case SDLK_DOWN:
joystick1.values[ODROID_INPUT_DOWN] = 1;
break;
case SDLK_LEFT:
joystick1.values[ODROID_INPUT_LEFT] = 1;
break;
case SDLK_RIGHT:
joystick1.values[ODROID_INPUT_RIGHT] = 1;
break;
case SDLK_ESCAPE:
exit(0);
break;
default:
break;
}
} else if (event.type == SDL_KEYUP) {
// printf("Release %d\n", event.key.keysym.sym);
switch (event.key.keysym.sym) {
case SDLK_x:
joystick1.values[ODROID_INPUT_A] = 0;
break;
case SDLK_z:
joystick1.values[ODROID_INPUT_B] = 0;
break;
case SDLK_LSHIFT:
joystick1.values[ODROID_INPUT_START] = 0;
break;
case SDLK_LCTRL:
joystick1.values[ODROID_INPUT_SELECT] = 0;
break;
case SDLK_UP:
joystick1.values[ODROID_INPUT_UP] = 0;
break;
case SDLK_DOWN:
joystick1.values[ODROID_INPUT_DOWN] = 0;
break;
case SDLK_LEFT:
joystick1.values[ODROID_INPUT_LEFT] = 0;
break;
case SDLK_RIGHT:
joystick1.values[ODROID_INPUT_RIGHT] = 0;
break;
default:
break;
}
}
}
S9xReportButton(ODROID_INPUT_A, joystick1.values[ODROID_INPUT_A]);
S9xReportButton(ODROID_INPUT_B, joystick1.values[ODROID_INPUT_B]);
S9xReportButton(ODROID_INPUT_START, joystick1.values[ODROID_INPUT_START]);
S9xReportButton(ODROID_INPUT_SELECT, joystick1.values[ODROID_INPUT_SELECT]);
S9xReportButton(ODROID_INPUT_UP, joystick1.values[ODROID_INPUT_UP]);
S9xReportButton(ODROID_INPUT_DOWN, joystick1.values[ODROID_INPUT_DOWN]);
S9xReportButton(ODROID_INPUT_LEFT, joystick1.values[ODROID_INPUT_LEFT]);
S9xReportButton(ODROID_INPUT_RIGHT, joystick1.values[ODROID_INPUT_RIGHT]);
}
const char * S9xSelectFilename (const char *, const char *, const char *, const char *) { return "STUB"; }
bool8 S9xOpenSoundDevice (void)
{
}
void S9xSyncSpeed (void)
{
}
void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2)
{
}
bool S9xPollButton (uint32 id, bool *pressed)
{
return 0;
}
bool S9xPollAxis (uint32 id, int16 *value)
{
return 0;
}
bool S9xPollPointer (uint32 id, int16 *x, int16 *y)
{
return 0;
}
void S9xMessage (int type, int number, const char *message)
{
printf("%s\n", message);
}
void S9xAutoSaveSRAM (void)
{
}
bool8 S9xInitUpdate (void)
{
return (TRUE);
}
bool8 S9xDeinitUpdate (int width, int height)
{
S9xPutImage(width, height);
return (TRUE);
}
bool8 S9xContinueUpdate (int width, int height)
{
return (TRUE);
}
void S9xSetPalette(void)
{
return;
}
void S9xExit (void)
{
exit(0);
}
int main(int argc, char *argv[])
{
// Read rom
uint8_t *ROM_DATA;
uint32_t ROM_DATA_LENGTH;
FILE *fp = fopen(argv[1], "rb");
if (!fp)
return -1;
fseek(fp, 0, SEEK_END);
ROM_DATA_LENGTH = ftell(fp);
fseek(fp, 0, SEEK_SET);
ROM_DATA = (uint8_t *) malloc(ROM_DATA_LENGTH);
fread(ROM_DATA, 1, ROM_DATA_LENGTH, fp);
fclose(fp);
////////////
printf("\n\nSnes9x " VERSION " for linux\n");
S9xInitSettings();
Settings.SixteenBitSound = FALSE;
Settings.Stereo = FALSE;
Settings.SoundPlaybackRate = 48000;
Settings.SoundInputRate = 20000;
Settings.SoundSync = FALSE;
Settings.Mute = TRUE;
Settings.AutoDisplayMessages = TRUE;
Settings.Transparency = TRUE;
Settings.SkipFrames = 0;
if (!Memory.Init(ROM_DATA) || !S9xInitAPU())
{
fprintf(stderr, "Snes9x: Memory allocation failure - not enough RAM/virtual memory available.\nExiting...\n");
Memory.Deinit();
S9xDeinitAPU();
exit(1);
}
GFX.ScreenSize = SNES_WIDTH * SNES_HEIGHT_EXTENDED;
GFX.PPL = SNES_WIDTH * 2;
GFX.Pitch = GFX.PPL * 2;
GFX.Screen = (uint16*) fb_data;
S9xGraphicsInit();
S9xInitDisplay(0, NULL);
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_NONE, 1, 0, 0, 0);
#define MAP_BUTTON(id, name) S9xMapButton((id), S9xGetCommandT((name)), false)
MAP_BUTTON(ODROID_INPUT_A, "Joypad1 A");
MAP_BUTTON(ODROID_INPUT_B, "Joypad1 Y");
MAP_BUTTON(ODROID_INPUT_START, "Joypad1 Start");
MAP_BUTTON(ODROID_INPUT_SELECT, "Joypad1 X"); // Select
MAP_BUTTON(ODROID_INPUT_LEFT, "Joypad1 Left");
MAP_BUTTON(ODROID_INPUT_RIGHT, "Joypad1 Right");
MAP_BUTTON(ODROID_INPUT_UP, "Joypad1 Up");
MAP_BUTTON(ODROID_INPUT_DOWN, "Joypad1 Down");
S9xInitSound(0);
S9xSetSoundMute(FALSE);
uint32 saved_flags = CPU.Flags;
if (!Memory.LoadROMMem(ROM_DATA, ROM_DATA_LENGTH)) {
fprintf(stderr, "Error opening the ROM file.\n");
exit(1);
}
CPU.Flags = saved_flags;
Settings.StopEmulation = FALSE;
while (1)
{
S9xMainLoop();
S9xProcessEvents(FALSE);
}
return 0;
}