diff --git a/src/common/api.c b/src/common/api.c index 5761783..35542d7 100644 --- a/src/common/api.c +++ b/src/common/api.c @@ -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; diff --git a/src/common/api.h b/src/common/api.h index 9bbb0e7..56f05b4 100644 --- a/src/common/api.h +++ b/src/common/api.h @@ -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 diff --git a/src/keymon/keymon.c b/src/keymon/keymon.c index 8fd2682..025f52c 100644 --- a/src/keymon/keymon.c +++ b/src/keymon/keymon.c @@ -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 #include #include +#include #include #include #include @@ -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()); -} \ No newline at end of file + + // 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); + } +} diff --git a/src/libmsettings/msettings.h b/src/libmsettings/msettings.h index e8276ee..77b84cf 100644 --- a/src/libmsettings/msettings.h +++ b/src/libmsettings/msettings.h @@ -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__ diff --git a/src/minarch/main.c b/src/minarch/main.c index 044f44b..45c409e 100644 --- a/src/minarch/main.c +++ b/src/minarch/main.c @@ -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_ratiotarget_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; diff --git a/src/minarch/overrides/fceumm.h b/src/minarch/overrides/fceumm.h index bf0f6df..8a527c6 100644 --- a/src/minarch/overrides/fceumm.h +++ b/src/minarch/overrides/fceumm.h @@ -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}, diff --git a/todo.txt b/todo.txt index 66e0a99..885d5f2 100644 --- a/todo.txt +++ b/todo.txt @@ -3,6 +3,7 @@ Please see the README.txt in the zip file for installation and update instructions. *base* +- initial hdmi support - fixed input mapping for cores with different input modes - fixed late loading of configs (was preventing boot logos for certain systems) - fixed flicker at low end of screen brightness ramp