0

here I am again ! So, I am developing an GBC emulator in C++ but I'm having some issues. First of all, I'm using Qt in VS10, which is working nice so far. But well, I have my GUI(main window) with a few Objects (QListWidget, Buttons etc). So, in my CPU class, I have a loop that emulates all the GBC instructions. It works in a simple way. Get code, decode, fetch and call the operation in a switch, do it all over again. So, my problem is, on each interation, I'd like to have this main screen showed up with the List updated.

Image below, I can't post cause I dont have 10 rep points. https://i.stack.imgur.com/BdaHo.png

So, a chunk of code so you can (try?) to understand whats going on: (cpu.cpp)

next:
op = FETCH;
setSelection((UINT32)op);
ciclos = cycles_table[op];

switch(op)
{
       do the magic
       emit onEndProcess((UINT32)op);
       goto next;
}

cpu.h

signals:
void onEndProcess(UINT32);

which is received by ratagbc (ratagbc.h)

public slots:
        void receivedEndProcess(UINT32);

And implemented:

void RataGBC::receivedEndProcess(UINT32 i){
    this->ui.listWidget->item(i+1)->setSelected(true);
    this->show();
 }

And in the rata constructor, after ui.setupUI(...) I have:

cpp = new cpu();
    connect(cpp,SIGNAL(onEndProcess(UINT32)),this,SLOT(receivedEndProcess(UINT32)));

}

Where cpp is an instance of cpu class. Here there is a problem, this connect is returning false !!

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
RataGBC w;
dasm dsm;
FILE *file = fopen("Tetris DX.gbc","r");
int c = 0;
while(dsm.DAsm(file,w.ui.listWidget,c));
fclose(file);
w.cpp->start();
w.show();
return a.exec();
}

One thing that I noticed is that I need to implement (a blank) onEndProcess in my cpu.cpp, or it gives me linking error. Is it really necessary ?

Hope you guys can understand what I need ! Thanks !

Leonardo
  • 3,141
  • 3
  • 31
  • 60

3 Answers3

1

a.exec() starts an event loop, which includes updating the GUI. Put the relevant steps into a function and use Qt's event system to execute the code.

And don't use goto.

Community
  • 1
  • 1
tmpearce
  • 12,523
  • 4
  • 42
  • 60
  • I didn't understand what you mean. Should I pass QApplication as a parameter to cpu ? Which steps ? Thanks ! – Leonardo Feb 29 '12 at 19:44
1

Use QTimer with 0 timeout to perform idle processing.
Make QObject (store your "emulated cpu" within it) with a slot, connect it to timer signal, and in that slot process one step of a program (RagaGBC) at a time. I.e. perform one step of your emulated program. Or a few steps, just not all of them. Start timer to start the emulated program.
Once you're done, call QCoreApplication::exit();.

If you don't understand how to make QObject/use Timers, read Qt tutorials.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
0

You are trying to run two “infinite loops” in the same thread. One is your CPU loop, which obviously blocks. The other is the Qt event loop, which will block until you quit the application.

I might be wrong here, since I never implemented a CPU emulator before, but — although it is possible — I think you should not run the CPU loop in the same thread as the GUI, since the CPU is tight and perhaps sensitive to timing fluctuations.

Instead, you should run the CPU in a separate thread and communicate with the GUI thread using queued slots and other multithreading constructs such as QMutex, QAtomicInt and QAtomicPointer.

The following is how I would implement it (you should obviously adapt it):

GUI Thread

This is where you run QApplication::exec().

  • Construct the main window (with the list and drawing surface)
  • Start the CPU thread
  • Whenever an input event occurs, signal the change to the CPU thread
  • Whenever the CPU thread updates the video buffer, update the drawing surface
  • When the user quits, stop the CPU thread

CPU Thread

Implement a new QThread to do the following.

  • Fetch, decode, execute
  • Read input whenever it is updated
  • Write the video memory and notify the GUI thread to update the drawing surface
  • Quit when told to.

Remember, only the GUI thread can manipulate UI widgets such as lists and menus. The CPU thread should use mechanisms such as queued slots to tell the GUI thread to update the widgets.

Another advice: look at how other people solved the same issue.

andref
  • 4,460
  • 32
  • 45
  • 1
    Why did that post get a -1? While I do not have the knowledge to judge if it is the best possible answer, andref's approach seems at least reasonable to. Thus, maybe someone may help me understand where the bad quality is above... – Thilo Feb 29 '12 at 21:10
  • 1
    @Thilo: Because it is unnecessarily complicated, and overly complicated solution will waste development time which will cost time and money. Remember the KISS principle. Programmer's job is not to provide most sophisticated solution, but the least expensive one. In this case there really is no need for another thread and possible synchronization problems/bugs that will surely follow. Without threads you can implement the whole thing in 20 lines of code or less. – SigTerm Feb 29 '12 at 21:17
  • That's a valid point of view. I qualified my answer, though: running the CPU and GUI in the same thread will subject the CPU to the event-loop timing fluctuations. If accuracy is not an issue, my suggestion is indeed a bit of overkill. That said, multithreaded programming in Qt is quite simple, especially using the constructs provided by the library. – andref Feb 29 '12 at 21:25
  • @andref I tried to do what u suggested, but when I try to connect the signal and slot, it keeps returning false. Gonna edit my code to see how it is. Thanks ! – Leonardo Mar 01 '12 at 01:03
  • Nobody ? Thanks and sorry for bothering ! – Leonardo Mar 02 '12 at 14:54
  • You mean connect returning false? Do the signal and slot signatures match? Did you add Q_OBJECT to the classes? – andref Mar 02 '12 at 20:36
  • @andref I managed to make it work (the connect), but now I face another problem. My receive from connect is like this: void RataGBC::receivedEndProcess(UINT32 i){ this->ui.listWidget->item(i+1)->setSelected(true); this->ui.statusBar->showMessage(QString::number(i)); //this->ui.listWidget_2->addItem(QString::number(cpp->getCpu(),16)); QCoreApplication::processEvents(); }. I can't see it yet. Which functions should I call in my receive ? Any idea ? Thanks – Leonardo Mar 04 '12 at 17:52
  • Is your code publicly accessible, in Github or Bitbucket or somewhere else? I think we have too little context to help you. – andref Mar 05 '12 at 12:51
  • I'm gonna make it available on Github ! Thanks for the tip ! – Leonardo Mar 06 '12 at 19:31
  • @andref here it goes dude. I tried to modify some stuff,as the connect on my main (connecting the thread to cpu) but its not working either. Thanks for the help ! https://github.com/leonardo2204/Rata-GBC – Leonardo Mar 07 '12 at 01:35