Compare commits

...

4 commits

Author SHA1 Message Date
rdanbrook 978366418b FLTK: Clean up Help->About 2024-06-01 21:55:03 -06:00
rdanbrook 249f1c22db FLTK: Add version.h 2024-06-01 21:43:21 -06:00
rdanbrook 0fe4aa5c80 FLTK: Fix aspect ratio and do special handling for overscan masking 2024-06-01 21:18:09 -06:00
rdanbrook cde9cb7e41 FLTK: Sync to latest jg.cpp 2024-06-01 20:33:02 -06:00
7 changed files with 121 additions and 48 deletions

View file

@ -739,6 +739,7 @@ nestopia_SOURCES += \
source/fltkui/uiadapter.h \
source/fltkui/videomanager.cpp \
source/fltkui/videomanager.h \
source/fltkui/version.h \
source/fltkui/jg.cpp \
source/fltkui/jg/jg.h \
source/fltkui/jg/jg_nes.h

View file

@ -56,6 +56,8 @@
#include "logdriver.h"
#include "version.h"
namespace {
int paused{0};
@ -398,50 +400,54 @@ static void fltkui_fds_insert(Fl_Widget* w, void* userdata) {
jg_media_insert();
}
static void fltkui_about_close(Fl_Widget* w, void* userdata) {
Fl_Window *about = (Fl_Window*)userdata;
void FltkUi::about_close(Fl_Widget *w, void *data) {
Fl_Window *about = (Fl_Window*)data;
about->hide();
}
static void fltkui_about(Fl_Widget* w, void* userdata) {
void FltkUi::about(Fl_Widget *w, void *data) {
Fl_Window about(460, 440);
Fl_Box iconbox(166, 16, 128, 128);
Fl_Box text0(0, 144, 460, UI_SPACING, "Nestopia UE");
text0.labelfont(FL_BOLD);
Fl_Box text1(0, 166, 460, UI_SPACING, "1.52.1");
Fl_Box text1(0, 166, 460, UI_SPACING, JG_VERSION);
Fl_Box text2(0, 208, 460, UI_SPACING, "Cycle-Accurate Nintendo Entertainment System Emulator");
Fl_Box text3(0, 256, 460, UI_SPACING, "FLTK Frontend\n(c) 2012-2024, R. Danbrook");
Fl_Box text3(0, 256, 460, UI_SPACING,
"FLTK Frontend\n(c) 2012-2024, R. Danbrook");
text3.labelsize(10);
Fl_Box text4(0, 320, 460, UI_SPACING, "Nestopia Emulator\n(c) 2020-2024, Rupert Carmichael\n(c) 2012-2020, Nestopia UE Contributors\n(c) 2003-2008, Martin Freij");
Fl_Box text4(0, 320, 460, UI_SPACING,
"Nestopia Emulator\n"
"(c) 2020-2024, Rupert Carmichael\n"
"(c) 2012-2020, Nestopia UE Contributors\n"
"(c) 2003-2008, Martin Freij");
text4.labelsize(10);
Fl_Box text5(0, 360, 460, UI_SPACING, "Icon based on drawing by Trollekop");
text5.labelsize(10);
// Set up the icon
char iconpath[512];
snprintf(iconpath, sizeof(iconpath), "%s/icons/hicolor/128x128/apps/nestopia.png", NST_DATAROOTDIR);
// Load the SVG from local source dir if make install hasn't been done
struct stat svgstat;
if (stat(iconpath, &svgstat) == -1) {
snprintf(iconpath, sizeof(iconpath), "icons/128/nestopia.png");
std::string iconpath{"icons/128/nestopia.png"};
if (!std::filesystem::exists(std::filesystem::path{iconpath})) {
iconpath = std::string(NST_DATAROOTDIR) + "/icons/hicolor/128x128/apps/nestopia.png";
}
Fl_PNG_Image nsticon(iconpath);
Fl_PNG_Image nsticon(iconpath.c_str());
iconbox.image(nsticon);
Fl_Button close(360, 400, 80, UI_SPACING, "&Close");
close.shortcut(FL_ALT + 'c');
close.callback(fltkui_about_close, (void*)&about);
close.callback(FltkUi::about_close, (void*)&about);
about.set_modal();
about.show();
while (about.shown()) { Fl::wait(); }
while (about.shown()) {
Fl::wait();
}
}
void FltkUi::quit(Fl_Widget *w, void *data) {
@ -546,7 +552,7 @@ static Fl_Menu_Item menutable[] = {
{"Settings...", 0, fltkui_settings, 0, 0},
{0}, // End Emulator
{"&Help", FL_ALT + 'h', 0, 0, FL_SUBMENU},
{"About", 0, fltkui_about, 0, 0},
{"About", 0, FltkUi::about, 0, 0},
{0}, // End Help
{0} // End Menu
};
@ -563,6 +569,7 @@ void FltkUi::show_msgbox(bool show) {
void makenstwin(const char *name) {
int rw, rh;
videomgr->set_dimensions();
videomgr->get_dimensions(&rw, &rh);
Fl::add_handler(handle);
@ -629,23 +636,10 @@ int main(int argc, char *argv[]) {
inputmgr = new InputManager(*jgm, *setmgr);
chtmgr = new CheatManager(*jgm);
makenstwin(argv[0]);
nstwin->label("Nestopia UE");
nstwin->show();
menubar->show();
glarea->make_current();
glarea->show();
videomgr->renderer_init();
Fl::check();
// Load a rom from the command line
if (argc > 1 && argv[argc - 1][0] != '-') {
fltkui_load_file(argv[argc - 1]);
if (jgm->is_loaded()) {
nstwin->label(jgm->get_gamename().c_str());
FltkUi::enable_menu();
jg_setup_audio();
jg_setup_video();
inputmgr->reassign();
@ -655,6 +649,25 @@ int main(int argc, char *argv[]) {
video_fullscreen = 0;
}
makenstwin(argv[0]);
if (jgm->is_loaded()) {
nstwin->label(jgm->get_gamename().c_str());
FltkUi::enable_menu();
}
else {
nstwin->label("Nestopia UE");
}
nstwin->show();
menubar->show();
glarea->make_current();
glarea->show();
videomgr->renderer_init();
Fl::check();
if (video_fullscreen) {
video_fullscreen = 0;
FltkUi::fullscreen(NULL, NULL);

View file

@ -44,4 +44,6 @@ public:
static void show_msgbox(bool show);
static void fullscreen(Fl_Widget *w = nullptr, void *data = nullptr);
static void quit(Fl_Widget *w = nullptr, void *data = nullptr);
static void about(Fl_Widget *w = nullptr, void *data = nullptr);
static void about_close(Fl_Widget *w = nullptr, void *data = nullptr);
};

View file

@ -141,6 +141,9 @@ void NstSettingsWindow::cb_slider(Fl_Widget *w, void *data) {
}
else {
jgm.rehash();
if (std::string(setting->name).find("overscan") != std::string::npos) {
FltkUi::rehash();
}
}
}

View file

@ -40,7 +40,7 @@
#include "core/api/NstApiCartridge.hpp"
#include "core/api/NstApiUser.hpp"
#include "core/api/NstApiFds.hpp"
//#include "version.h"
#include "version.h"
#define SAMPLERATE 48000
#define FRAMERATE 60.098814
@ -48,8 +48,8 @@
#define CHANNELS 1
#define NUMINPUTS 5
#define ASPECT_NTSC 1.3061224
#define ASPECT_PAL 1.4257812
#define ASPECT_NTSC 8.0 / 7.0
#define ASPECT_PAL 7375000.0 / 5320342.5
#define NTSC_FILTER_RATIO 2.3515625 // 602 / 256
using namespace Nes::Api;
@ -65,7 +65,7 @@ static jg_cb_log_t jg_cb_log;
static jg_cb_rumble_t jg_cb_rumble;
static jg_coreinfo_t coreinfo = {
"nestopia", "Nestopia JG", "1.52.1", "nes", NUMINPUTS, 0
"nestopia", "Nestopia JG", JG_VERSION, "nes", NUMINPUTS, 0
};
static jg_fileinfo_t biosinfo;
@ -77,11 +77,11 @@ static jg_videoinfo_t vidinfo = {
Video::Output::NTSC_WIDTH, // wmax
Video::Output::HEIGHT, // hmax
Video::Output::WIDTH, // w
Video::Output::HEIGHT - 16, // h
Video::Output::HEIGHT, // h
0, // x
8, // y
0, // y
Video::Output::NTSC_WIDTH, // p
ASPECT_NTSC, // aspect
(Video::Output::WIDTH * ASPECT_NTSC) / Video::Output::HEIGHT, // aspect
NULL
};
@ -152,6 +152,26 @@ static jg_setting_t settings_nst[] = {
"Set the NTSC Filter Mode",
0, 0, 3, 0
},
{ "overscan_t", "Overscan Mask (Top)",
"N = Hide N pixels of Overscan (Top)",
"Hide N pixels of Overscan (Top)",
8, 0, 12, 0
},
{ "overscan_b", "Overscan Mask (Bottom)",
"N = Hide N pixels of Overscan (Bottom)",
"Hide N pixels of Overscan (Bottom)",
8, 0, 12, 0
},
{ "overscan_l", "Overscan Mask (Left)",
"N = Hide N pixels of Overscan (Left)",
"Hide N pixels of Overscan (Left)",
0, 0, 12, 0
},
{ "overscan_r", "Overscan Mask (Right)",
"N = Hide N pixels of Overscan (Right)",
"Hide N pixels of Overscan (Right)",
0, 0, 12, 0
},
{ "favored_system", "Favored/System",
"0 = NTSC, 1 = PAL, 2 = Famicom, 3 = Dendy",
"Set the desired system in cases where a database entry does not exist",
@ -196,6 +216,10 @@ enum {
PALETTE,
NTSC,
NTSCMODE,
OVERSCAN_T,
OVERSCAN_B,
OVERSCAN_L,
OVERSCAN_R,
FAVSYSTEM,
FORCEREGION,
RAMPOWERSTATE,
@ -1000,7 +1024,21 @@ static void nst_params_video(void) {
// Set up video parameters
int renderwidth = settings_nst[NTSC].val ?
Video::Output::NTSC_WIDTH : Video::Output::WIDTH;
vidinfo.w = renderwidth;
unsigned aspect_w = Video::Output::WIDTH - (settings_nst[OVERSCAN_L].val +
settings_nst[OVERSCAN_R].val);
unsigned w = renderwidth - (settings_nst[OVERSCAN_L].val +
settings_nst[OVERSCAN_R].val);
unsigned h = Video::Output::HEIGHT - (settings_nst[OVERSCAN_T].val +
settings_nst[OVERSCAN_B].val);
vidinfo.w = w;
vidinfo.h = h;
vidinfo.x = settings_nst[OVERSCAN_L].val;
vidinfo.y = settings_nst[OVERSCAN_T].val;
bool pal = Machine(emulator).GetMode() == Machine::PAL;
vidinfo.aspect = (aspect_w * (pal ? ASPECT_PAL : ASPECT_NTSC)) / (double)h;
Video video(emulator);
Video::RenderState renderState;
@ -1300,12 +1338,10 @@ int jg_game_load(void) {
// Adjustments for PAL mode
if (machine.GetMode() == Machine::PAL) {
vidinfo.aspect = ASPECT_PAL;
audinfo.spf = (SAMPLERATE / (unsigned)FRAMERATE_PAL) * CHANNELS;
jg_cb_frametime(FRAMERATE_PAL);
}
else {
vidinfo.aspect = ASPECT_NTSC;
audinfo.spf = (SAMPLERATE / (unsigned)FRAMERATE) * CHANNELS;
jg_cb_frametime(FRAMERATE);
}

View file

@ -786,15 +786,6 @@ VideoManager::VideoManager(JGManager& jgm, SettingManager& setmgr)
videobuf = (uint32_t*)calloc(1, vidinfo->hmax * vidinfo->wmax * sizeof(uint32_t));
vidinfo->buf = (void*)&videobuf[0];
set_aspect();
int scale = setmgr.get_setting("v_scale")->val;
dimensions.ww = (aspect * vidinfo->h * scale) + 0.5;
dimensions.wh = (vidinfo->h * scale) + 0.5;
dimensions.rw = dimensions.ww;
dimensions.rh = dimensions.wh;
dimensions.dpiscale = 1.0;
}
VideoManager::~VideoManager() {
@ -828,6 +819,31 @@ void VideoManager::get_dimensions(int *w, int *h) {
*h = dimensions.rh;
}
void VideoManager::set_dimensions() {
// Try to guess the correct video parameters if no game is loaded
if (!jgm.is_loaded()) {
int t = jgm.get_setting("overscan_t")->val;
int b = jgm.get_setting("overscan_b")->val;
int l = jgm.get_setting("overscan_l")->val;
int r = jgm.get_setting("overscan_r")->val;
vidinfo->w = vidinfo->w - (l + r);
vidinfo->h = vidinfo->h - (t + b);
vidinfo->x = l;
vidinfo->y = t;
vidinfo->aspect = (vidinfo->w * 8.0 / 7.0) / vidinfo->h; // NTSC
}
set_aspect();
int scale = setmgr.get_setting("v_scale")->val;
dimensions.ww = (aspect * vidinfo->h * scale) + 0.5;
dimensions.wh = (vidinfo->h * scale) + 0.5;
dimensions.rw = dimensions.ww;
dimensions.rh = dimensions.wh;
dimensions.dpiscale = 1.0;
}
// FIXME maybe use std::tuple here
void VideoManager::get_scaled_coords(int x, int y, int *xcoord, int *ycoord) {
float xscale = dimensions.rw / (vidinfo->aspect * vidinfo->h) / dimensions.dpiscale;

View file

@ -86,6 +86,8 @@ public:
~VideoManager();
void get_dimensions(int *w, int *h);
void set_dimensions();
void get_scaled_coords(int x, int y, int *xcoord, int *ycoord);
void rehash(bool reset_shaders = false);