⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uifltk-ui.cpp

📁 一个任天堂掌上游戏机NDS的源代码
💻 CPP
字号:
/*************************************************************************** DSemu - The Next Generation                                             ** Fltk user interface: Interface handlers [uifltk-ui.cpp]                 ** Copyright Imran Nazar, 2005; released under the BSD public licence.     ** Fltk used under the terms of the LGPL.                                  ***************************************************************************/#include <map>#include <FL/Fl.h>#include <FL/fl_draw.H>#include "uifltk.h"#include "plugin.h"#include "log.h"#include "w32compile.h"//---Static private class members, and a fair few of them------------------u8 *UIFltk::UI::outbuf;UIFltk::UI *UIFltk::ui=NULL;Fl_Menu_Bar *UIFltk::UI::mbar;Fl_Box *UIFltk::UI::sbarl, *UIFltk::UI::sbarr;Fl_Box *UIFltk::UI::display;Fl_Group *UIFltk::UI::mbarcon;std::map<int, UIFltk::UI::SubWindow*> UIFltk::UI::subwindows;std::deque<EventMsg> UIFltk::UI::events;MMU32Plugin *UIFltk::UI::mmu, *UIFltk::UI::mmuSub;CPUPlugin *UIFltk::UI::cpu, *UIFltk::UI::cpuSub;GPUPlugin *UIFltk::UI::gpu;APUPlugin *UIFltk::UI::apu;Plugin *UIFltk::UI::timer;std::string UIFltk::UI::ROMpath;int UIFltk::UI::loaded=0;int UIFltk::UI::running=0;int UIFltk::UI::stepping=0;int UIFltk::UI::frames=0;int UIFltk::UI::DSmode=0;uint64_t UIFltk::UI::timestamp=0;int UIFltk::UI::cpuStatMode=3;int UIFltk::UI::mmuDumpAddr=0x04000000;int UIFltk::UI::mmuDumpMode=1;u16 UIFltk::UI::keys=0xFFFF;REQPTR UIFltk::pRequest;UNREQPTR UIFltk::pUnrequest;UIFltk::UI::BkptWindow *UIFltk::UI::bkptWnd;int UIFltk::UI::bkptVisible=0;UIFltk::UI::LogWindow *UIFltk::UI::logWnd;int UIFltk::UI::logVisible=0;UIFltk::UI::AboutWindow *UIFltk::UI::aboutWnd;int UIFltk::UI::aboutVisible=0;// Used by the Events map to work out sorting order (sort on timestamp)bool operator<(const EventMsg &a, const EventMsg &b) { return a.getTime()<b.getTime(); }		  //---Handlers--------------------------------------------------------------// Initialise the windowUIFltk::UI::UI(int x, int y, int w, int h, const char *title) : Fl_Double_Window(x,y,w,h,title){    // We couldn't set these callbacks statically, so do it now.    menu[MENU_FILE_OPENGBA].callback(cbOpenGBA, this);    menu[MENU_FILE_OPENDS].callback(cbOpenDS, this);    menu[MENU_FILE_CLOSE].callback(cbClose, this);    menu[MENU_FILE_EXIT].callback(cbExit, this);    menu[MENU_DEBUG_RUN].callback(cbRun, this);    menu[MENU_DEBUG_RESET].callback(cbReset, this);    menu[MENU_DEBUG_BKPT].callback(cbBkpt, this);    menu[MENU_DEBUG_STEP].callback(cbStep, this);    menu[MENU_DEBUG_ASTEP].callback(cbAStep, this);    menu[MENU_VIEW_LOG].callback(cbLog, this);    menu[MENU_HELP_ABOUT].callback(cbAbout, this);        // Define the window controls    begin();    	display = new Fl_Box(0, 18, 240, 1);	display->box(FL_NO_BOX);	        mbarcon = new Fl_Group(0, 0, 240, 18);	mbarcon->box(FL_NO_BOX);	mbarcon->begin();	            mbar = new Fl_Menu_Bar(0, 0, 240, 18);            mbar->copy(&menu[0]);            mbar->box(FL_FLAT_BOX);            mbar->align(FL_ALIGN_INSIDE|FL_ALIGN_TOP|FL_ALIGN_LEFT);	mbarcon->end();	sbarl = new Fl_Box(0, 19, 56, 18);	sbarl->box(FL_THIN_DOWN_BOX);	sbarl->labelsize(11);	sbarl->align(FL_ALIGN_INSIDE|FL_ALIGN_TOP|FL_ALIGN_LEFT);		sbarr = new Fl_Box(56, 19, 184, 18, "Application loaded.");	sbarr->box(FL_THIN_DOWN_BOX);	sbarr->labelsize(11);	sbarr->align(FL_ALIGN_INSIDE|FL_ALIGN_TOP|FL_ALIGN_LEFT);	    end();    Fl::visual(FL_RGB);    resizable(display);    // Set the minimal size of the window (at least menu and statusbar)    size_range(240,37, 240,37);    color(FL_BLACK);    show();    logVisible=0;      Logger::log(pluginName) << "Interface brought up.";}// Shut down interface: free up the log windowUIFltk::UI::~UI(){    if(logWnd) { logWnd->hide(); delete logWnd; logWnd=NULL; }}// Redraw window: fill the framebuffervoid UIFltk::UI::draw(){    Fl_Double_Window::draw();    if(loaded && outbuf)        fl_draw_image(outbuf, 0,18, 240,160, 4);}// Make a subwindowint UIFltk::UI::subwinCreate(int xd, int yd, const char *title, u32 *buf){    int id;        // Generate a random ID; if it's already in the map, make another.    do id=(0xCAFE0003+(rand()&32767)); while(subwindows.find(id) != subwindows.end());    // Create a new entry in the subwindow map.    subwindows[id] = new SubWindow(xd, yd, this);    subwindows[id]->winID = id;    subwindows[id]->buffer = buf;    subwindows[id]->visible = 0;    subwindows[id]->title = title;    subwindows[id]->label(title);    // Add the title to the View menu as a checkbox option.    Fl_Menu_Item item={title,0,cbSub,0,0,0,0,11};    item.callback(cbSub,this);    item.flags=FL_MENU_TOGGLE;    menu.insert(menu.begin()+MENU_OPT-2, item);    mbar->copy(&menu[0]);        char str[64];    sprintf(str, "Subwindow %08X created.", id);    Logger::log(pluginName) << str;        return id;}// Refresh a subwindow; tell it to redraw itself.void UIFltk::UI::subwinRefresh(int id){    subwindows[id]->redraw();}// Run the emulation for a framevoid UIFltk::UI::execFrame(){    if(loaded && running)    {	int t, clk, frameclk=0, cyc;	EventMsg ev;	// Pop an event from the events queue, run until the time it says,	// then do the action it says. Keep doing this until we run out of	// time for this frame.	do {	    if(!events.empty())	    {                ev = events.front();		events.pop_front();                t=ev.getTime()-timestamp;//                printf("Time %lld: Executing %d cycles to %lld. Queue is %d entries.\n", timestamp, t, ev.getTime(), events.size());	        clk=0;                if(t)                {                    do                    {			if(DSmode)			{			    cyc = cpu->exec(1);			    if(cyc>=0) clk+=cyc;			    else { timestamp -= cyc; events.push_front(EventMsg(ev)); cbRunI(); return; }			    cyc = cpu->exec(1);			    if(cyc>=0) clk+=cyc;			    else { timestamp -= cyc; events.push_front(EventMsg(ev)); cbRunI(); return; }			    cyc = cpuSub->exec(1);			    if(cyc<0) { events.push_front(EventMsg(ev)); cbRunI(); return; }			} else {                            cyc = cpu->exec(t-clk);                            if(cyc >= 0) clk += cyc;                            else	                    {                                // If we hit a breakpoint, the return will be negative.                                // Put the event back, because we didn't finish it yet.                                timestamp -= cyc;//                                printf("Breakpoint reached at %lld.\n", timestamp);                                events.push_front(EventMsg(ev));                                cbRunI(); return;                            }			}                    } while(clk<t);                }                timestamp = ev.getTime(); frameclk+=t;                ev.callFunc();	    }	} while(frameclk < 228*1232);	frames++;	redraw();    }}// Run the emulation for at most one instructionvoid UIFltk::UI::execStep(){    static EventMsg ev; static int t=-8388608, subflag=0; int clk=0;    // If there's no event to head towards, don't bother.    if(!events.empty())    {        ev = events.front(); t=ev.getTime()-timestamp;//        printf("Time %lld: %d left to next event. Queue is %d entries.\n", timestamp, t, events.size());        // If this event is now, run the callback.	if(t<=0)	{//	    printf("Time reached. Popping event.\n");	    events.pop_front();	    ev.callFunc();	}	// Execute "one clock"; will always run at least one instruction.	if(DSmode && subflag)	{	    clk = cpu->exec(1);	    cpuSub->exec(1);	}	else clk = cpu->exec(1);	subflag=!subflag;        t-=clk; timestamp+=clk;//	eventPush(ev.getTime(), ev.getType(), ev.getFunc(), ev.getData());    }    frames=0; redraw();}// If a plugin wants to know where the UI is, tell it.uint64_t UIFltk::UI::getTimestamp(){    return timestamp;}// Push an event into the queue at the back, and sort by timestamp.void UIFltk::UI::eventPush(u32 etime, int type, vfptr func, void *data){    events.push_back(EventMsg(timestamp+etime, type, func, data, 0));    std::sort(events.begin(), events.end());//    printf("Pushed at %lld: In %d cycles, call %08X(%08X). %d in queue.\n", timestamp, etime, func, data, events.size());}// Window event handlerint UIFltk::UI::handle(int e){    int ret = Fl_Window::handle(e);    // If there are any subwindows with the event ID, something made that    // subwindow hidden. Update the status for that subwindow.    if(subwindows.find(e) != subwindows.end())    {	if(subwindows[e]->visible) cbSubI(subwindows[e]->title);    }        switch(e)    {        case FL_HIDE:	    if(loaded) cbCloseI();	    break;	case 0xBEEF0001:	    logVisible=1; cbLogI(); break;	case 0xBEEF0002:	    aboutVisible=1; cbAboutI(); break;	case 0xBEEF0003:	    bkptVisible=1; cbBkptI(); break;	// If a key was hit, update REGKEYS.	// TODO: Configurable keys	case FL_KEYDOWN:	    if(loaded)	    {		switch(Fl::event_key())		{                    case 'z': keys &= ~0x0001; break;                    case 'x': keys &= ~0x0002; break;                    case FL_BackSpace: keys &= ~0x0004; break;                    case FL_Enter: keys &= ~0x0008; break;                    case FL_Right: keys &= ~0x0010; break;                    case FL_Left: keys &= ~0x0020; break;                    case FL_Up: keys &= ~0x0040; break;                    case FL_Down: keys &= ~0x0080; break;                    case 's': keys &= ~0x0100; break;                    case 'a': keys &= ~0x0200; break;		}	    }	    break;	case FL_KEYUP:	    if(loaded)	    {		switch(Fl::event_key())		{                    case 'z': keys |= 0x0001; break;                    case 'x': keys |= 0x0002; break;                    case FL_BackSpace: keys |= 0x0004; break;                    case FL_Enter: keys |= 0x0008; break;                    case FL_Right: keys |= 0x0010; break;                    case FL_Left: keys |= 0x0020; break;                    case FL_Up: keys |= 0x0040; break;                    case FL_Down: keys |= 0x0080; break;                    case 's': keys |= 0x0100; break;                    case 'a': keys |= 0x0200; break;		}	    }	    break;    }    return ret;}// Update the status bar with the current FPSvoid UIFltk::UI::cbFPScount(void *in){    static char str[64];    if(((UIFltk::UI*)in)->frames)    {        sprintf(str, "%d fps", ((UIFltk::UI*)in)->frames);        ((UIFltk::UI*)in)->sbarr->label(str);        ((UIFltk::UI*)in)->frames=0;    }    Fl::repeat_timeout(1.0, cbFPScount);}// Key I/O accessorsu8 UIFltk::UI::keyRdB(u32 a){    switch(a&0xF)    {	case 0: return keys&0xFF;        case 1: return keys>>8;	default: return 0xFF;    }}u16 UIFltk::UI::keyRdH(u32 a){    switch(a&0xE)    {	case 0: return keys;	default: return 0xFFFF;    }}u32 UIFltk::UI::keyRdW(u32 a){    switch(a&0xC)    {	case 0: return keys;	default: return 0xFFFFFFFF;    }}// TODO: Key input handlers are pending interruptsvoid UIFltk::UI::keyWrB(u32 a, u8 d){}void UIFltk::UI::keyWrH(u32 a, u16 d){}void UIFltk::UI::keyWrW(u32 a, u32 d){}/*** EOF: uifltk-ui.cpp **************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -