reeeeally rough first pass at hdmi support
This commit is contained in:
parent
a416457520
commit
e2f7c63892
8 changed files with 167 additions and 55 deletions
|
|
@ -247,8 +247,8 @@ SDL_Surface* GFX_init(int mode) {
|
|||
ioctl(gfx.fb0_fd, FBIOGET_FSCREENINFO, &gfx.finfo);
|
||||
ioctl(gfx.fb0_fd, FBIOGET_VSCREENINFO, &gfx.vinfo);
|
||||
gfx.vinfo.bits_per_pixel = FIXED_DEPTH;
|
||||
gfx.vinfo.xres = FIXED_WIDTH;
|
||||
gfx.vinfo.yres = FIXED_HEIGHT;
|
||||
gfx.vinfo.xres = SCREEN_WIDTH;
|
||||
gfx.vinfo.yres = SCREEN_HEIGHT;
|
||||
gfx.vinfo.xres_virtual = VIRTUAL_WIDTH;
|
||||
gfx.vinfo.yres_virtual = VIRTUAL_HEIGHT;
|
||||
gfx.vinfo.xoffset = 0;
|
||||
|
|
@ -275,7 +275,7 @@ SDL_Surface* GFX_init(int mode) {
|
|||
gfx.fb0_buffer = mmap(0, gfx.finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, gfx.fb0_fd, 0);
|
||||
memset(gfx.fb0_buffer, 0, VIRTUAL_SIZE); // clear both buffers
|
||||
|
||||
gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), FIXED_WIDTH,FIXED_HEIGHT, FIXED_DEPTH,FIXED_PITCH, 0,0,0,0);
|
||||
gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), SCREEN_WIDTH,SCREEN_HEIGHT, FIXED_DEPTH,SCREEN_PITCH, 0,0,0,0);
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
|
|
@ -329,10 +329,10 @@ void GFX_quit(void) {
|
|||
|
||||
// restore for other binaries
|
||||
gfx.vinfo.bits_per_pixel = FIXED_DEPTH;
|
||||
gfx.vinfo.xres = FIXED_WIDTH;
|
||||
gfx.vinfo.yres = FIXED_HEIGHT;
|
||||
gfx.vinfo.xres_virtual = FIXED_WIDTH;
|
||||
gfx.vinfo.yres_virtual = FIXED_HEIGHT;
|
||||
gfx.vinfo.xres = SCREEN_WIDTH;
|
||||
gfx.vinfo.yres = SCREEN_HEIGHT;
|
||||
gfx.vinfo.xres_virtual = SCREEN_WIDTH;
|
||||
gfx.vinfo.yres_virtual = SCREEN_HEIGHT;
|
||||
gfx.vinfo.xoffset = 0;
|
||||
gfx.vinfo.yoffset = 0;
|
||||
if (ioctl(gfx.fb0_fd, FBIOPUT_VSCREENINFO, &gfx.vinfo)) LOG_info("FBIOPUT_VSCREENINFO failed %s\n", strerror(errno));
|
||||
|
|
@ -373,6 +373,7 @@ SDL_Surface* GFX_resize(int w, int h, int pitch) {
|
|||
if (gfx.screen) SDL_FreeSurface(gfx.screen);
|
||||
|
||||
gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), w,h, FIXED_DEPTH,pitch, 0,0,0,0);
|
||||
LOG_info("fb offset: %i end: %i all: %i\n", gfx.screen->pixels - gfx.fb0_buffer, gfx.screen->pixels - gfx.fb0_buffer + PAGE_SIZE, gfx.finfo.smem_len);
|
||||
memset(gfx.screen->pixels, 0, PAGE_SIZE);
|
||||
|
||||
gfx.vinfo.xres = w;
|
||||
|
|
@ -1205,12 +1206,7 @@ static void POW_initOverlay(void) {
|
|||
GFX_blitAsset(ASSET_BLACK_PILL, NULL, pow.overlay, NULL);
|
||||
SDL_SetAlpha(gfx.assets, SDL_SRCALPHA,0);
|
||||
GFX_blitBattery(pow.overlay, NULL);
|
||||
|
||||
// SDL_Rect rect = asset_rects[ASSET_BATTERY];
|
||||
// int ox = (SCALE1(PILL_SIZE) - (rect.w + SCREEN_SCALE)) / 2;
|
||||
// int oy = (SCALE1(PILL_SIZE) - rect.h) / 2;
|
||||
// GFX_blitAsset(ASSET_BATTERY_LOW, NULL, pow.overlay, &(SDL_Rect){ox,oy});
|
||||
|
||||
|
||||
// setup overlay
|
||||
memset(&pow.oargs, 0, sizeof(struct owlfb_overlay_args));
|
||||
pow.oargs.fb_id = OVERLAY_FB;
|
||||
|
|
@ -1220,7 +1216,7 @@ static void POW_initOverlay(void) {
|
|||
|
||||
int x,y,w,h;
|
||||
w = h = pow.overlay->w;
|
||||
x = FIXED_WIDTH - SCALE1(PADDING) - w;
|
||||
x = SCREEN_WIDTH - SCALE1(PADDING) - w;
|
||||
y = SCALE1(PADDING);
|
||||
|
||||
pow.oinfo.mem_off = offset;
|
||||
|
|
@ -1370,7 +1366,7 @@ void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, PO
|
|||
}
|
||||
|
||||
#define MENU_DELAY 250 // also in PAD_tappedMenu()
|
||||
if (PAD_justRepeated(BTN_PLUS) || PAD_justRepeated(BTN_MINUS) || (PAD_isPressed(BTN_MENU) && now-menu_start>=MENU_DELAY)) {
|
||||
if (PAD_justRepeated(BTN_PLUS) || PAD_justRepeated(BTN_MINUS) || (PAD_isPressed(BTN_MENU) && now-menu_start>=MENU_DELAY && !GetHDMI())) {
|
||||
setting_start = now;
|
||||
if (PAD_isPressed(BTN_MENU)) {
|
||||
show_setting = 1;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@ void LOG_note(int level, const char* fmt, ...);
|
|||
#define FIXED_PITCH FIXED_WIDTH * FIXED_BPP
|
||||
#define FIXED_SIZE FIXED_HEIGHT * FIXED_PITCH
|
||||
|
||||
#define HDMI_WIDTH 1280
|
||||
#define HDMI_HEIGHT 720
|
||||
#define HDMI_PITCH HDMI_WIDTH * FIXED_BPP
|
||||
#define HDMI_SIZE HDMI_HEIGHT * HDMI_PITCH
|
||||
|
||||
#define PAGE_COUNT 2
|
||||
#define PAGE_SCALE 2
|
||||
#define PAGE_WIDTH FIXED_WIDTH * PAGE_SCALE
|
||||
|
|
|
|||
|
|
@ -26,36 +26,56 @@
|
|||
#define INPUT_COUNT 2
|
||||
static int inputs[INPUT_COUNT];
|
||||
static struct input_event ev;
|
||||
|
||||
static int jack_fd;
|
||||
static pthread_t jack_pt;
|
||||
static pthread_t ports_pt;
|
||||
|
||||
#define JACK_STATE_PATH "/sys/class/switch/h2w/state"
|
||||
#define HDMI_STATE_PATH "/sys/class/switch/hdmi/state" // TODO:
|
||||
#define HDMI_STATE_PATH "/sys/class/switch/hdmi/state"
|
||||
|
||||
static void* watchJack(void *arg) {
|
||||
uint32_t has_headphones;
|
||||
uint32_t had_headphones;
|
||||
int getInt(char* path) {
|
||||
int i = 0;
|
||||
FILE *file = fopen(path, "r");
|
||||
if (file!=NULL) {
|
||||
fscanf(file, "%i", &i);
|
||||
fclose(file);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// TODO: test HDMI connect/disconnect
|
||||
// TODO: still resetting between launches
|
||||
static void* watchPorts(void *arg) {
|
||||
int has_headphones,had_headphones;
|
||||
int has_hdmi,had_hdmi;
|
||||
|
||||
FILE *file = fopen(JACK_STATE_PATH, "r");
|
||||
fscanf(file, "%i", &has_headphones);
|
||||
had_headphones = has_headphones;
|
||||
has_headphones = had_headphones = getInt(JACK_STATE_PATH);
|
||||
has_hdmi = had_hdmi = getInt(HDMI_STATE_PATH);
|
||||
SetJack(has_headphones);
|
||||
SetHDMI(has_hdmi);
|
||||
|
||||
while(1) {
|
||||
sleep(1);
|
||||
rewind(file);
|
||||
fscanf(file, "%i", &has_headphones);
|
||||
|
||||
has_headphones = getInt(JACK_STATE_PATH);
|
||||
if (had_headphones!=has_headphones) {
|
||||
had_headphones = has_headphones;
|
||||
SetJack(has_headphones);
|
||||
}
|
||||
|
||||
has_hdmi = getInt(HDMI_STATE_PATH);
|
||||
if (had_hdmi!=has_hdmi) {
|
||||
had_hdmi = has_hdmi;
|
||||
SetHDMI(has_hdmi);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
InitSettings();
|
||||
pthread_create(&jack_pt, NULL, &watchJack, NULL);
|
||||
pthread_create(&ports_pt, NULL, &watchPorts, NULL);
|
||||
|
||||
char path[32];
|
||||
for (int i=0; i<INPUT_COUNT; i++) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/fb.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
@ -12,30 +13,38 @@
|
|||
|
||||
///////////////////////////////////////
|
||||
|
||||
#define SETTINGS_VERSION 2
|
||||
typedef struct Settings {
|
||||
int version; // future proofing
|
||||
int brightness;
|
||||
int headphones;
|
||||
int speaker;
|
||||
int unused[3]; // for future use
|
||||
int jack; // NOTE: doesn't really need to be persisted but still needs to be shared
|
||||
int unused[2]; // for future use
|
||||
// NOTE: doesn't really need to be persisted but still needs to be shared
|
||||
int jack;
|
||||
int hdmi;
|
||||
} Settings;
|
||||
static Settings DefaultSettings = {
|
||||
.version = 1,
|
||||
.version = SETTINGS_VERSION,
|
||||
.brightness = 2,
|
||||
.headphones = 4,
|
||||
.speaker = 8,
|
||||
.jack = 0,
|
||||
.hdmi = 0,
|
||||
};
|
||||
static Settings* settings;
|
||||
|
||||
#define SHM_KEY "/SharedSettings"
|
||||
// static char SettingsPath[256];
|
||||
static char* SettingsPath = "/mnt/sdcard/.userdata/rg35xx/msettings.bin";
|
||||
static int shm_fd = -1;
|
||||
static int is_host = 0;
|
||||
static int shm_size = sizeof(Settings);
|
||||
|
||||
#define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power"
|
||||
#define BRIGHTNESS_PATH "/sys/class/backlight/backlight.2/brightness"
|
||||
#define VOLUME_PATH "/sys/class/volume/value"
|
||||
#define MIRROR_PATH "/sys/class/graphics/fb0/mirror_to_hdmi"
|
||||
|
||||
void InitSettings(void) {
|
||||
// sprintf(SettingsPath, "%s/msettings.bin", getenv("USERDATA_PATH"));
|
||||
|
||||
|
|
@ -46,7 +55,7 @@ void InitSettings(void) {
|
|||
settings = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
|
||||
}
|
||||
else { // host
|
||||
puts("Settings host");
|
||||
puts("Settings host"); // keymon
|
||||
is_host = 1;
|
||||
// we created it so set initial size and populate
|
||||
ftruncate(shm_fd, shm_size);
|
||||
|
|
@ -55,18 +64,22 @@ void InitSettings(void) {
|
|||
int fd = open(SettingsPath, O_RDONLY);
|
||||
if (fd>=0) {
|
||||
read(fd, settings, shm_size);
|
||||
// TODO: use settings->version for future proofing
|
||||
// TODO: use settings->version for future proofing?
|
||||
close(fd);
|
||||
}
|
||||
else {
|
||||
// load defaults
|
||||
memcpy(settings, &DefaultSettings, shm_size);
|
||||
}
|
||||
|
||||
// these shouldn't be persisted
|
||||
// settings->jack = 0;
|
||||
// settings->hdmi = 0;
|
||||
}
|
||||
printf("brightness: %i\nspeaker: %i \n", settings->brightness, settings->speaker);
|
||||
|
||||
|
||||
SetVolume(GetVolume());
|
||||
SetBrightness(GetBrightness());
|
||||
SetBrightness(GetBrightness()); // also sets HDMI
|
||||
}
|
||||
void QuitSettings(void) {
|
||||
munmap(settings, shm_size);
|
||||
|
|
@ -117,26 +130,60 @@ void SetVolume(int value) {
|
|||
}
|
||||
|
||||
void SetRawBrightness(int val) { // 0 - 1024
|
||||
int fd = open("/sys/class/backlight/backlight.2/brightness", O_WRONLY);
|
||||
// printf("SetRawBrightness(%i)\n", val); fflush(stdout);
|
||||
int fd = open(BRIGHTNESS_PATH, O_WRONLY);
|
||||
if (fd>=0) {
|
||||
dprintf(fd,"%d",val);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// this prevents exiting/launching from turning the screen back on
|
||||
SetHDMI(GetHDMI()); // TODO: isn't working
|
||||
}
|
||||
void SetRawVolume(int val) { // 0 - 40
|
||||
int fd = open("/sys/class/volume/value", O_WRONLY);
|
||||
int fd = open(VOLUME_PATH, O_WRONLY);
|
||||
if (fd>=0) {
|
||||
dprintf(fd,"%d",val);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
// monitored and set by thread in keymon
|
||||
int GetJack(void) {
|
||||
// return /sys/class/switch/h2w/state==1`
|
||||
// access("/dev/dsp1", F_OK)==0
|
||||
return settings->jack;
|
||||
}
|
||||
void SetJack(int value) { // monitored and set by thread in keymon
|
||||
void SetJack(int value) {
|
||||
// printf("SetJack(%i)\n", value); fflush(stdout);
|
||||
|
||||
settings->jack = value;
|
||||
SetVolume(GetVolume());
|
||||
}
|
||||
|
||||
// TODO: tmp, testing hdmi without an hdmi output
|
||||
// int fd = open(BACKLIGHT_PATH, O_WRONLY);
|
||||
// if (fd>=0) {
|
||||
// dprintf(fd,"%d",value ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
|
||||
// close(fd);
|
||||
// }
|
||||
}
|
||||
|
||||
int GetHDMI(void) {
|
||||
// TODO: tmp, testing hdmi without an hdmi output
|
||||
// return settings->jack;
|
||||
return settings->hdmi;
|
||||
}
|
||||
void SetHDMI(int value) {
|
||||
// printf("SetHDMI(%i)\n", value); fflush(stdout);
|
||||
|
||||
settings->hdmi = value;
|
||||
int fd = open(MIRROR_PATH, O_WRONLY);
|
||||
if (fd>=0) {
|
||||
dprintf(fd,"%d",value);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
fd = open(BACKLIGHT_PATH, O_WRONLY);
|
||||
if (fd>=0) {
|
||||
dprintf(fd,"%d",value ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,4 +16,7 @@ void SetVolume(int value); // 0-20
|
|||
int GetJack(void);
|
||||
void SetJack(int value); // 0-1
|
||||
|
||||
int GetHDMI(void);
|
||||
void SetHDMI(int value); // 0-1
|
||||
|
||||
#endif // __msettings_h__
|
||||
|
|
|
|||
|
|
@ -1205,12 +1205,16 @@ void Input_init(const struct retro_input_descriptor *vars) {
|
|||
}
|
||||
}
|
||||
|
||||
puts("---------------------------------");
|
||||
|
||||
for (int i=0;default_button_mapping[i].name; i++) {
|
||||
ButtonMapping* mapping = &default_button_mapping[i];
|
||||
LOG_info("DEFAULT %s (%s): <%s>\n", core_button_names[mapping->retro], mapping->name, (mapping->local==BTN_ID_NONE ? "NONE" : device_button_names[mapping->local]));
|
||||
mapping->name = (char*)core_button_names[mapping->retro];
|
||||
}
|
||||
|
||||
puts("---------------------------------");
|
||||
|
||||
for (int i=0; config.controls[i].name; i++) {
|
||||
ButtonMapping* mapping = &config.controls[i];
|
||||
mapping->default_ = mapping->local;
|
||||
|
|
@ -2306,10 +2310,13 @@ static void selectScaler_AR(int width, int height, int pitch) {
|
|||
int src_w = width;
|
||||
int src_h = height;
|
||||
|
||||
int scale_x = CEIL_DIV(FIXED_WIDTH, src_w);
|
||||
int scale_y = CEIL_DIV(FIXED_HEIGHT,src_h);
|
||||
int has_hdmi = GetHDMI();
|
||||
int scale_x = CEIL_DIV(has_hdmi ? HDMI_WIDTH : SCREEN_WIDTH, src_w);
|
||||
int scale_y = CEIL_DIV(has_hdmi ? HDMI_HEIGHT: SCREEN_HEIGHT,src_h);
|
||||
int scale = MAX(scale_x, scale_y);
|
||||
|
||||
// TODO: this "logic" is a disaster
|
||||
|
||||
// if (scale>6) scale = 6;
|
||||
// else
|
||||
if (scale>2) scale = 4; // TODO: pillar/letterboxing at 3x produces vertical banding (some kind of alignment issue?)
|
||||
|
|
@ -2328,20 +2335,47 @@ static void selectScaler_AR(int width, int height, int pitch) {
|
|||
|
||||
char scaler_name[8];
|
||||
#define FOUR_THREE 4.0f / 3
|
||||
#define SIXTEEN_NINE 16.0 / 9
|
||||
|
||||
double target_ratio = has_hdmi ? SIXTEEN_NINE : FOUR_THREE;
|
||||
|
||||
if (screen_scaling==1) {
|
||||
sprintf(scaler_name, "AR_%iX", scale);
|
||||
if (core.aspect_ratio==FOUR_THREE) {
|
||||
// LOG_info("already 4:3\n");
|
||||
}
|
||||
else if (core.aspect_ratio<FOUR_THREE) {
|
||||
// LOG_info("pillarbox\n");
|
||||
target_w = CEIL_DIV(src_h, 3) * 4 * scale;
|
||||
target_h = src_h * scale;
|
||||
sprintf(scaler_name, "AR_%iX%s", scale, has_hdmi?"W":"R");
|
||||
if (core.aspect_ratio==target_ratio) {
|
||||
// LOG("already correct ratio\n");
|
||||
}
|
||||
else {
|
||||
// LOG_info("letterbox\n");
|
||||
target_w = src_w * scale;
|
||||
target_h = CEIL_DIV(src_w, 4) * 3 * scale;
|
||||
// TODO: is this ignoring the core's desired aspect ratio?
|
||||
|
||||
int ratio_left = target_ratio==SIXTEEN_NINE ? 16 : 4;
|
||||
int ratio_right = target_ratio==SIXTEEN_NINE ? 9 : 3;
|
||||
|
||||
// TODO: why do these use CEIL_DIV?
|
||||
if (core.aspect_ratio<target_ratio) {
|
||||
// LOG_info("pillarbox\n");
|
||||
target_w = CEIL_DIV(src_h, ratio_right) * ratio_left * scale;
|
||||
target_h = src_h * scale;
|
||||
}
|
||||
else if (core.aspect_ratio>target_ratio) {
|
||||
// LOG_info("letterbox\n");
|
||||
target_w = src_w * scale;
|
||||
target_h = CEIL_DIV(src_w, ratio_left) * ratio_right * scale;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
if (target_w > PAGE_WIDTH) {
|
||||
target_h = CEIL_DIV(PAGE_WIDTH, ratio_left) * ratio_right;
|
||||
target_w = PAGE_WIDTH;
|
||||
|
||||
if (dst_h > target_h) {
|
||||
scale -= 1;
|
||||
dst_w = src_w * scale;
|
||||
dst_h = src_h * scale;
|
||||
}
|
||||
sprintf(scaler_name, "AR_%iXD", scale);
|
||||
|
||||
LOG_warn("target: %ix%i (%i) page: %ix%i (%i) \n", target_w,target_h, target_w*target_h*FIXED_BPP, PAGE_WIDTH,PAGE_HEIGHT,PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -2350,17 +2384,23 @@ static void selectScaler_AR(int width, int height, int pitch) {
|
|||
|
||||
if (target_w%2) target_w += 1;
|
||||
if (target_h%2) target_h += 1;
|
||||
|
||||
|
||||
int dx = (target_w - dst_w) / 2;
|
||||
int dy = (target_h - dst_h) / 2;
|
||||
|
||||
// TODO: this masks a larger problem above
|
||||
if (dx<0) dx = 0;
|
||||
if (dy<0) dy = 0;
|
||||
|
||||
int target_pitch = target_w * FIXED_BPP;
|
||||
|
||||
renderer.dst_w = target_w;
|
||||
renderer.dst_h = target_h;
|
||||
renderer.dst_p = target_pitch;
|
||||
renderer.dst_offset = (dy * target_pitch) + (dx * FIXED_BPP);
|
||||
|
||||
if (has_hdmi) LOG_warn("dst offset: %i,%i (%i)\n", dx,dy, renderer.dst_offset);
|
||||
|
||||
switch (scale) {
|
||||
case 6: renderer.scaler = scale6x_n16; break;
|
||||
case 5: renderer.scaler = scale5x_n16; break;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ static CoreOverrides fceumm_overrides = {
|
|||
.option_overrides = (OptionOverride[]){
|
||||
{"fceumm_sndquality", "High"},
|
||||
{"fceumm_sndvolume", "10"},
|
||||
{"fceumm_turbo_enable", "Player 1"}, // stupidly defaults to None
|
||||
{"fceumm_turbo_enable", "Player 1"}, // stupidly defaults to None despite binding turbo buttons by default
|
||||
{"fceumm_show_adv_system_options","disabled",1}, // doesn't do anything
|
||||
{"fceumm_show_adv_sound_options","disabled", 1}, // doesn't do anything
|
||||
{NULL,NULL},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue