mirror of
https://github.com/libretro/smsplus-gx.git
synced 2024-12-12 11:35:40 +00:00
Add FBDev/evdev port for Embedded linux platforms.
This was mostly done to allow us to decrease the size of the binary when using static linking as well as avoid the overhead of libSDL. The input code reads directly from /dev/input/event0 (which is the keyboard). It does seem to suffer from ghosting (?) when the program slows down a lot. This does not happen on libSDL so i'm not sure what to do, it seems that they might be using threads to solve this issue ? The FBDev code does not currently support double buffering : This would require us doubling the vertical size of the allocated resolution. The Pandora wiki explains how this is implemented with fbdev : https://pandorawiki.org/Kernel_interface
This commit is contained in:
parent
2ba43256b4
commit
e3156e37ce
711
source/ports/fbdev/smsplus.c
Normal file
711
source/ports/fbdev/smsplus.c
Normal file
@ -0,0 +1,711 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/keyboard.h>
|
||||
|
||||
#include "shared.h"
|
||||
#include "scaler.h"
|
||||
#include "smsplus.h"
|
||||
#include "sound_output.h"
|
||||
|
||||
#include "font_drawing.h"
|
||||
|
||||
static gamedata_t gdata;
|
||||
|
||||
static uint16_t* restrict fbp = 0;
|
||||
uint16_t* restrict backbuffer = 0;
|
||||
|
||||
static int fbfd = 0, keyboard_fd = 0;
|
||||
static struct input_event data;
|
||||
static struct fb_var_screeninfo orig_vinfo;
|
||||
static struct fb_var_screeninfo vinfo;
|
||||
static struct fb_fix_screeninfo finfo;
|
||||
static size_t screensize = 0;
|
||||
|
||||
t_config option;
|
||||
|
||||
static int8_t fullscreen = 1;
|
||||
static uint8_t selectpressed = 0;
|
||||
static uint8_t save_slot = 0;
|
||||
static uint8_t quit = 0;
|
||||
|
||||
#ifdef SCALE2X_UPSCALER
|
||||
static uint32_t dst_x, dst_w, dst_h;
|
||||
static uint16_t* restrict scale2x_buf;
|
||||
#endif
|
||||
|
||||
const int8_t upscalers_available = 1
|
||||
#ifdef SCALE2X_UPSCALER
|
||||
+1
|
||||
#endif
|
||||
;
|
||||
static uint16_t* restrict sms_bitmap;
|
||||
|
||||
|
||||
static void video_update()
|
||||
{
|
||||
switch(fullscreen)
|
||||
{
|
||||
// Native
|
||||
case 0:
|
||||
if(sms.console == CONSOLE_GG)
|
||||
bitmap_scale(48,0,160,144,160,144,256,HOST_WIDTH_RESOLUTION-160,(uint16_t* restrict)sms_bitmap,(uint16_t* restrict)fbp+(HOST_WIDTH_RESOLUTION-160)/2+(HOST_HEIGHT_RESOLUTION-144)/2*HOST_WIDTH_RESOLUTION);
|
||||
else
|
||||
bitmap_scale(0,0,256,vdp.height,256,(vdp.height),256,HOST_WIDTH_RESOLUTION-256,(uint16_t* restrict)sms_bitmap,(uint16_t* restrict)fbp+(HOST_WIDTH_RESOLUTION-256)/2+(HOST_HEIGHT_RESOLUTION-(vdp.height))/2*HOST_WIDTH_RESOLUTION);
|
||||
break;
|
||||
// Fullscreen
|
||||
case 1:
|
||||
if(sms.console == CONSOLE_GG)
|
||||
upscale_160x144_to_320x240((uint32_t* restrict)fbp, (uint32_t* restrict)sms_bitmap+24);
|
||||
else
|
||||
upscale_SMS_to_320x240((uint32_t* restrict)fbp, (uint32_t* restrict)sms_bitmap, vdp.height);
|
||||
break;
|
||||
// Hqx
|
||||
case 2:
|
||||
#ifdef SCALE2X_UPSCALER
|
||||
if(sms.console == CONSOLE_GG)
|
||||
{
|
||||
dst_x = 96;
|
||||
dst_w = 320;
|
||||
dst_h = 144*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hide_left = (vdp.reg[0] & 0x20) ? 1 : 0;
|
||||
dst_x = hide_left ? 16 : 0;
|
||||
dst_w = (hide_left ? 248 : 256)*2;
|
||||
dst_h = vdp.height*2;
|
||||
}
|
||||
scale2x(sms_bitmap, scale2x_buf, 512, 1024, 256, 240);
|
||||
bitmap_scale(dst_x,0,dst_w,dst_h,HOST_WIDTH_RESOLUTION,HOST_HEIGHT_RESOLUTION,512,0,scale2x_buf,fbp);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void smsp_state(uint8_t slot_number, uint8_t mode)
|
||||
{
|
||||
// Save and Load States
|
||||
char stpath[PATH_MAX];
|
||||
snprintf(stpath, sizeof(stpath), "%s%s.st%d", gdata.stdir, gdata.gamename, slot_number);
|
||||
FILE *fd;
|
||||
|
||||
switch(mode) {
|
||||
case 0:
|
||||
fd = fopen(stpath, "wb");
|
||||
if (fd) {
|
||||
system_save_state(fd);
|
||||
fclose(fd);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fd = fopen(stpath, "rb");
|
||||
if (fd) {
|
||||
system_load_state(fd);
|
||||
fclose(fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void system_manage_sram(uint8_t *sram, uint8_t slot_number, uint8_t mode)
|
||||
{
|
||||
// Set up save file name
|
||||
FILE *fd;
|
||||
switch(mode)
|
||||
{
|
||||
case SRAM_SAVE:
|
||||
if(sms.save)
|
||||
{
|
||||
fd = fopen(gdata.sramfile, "wb");
|
||||
if (fd)
|
||||
{
|
||||
fwrite(sram, 0x8000, 1, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SRAM_LOAD:
|
||||
fd = fopen(gdata.sramfile, "rb");
|
||||
if (fd)
|
||||
{
|
||||
sms.save = 1;
|
||||
fread(sram, 0x8000, 1, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
else
|
||||
memset(sram, 0x00, 0x8000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Controls()
|
||||
{
|
||||
int bytes;
|
||||
if (sms.console == CONSOLE_COLECO)
|
||||
{
|
||||
coleco.keypad[0] = 0xff;
|
||||
coleco.keypad[1] = 0xff;
|
||||
}
|
||||
|
||||
bytes = read(keyboard_fd, &data, sizeof(data));
|
||||
|
||||
//if (data.type == 0x01)
|
||||
{
|
||||
switch(data.code)
|
||||
{
|
||||
/* At least allow them to play on the lowest difficulties, Maybe this needs a better implementation ? */
|
||||
case 15:
|
||||
coleco.keypad[0] = 1;
|
||||
break;
|
||||
case 16:
|
||||
coleco.keypad[0] = 2;
|
||||
break;
|
||||
case 107:
|
||||
case 1:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
selectpressed = 1;
|
||||
else
|
||||
selectpressed = 0;
|
||||
break;
|
||||
case 28:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
input.system |= (sms.console == CONSOLE_GG) ? INPUT_START : INPUT_PAUSE;
|
||||
else if (data.value == 0)
|
||||
input.system &= (sms.console == CONSOLE_GG) ? ~INPUT_START : ~INPUT_PAUSE;
|
||||
break;
|
||||
case 103:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
{
|
||||
input.pad[0] |= INPUT_UP;
|
||||
}
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_UP;
|
||||
break;
|
||||
case 108:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
{
|
||||
input.pad[0] |= INPUT_DOWN;
|
||||
}
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_DOWN;
|
||||
break;
|
||||
case 105:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
{
|
||||
input.pad[0] |= INPUT_LEFT;
|
||||
}
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_LEFT;
|
||||
break;
|
||||
case 106:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
{
|
||||
input.pad[0] |= INPUT_RIGHT;
|
||||
}
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_RIGHT;
|
||||
break;
|
||||
case 56:
|
||||
case 42:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
input.pad[0] |= INPUT_BUTTON1;
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_BUTTON1;
|
||||
break;
|
||||
case 29:
|
||||
case 57:
|
||||
if (data.value == 1 && bytes > 0)
|
||||
input.pad[0] |= INPUT_BUTTON2;
|
||||
else if (data.value == 0)
|
||||
input.pad[0] &= ~INPUT_BUTTON2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sms.console == CONSOLE_COLECO) input.system = 0;
|
||||
}
|
||||
|
||||
|
||||
static void bios_init()
|
||||
{
|
||||
FILE *fd;
|
||||
char bios_path[256];
|
||||
|
||||
bios.rom = malloc(0x100000);
|
||||
bios.enabled = 0;
|
||||
|
||||
snprintf(bios_path, sizeof(bios_path), "%s%s", gdata.biosdir, "BIOS.sms");
|
||||
|
||||
fd = fopen(bios_path, "rb");
|
||||
if(fd)
|
||||
{
|
||||
/* Seek to end of file, and get size */
|
||||
fseek(fd, 0, SEEK_END);
|
||||
uint32_t size = ftell(fd);
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
if (size < 0x4000) size = 0x4000;
|
||||
fread(bios.rom, size, 1, fd);
|
||||
bios.enabled = 2;
|
||||
bios.pages = size / 0x4000;
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
snprintf(bios_path, sizeof(bios_path), "%s%s", gdata.biosdir, "BIOS.col");
|
||||
|
||||
fd = fopen(bios_path, "rb");
|
||||
if(fd)
|
||||
{
|
||||
/* Seek to end of file, and get size */
|
||||
fread(coleco.rom, 0x2000, 1, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void smsp_gamedata_set(char *filename)
|
||||
{
|
||||
// Set paths, create directories
|
||||
char home_path[256];
|
||||
snprintf(home_path, sizeof(home_path), "%s/.smsplus/", getenv("HOME"));
|
||||
|
||||
if (mkdir(home_path, 0755) && errno != EEXIST) {
|
||||
fprintf(stderr, "Failed to create %s: %d\n", home_path, errno);
|
||||
}
|
||||
|
||||
// Set the game name
|
||||
snprintf(gdata.gamename, sizeof(gdata.gamename), "%s", basename(filename));
|
||||
|
||||
// Strip the file extension off
|
||||
for (unsigned long i = strlen(gdata.gamename) - 1; i > 0; i--) {
|
||||
if (gdata.gamename[i] == '.') {
|
||||
gdata.gamename[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the sram directory
|
||||
snprintf(gdata.sramdir, sizeof(gdata.sramdir), "%ssram/", home_path);
|
||||
if (mkdir(gdata.sramdir, 0755) && errno != EEXIST) {
|
||||
fprintf(stderr, "Failed to create %s: %d\n", gdata.sramdir, errno);
|
||||
}
|
||||
|
||||
// Set up the sram file
|
||||
snprintf(gdata.sramfile, sizeof(gdata.sramfile), "%s%s.sav", gdata.sramdir, gdata.gamename);
|
||||
|
||||
// Set up the state directory
|
||||
snprintf(gdata.stdir, sizeof(gdata.stdir), "%sstate/", home_path);
|
||||
if (mkdir(gdata.stdir, 0755) && errno != EEXIST) {
|
||||
fprintf(stderr, "Failed to create %s: %d\n", gdata.stdir, errno);
|
||||
}
|
||||
|
||||
// Set up the screenshot directory
|
||||
snprintf(gdata.scrdir, sizeof(gdata.scrdir), "%sscreenshots/", home_path);
|
||||
if (mkdir(gdata.scrdir, 0755) && errno != EEXIST) {
|
||||
fprintf(stderr, "Failed to create %s: %d\n", gdata.scrdir, errno);
|
||||
}
|
||||
|
||||
// Set up the sram directory
|
||||
snprintf(gdata.biosdir, sizeof(gdata.biosdir), "%sbios/", home_path);
|
||||
if (mkdir(gdata.biosdir, 0755) && errno != EEXIST) {
|
||||
fprintf(stderr, "Failed to create %s: %d\n", gdata.sramdir, errno);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define TextWhite 65535
|
||||
#define TextRed ((255>>3)<<11) + ((0>>2)<<5) + (0>>3)
|
||||
|
||||
static void Menu()
|
||||
{
|
||||
uint32_t pressed = 0;
|
||||
uint32_t currentselection = 1;
|
||||
uint32_t miniscreenwidth = 128;
|
||||
uint32_t miniscreenheight = 128;
|
||||
char text[50];
|
||||
int bytes;
|
||||
|
||||
while(((currentselection != 1) && (currentselection != 6)) || (!pressed))
|
||||
{
|
||||
bytes = read(keyboard_fd, &data, sizeof(data));
|
||||
pressed = 0;
|
||||
|
||||
switch(data.code)
|
||||
{
|
||||
case 103:
|
||||
if (data.value == 1)
|
||||
{
|
||||
currentselection--;
|
||||
if (currentselection == 0)
|
||||
currentselection = 6;
|
||||
}
|
||||
break;
|
||||
case 108:
|
||||
if (data.value == 1)
|
||||
{
|
||||
currentselection++;
|
||||
if (currentselection == 7)
|
||||
currentselection = 1;
|
||||
}
|
||||
break;
|
||||
case 105:
|
||||
if (data.value == 1)
|
||||
{
|
||||
switch(currentselection)
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
if (save_slot > 0) save_slot--;
|
||||
break;
|
||||
case 4:
|
||||
fullscreen--;
|
||||
if (fullscreen < 0)
|
||||
fullscreen = upscalers_available;
|
||||
break;
|
||||
case 5:
|
||||
option.soundlevel--;
|
||||
if (option.soundlevel < 1)
|
||||
option.soundlevel = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 106:
|
||||
if (data.value == 1)
|
||||
{
|
||||
switch(currentselection)
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
save_slot++;
|
||||
if (save_slot == 10)
|
||||
save_slot = 9;
|
||||
break;
|
||||
case 4:
|
||||
fullscreen++;
|
||||
if (fullscreen > upscalers_available)
|
||||
fullscreen = 0;
|
||||
break;
|
||||
case 5 :
|
||||
option.soundlevel++;
|
||||
if (option.soundlevel > 4)
|
||||
option.soundlevel = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 29:
|
||||
if (data.value == 1)
|
||||
{
|
||||
pressed = 1;
|
||||
switch(currentselection)
|
||||
{
|
||||
case 5 :
|
||||
option.soundlevel++;
|
||||
if (option.soundlevel > 4)
|
||||
option.soundlevel = 0;
|
||||
break;
|
||||
case 4 :
|
||||
fullscreen++;
|
||||
if (fullscreen > upscalers_available)
|
||||
fullscreen = 0;
|
||||
break;
|
||||
case 2 :
|
||||
smsp_state(save_slot, 1);
|
||||
currentselection = 1;
|
||||
break;
|
||||
case 3 :
|
||||
smsp_state(save_slot, 0);
|
||||
currentselection = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
memset(backbuffer, 0, (320*240)*sizeof(uint16_t));
|
||||
|
||||
if(IS_GG)
|
||||
{
|
||||
bitmap_scale(48,0,
|
||||
160,144,
|
||||
miniscreenwidth,miniscreenheight,
|
||||
256, HOST_WIDTH_RESOLUTION-miniscreenwidth,
|
||||
(uint16_t* restrict)sms_bitmap,(uint16_t* restrict)backbuffer+(HOST_WIDTH_RESOLUTION+45)/2+(HOST_HEIGHT_RESOLUTION-vdp.height+24)/2*HOST_WIDTH_RESOLUTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap_scale(0,0,
|
||||
256,vdp.height,
|
||||
miniscreenwidth,miniscreenheight,
|
||||
256, HOST_WIDTH_RESOLUTION-miniscreenwidth,
|
||||
(uint16_t* restrict)sms_bitmap,(uint16_t* restrict)backbuffer+(HOST_WIDTH_RESOLUTION+45)/2+(HOST_HEIGHT_RESOLUTION-vdp.height+24)/2*HOST_WIDTH_RESOLUTION);
|
||||
}
|
||||
|
||||
print_string("SMS PLUS GX", TextWhite, 0, 105, 15);
|
||||
|
||||
if (currentselection == 1) print_string("Continue", TextRed, 0, 5, 45);
|
||||
else print_string("Continue", TextWhite, 0, 5, 45);
|
||||
|
||||
snprintf(text, sizeof(text), "Load State %d", save_slot);
|
||||
|
||||
if (currentselection == 2) print_string(text, TextRed, 0, 5, 65);
|
||||
else print_string(text, TextWhite, 0, 5, 65);
|
||||
|
||||
snprintf(text, sizeof(text), "Save State %d", save_slot);
|
||||
|
||||
if (currentselection == 3) print_string(text, TextRed, 0, 5, 85);
|
||||
else print_string(text, TextWhite, 0, 5, 85);
|
||||
|
||||
|
||||
if (currentselection == 4)
|
||||
{
|
||||
switch(fullscreen)
|
||||
{
|
||||
case 0:
|
||||
print_string("Scaling : Native", TextRed, 0, 5, 105);
|
||||
break;
|
||||
case 1:
|
||||
print_string("Scaling : Stretched", TextRed, 0, 5, 105);
|
||||
break;
|
||||
case 2:
|
||||
print_string("Scaling : EPX/Scale2x", TextRed, 0, 5, 105);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(fullscreen)
|
||||
{
|
||||
case 0:
|
||||
print_string("Scaling : Native", TextWhite, 0, 5, 105);
|
||||
break;
|
||||
case 1:
|
||||
print_string("Scaling : Stretched", TextWhite, 0, 5, 105);
|
||||
break;
|
||||
case 2:
|
||||
print_string("Scaling : EPX/Scale2x", TextWhite, 0, 5, 105);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
snprintf(text, sizeof(text), "Sound volume : %d", option.soundlevel);
|
||||
|
||||
if (currentselection == 5) print_string(text, TextRed, 0, 5, 125);
|
||||
else print_string(text, TextWhite, 0, 5, 125);
|
||||
|
||||
if (currentselection == 6) print_string("Quit", TextRed, 0, 5, 145);
|
||||
else print_string("Quit", TextWhite, 0, 5, 145);
|
||||
|
||||
print_string("Based on SMS Plus by Charles Mcdonald", TextWhite, 0, 5, 175);
|
||||
print_string("Fork of SMS Plus GX by gameblabla", TextWhite, 0, 5, 190);
|
||||
print_string("Scaler : Alekmaul", TextWhite, 0, 5, 205);
|
||||
print_string("Text drawing : n2DLib", TextWhite, 0, 5, 220);
|
||||
|
||||
memmove(fbp, backbuffer, (320*240)*sizeof(uint16_t));
|
||||
|
||||
#ifdef VSYNC_SUPPORTED
|
||||
int arg = 0;
|
||||
if ( ioctl(fbfd, FBIO_WAITFORVSYNC, 0) < 0 )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(backbuffer, 0, (320*240)*sizeof(uint16_t));
|
||||
memset(fbp, 0, (320*240)*sizeof(uint16_t));
|
||||
|
||||
if (currentselection == 6)
|
||||
quit = 1;
|
||||
}
|
||||
|
||||
|
||||
static void Cleanup(void)
|
||||
{
|
||||
#ifdef SCALE2X_UPSCALER
|
||||
if (scale2x_buf) free(scale2x_buf);
|
||||
#endif
|
||||
if (sms_bitmap) free(sms_bitmap);
|
||||
if (backbuffer) free(backbuffer);
|
||||
munmap(fbp, screensize);
|
||||
|
||||
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo))
|
||||
{
|
||||
printf("Error re-setting variable information.\n");
|
||||
}
|
||||
|
||||
if (fbfd) close(fbfd);
|
||||
if (keyboard_fd) close(keyboard_fd);
|
||||
|
||||
if (bios.rom) free(bios.rom);
|
||||
|
||||
// Deinitialize audio and video output
|
||||
Sound_Close();
|
||||
|
||||
// Shut down
|
||||
system_poweroff();
|
||||
system_shutdown();
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: ./smsplus [FILE]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&option, 0, sizeof(option));
|
||||
|
||||
option.fm = 1;
|
||||
option.spritelimit = 1;
|
||||
option.country = 0;
|
||||
option.tms_pal = 2;
|
||||
option.console = 0;
|
||||
option.nosound = 0;
|
||||
option.soundlevel = 1;
|
||||
|
||||
strcpy(option.game_name, argv[1]);
|
||||
|
||||
smsp_gamedata_set(argv[1]);
|
||||
|
||||
// Force Colecovision mode
|
||||
if (strcmp(strrchr(argv[1], '.'), ".col") == 0) option.console = 6;
|
||||
|
||||
// Load ROM
|
||||
if(!load_rom(argv[1])) {
|
||||
fprintf(stderr, "Error: Failed to load %s.\n", argv[1]);
|
||||
Cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyboard_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
|
||||
if (!keyboard_fd)
|
||||
{
|
||||
printf("Error: Cannot open Keyboard\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
|
||||
ioctl(keyboard_fd, VT_ACTIVATE, 1);
|
||||
ioctl(keyboard_fd, VT_WAITACTIVE, 1);
|
||||
|
||||
fbfd = open("/dev/fb0", O_RDWR | O_SYNC);
|
||||
if (!fbfd)
|
||||
{
|
||||
printf("Error: cannot open framebuffer device.\n");
|
||||
return 1 ;
|
||||
}
|
||||
// Get variable screen information
|
||||
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||
printf("Error reading variable information.\n");
|
||||
}
|
||||
|
||||
// Store for reset (copy vinfo to vinfo_orig)
|
||||
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
|
||||
|
||||
// Change variable info
|
||||
vinfo.bits_per_pixel = 16;
|
||||
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
|
||||
printf("Error : Setting variable information.\n");
|
||||
}
|
||||
|
||||
// Get fixed screen information
|
||||
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
|
||||
printf("Error : Reading fixed information.\n");
|
||||
}
|
||||
|
||||
// map fb to user mem
|
||||
screensize = finfo.smem_len;
|
||||
|
||||
fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
|
||||
|
||||
sms_bitmap = malloc((VIDEO_WIDTH_SMS*240)*sizeof(uint16_t));
|
||||
backbuffer = malloc((320*240)*sizeof(uint16_t));
|
||||
|
||||
Sound_Init();
|
||||
|
||||
#ifdef SCALE2X_UPSCALER
|
||||
scale2x_buf = malloc(((VIDEO_WIDTH_SMS*2)*480)*sizeof(uint16_t));
|
||||
#endif
|
||||
|
||||
fprintf(stdout, "CRC : %08X\n", cart.crc);
|
||||
|
||||
// Set parameters for internal bitmap
|
||||
bitmap.width = VIDEO_WIDTH_SMS;
|
||||
bitmap.height = VIDEO_HEIGHT_SMS;
|
||||
bitmap.depth = 16;
|
||||
bitmap.granularity = 2;
|
||||
bitmap.data = (uint8_t *)sms_bitmap;
|
||||
bitmap.pitch = 512;
|
||||
bitmap.viewport.w = VIDEO_WIDTH_SMS;
|
||||
bitmap.viewport.h = VIDEO_HEIGHT_SMS;
|
||||
bitmap.viewport.x = 0x00;
|
||||
bitmap.viewport.y = 0x00;
|
||||
|
||||
//sms.territory = settings.misc_region;
|
||||
if (sms.console == CONSOLE_SMS || sms.console == CONSOLE_SMS2)
|
||||
sms.use_fm = 1;
|
||||
|
||||
bios_init();
|
||||
|
||||
// Initialize all systems and power on
|
||||
system_poweron();
|
||||
|
||||
// Loop until the user closes the window
|
||||
while (!quit)
|
||||
{
|
||||
// Refresh video data
|
||||
video_update();
|
||||
|
||||
// Output audio
|
||||
Sound_Update();
|
||||
|
||||
// Execute frame(s)
|
||||
system_frame(0);
|
||||
|
||||
#ifdef VSYNC_SUPPORTED
|
||||
int arg = 0;
|
||||
if ( ioctl(fbfd, FBIO_WAITFORVSYNC, &arg) < 0 )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
if (selectpressed == 1)
|
||||
{
|
||||
Menu();
|
||||
input.system &= (IS_GG) ? ~INPUT_START : ~INPUT_PAUSE;
|
||||
selectpressed = 0;
|
||||
}
|
||||
|
||||
Controls();
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
29
source/ports/fbdev/smsplus.h
Normal file
29
source/ports/fbdev/smsplus.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef SMSPLUS_H
|
||||
#define SMSPLUS_H
|
||||
|
||||
#define HOST_WIDTH_RESOLUTION 320
|
||||
#define HOST_HEIGHT_RESOLUTION 240
|
||||
|
||||
#define VIDEO_WIDTH_SMS 256
|
||||
#define VIDEO_HEIGHT_SMS 192
|
||||
#define VIDEO_WIDTH_GG 160
|
||||
#define VIDEO_HEIGHT_GG 144
|
||||
|
||||
/* Right now it doesn't set VSYNC so disable for now */
|
||||
//#define VSYNC_SUPPORTED 1
|
||||
|
||||
typedef struct {
|
||||
char gamename[256];
|
||||
char sramdir[256];
|
||||
char sramfile[256];
|
||||
char stdir[256];
|
||||
char scrdir[256];
|
||||
char biosdir[256];
|
||||
} gamedata_t;
|
||||
|
||||
void smsp_state(uint8_t slot_number, uint8_t mode);
|
||||
|
||||
#define SOUND_FREQUENCY 44100
|
||||
#define SOUND_SAMPLES_SIZE 1024
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user