OSDN Git Service

[VM][General][Qt] Merge Upstream 2015-12-10.
[csp-qt/common_source_project-fm7.git] / source / src / qt / common / emu_thread.cpp
1 /*
2         Skelton for retropc emulator
3         Author : Takeda.Toshiya
4     Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2015.11.10
6         History: 2015.11.10 Split from qt_main.cpp
7
8         [ win32 main ] -> [ Qt main ] -> [Emu Thread]
9 */
10
11 #include <QString>
12 #include <QTextCodec>
13 #include <QWaitCondition>
14
15 #include <SDL.h>
16
17 #include "emu_thread.h"
18
19 #include "qt_gldraw.h"
20 #include "agar_logger.h"
21
22 // buttons
23 #ifdef MAX_BUTTONS
24 #define MAX_FONT_SIZE 32
25 #endif
26 #define MAX_SKIP_FRAMES 10
27
28 EmuThreadClass::EmuThreadClass(META_MainWindow *rootWindow, EMU *pp_emu, QObject *parent) : QThread(parent) {
29         MainWindow = rootWindow;
30         p_emu = pp_emu;
31         bRunThread = true;
32         prev_skip = false;
33         update_fps_time = SDL_GetTicks();
34         next_time = update_fps_time;
35         total_frames = 0;
36         draw_frames = 0;
37         skip_frames = 0;
38         calc_message = true;
39         mouse_flag = false;
40         p_emu->set_parent_handler(this);
41         drawCond = new QWaitCondition();
42 #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
43         tape_play_flag = false;
44         tape_rec_flag = false;
45         tape_pos = 0;
46 #endif  
47 };
48
49 EmuThreadClass::~EmuThreadClass() {
50         delete drawCond;
51 };
52
53
54 int EmuThreadClass::get_interval(void)
55 {
56         static int accum = 0;
57         accum += p_emu->frame_interval();
58         int interval = accum >> 10;
59         accum -= interval << 10;
60         return interval;
61 }
62
63 void EmuThreadClass::doExit(void)
64 {
65         int status;
66         bRunThread = false;
67 }
68
69 void EmuThreadClass::moved_mouse(int x, int y)
70 {
71         p_emu->setMousePointer(x, y);
72 }
73
74 void EmuThreadClass::button_pressed_mouse(Qt::MouseButton button)
75 {
76         int stat = p_emu->getMouseButton();
77         bool flag = p_emu->get_mouse_enabled();
78         switch(button) {
79         case Qt::LeftButton:
80                 stat |= 0x01;
81                 break;
82         case Qt::RightButton:
83                 stat |= 0x02;
84                 break;
85         case Qt::MiddleButton:
86                 flag = !flag;
87                 emit sig_mouse_enable(flag);
88                 break;
89         }
90         p_emu->setMouseButton(stat);
91 }
92
93 void EmuThreadClass::button_released_mouse(Qt::MouseButton button)
94 {
95         int stat = p_emu->getMouseButton();
96         switch(button) {
97         case Qt::LeftButton:
98                 stat &= 0x7ffffffe;
99                 break;
100         case Qt::RightButton:
101                 stat &= 0x7ffffffd;
102                 break;
103         case Qt::MiddleButton:
104           //emit sig_mouse_enable(false);
105                 break;
106         }
107         p_emu->setMouseButton(stat);
108 }
109
110
111 void EmuThreadClass::set_tape_play(bool flag)
112 {
113 #ifdef USE_TAPE_BUTTON
114         tape_play_flag = flag;
115 #endif
116 }
117
118 EmuThreadClass *EmuThreadClass::currentHandler()
119 {
120         return this;
121 }
122
123 void EmuThreadClass::resize_screen(int screen_width, int screen_height, int stretched_width, int stretched_height)
124 {
125         //emit sig_resize_uibar(stretched_width, stretched_height);
126         emit sig_resize_screen(screen_width, screen_height);
127 }
128
129 void EmuThreadClass::do_start_auto_key(QString ctext)
130 {
131 #ifdef USE_AUTO_KEY
132         QTextCodec *codec = QTextCodec::codecForName("Shift-Jis");
133         QByteArray array;
134         clipBoardText = ctext;
135         if(clipBoardText.size() > 0) {
136                 array = codec->fromUnicode(clipBoardText.toUtf8());
137                 //p_emu->set_auto_key_string((const char *)array.constData());
138                 emit sig_auto_key_string(array);
139                 //AGAR_DebugLog(AGAR_LOG_DEBUG, "AutoKey: SET :%s\n", clipBoardText.toUtf8().constData());
140                 p_emu->start_auto_key();
141         }
142         //clipBoardText.clear();
143 #endif  
144 }
145
146 void EmuThreadClass::do_stop_auto_key(void)
147 {
148 #ifdef USE_AUTO_KEY
149         AGAR_DebugLog(AGAR_LOG_DEBUG, "AutoKey: stop\n");
150         p_emu->stop_auto_key();
151 #endif  
152 }
153
154 #if defined(USE_FD1) || defined(USE_FD2) || defined(USE_FD3) || defined(USE_FD4) || \
155     defined(USE_FD5) || defined(USE_FD6) || defined(USE_FD7) || defined(USE_FD8)
156 void EmuThreadClass::do_write_protect_disk(int drv, bool flag)
157 {
158         p_emu->set_disk_protected(drv, flag);
159 }
160
161 void EmuThreadClass::do_close_disk(int drv)
162 {
163         p_emu->close_disk(drv);
164         p_emu->d88_file[drv].bank_num = 0;
165         p_emu->d88_file[drv].cur_bank = -1;
166 }
167
168 void EmuThreadClass::do_open_disk(int drv, QString path, int bank)
169 {
170    
171         QByteArray localPath = path.toLocal8Bit();
172    
173         p_emu->d88_file[drv].bank_num = 0;
174         p_emu->d88_file[drv].cur_bank = -1;
175         
176         if(check_file_extension(localPath.constData(), ".d88") || check_file_extension(localPath.constData(), ".d77")) {
177                 
178                 FILEIO *fio = new FILEIO();
179                 if(fio->Fopen(localPath.constData(), FILEIO_READ_BINARY)) {
180                         try {
181                                 fio->Fseek(0, FILEIO_SEEK_END);
182                                 int file_size = fio->Ftell(), file_offset = 0;
183                                 while(file_offset + 0x2b0 <= file_size && p_emu->d88_file[drv].bank_num < MAX_D88_BANKS) {
184                                         fio->Fseek(file_offset, FILEIO_SEEK_SET);
185                                         char tmp[18];
186                                         memset(tmp, 0x00, sizeof(tmp));
187                                         fio->Fread(tmp, 17, 1);
188                                         memset(p_emu->d88_file[drv].disk_name[p_emu->d88_file[drv].bank_num], 0x00, 128);
189                                         if(strlen(tmp) > 0) Convert_CP932_to_UTF8(p_emu->d88_file[drv].disk_name[p_emu->d88_file[drv].bank_num], tmp, 127, 17);
190                                         
191                                         fio->Fseek(file_offset + 0x1c, FILEIO_SEEK_SET);
192                                         file_offset += fio->FgetUint32_LE();
193                                         p_emu->d88_file[drv].bank_num++;
194                                 }
195                                 strcpy(p_emu->d88_file[drv].path, path.toUtf8().constData());
196                                 if(bank >= p_emu->d88_file[drv].bank_num) bank = p_emu->d88_file[drv].bank_num - 1;
197                                 if(bank < 0) bank = 0;
198                                 p_emu->d88_file[drv].cur_bank = bank;
199                         }
200                         catch(...) {
201                                 bank = 0;
202                                 p_emu->d88_file[drv].bank_num = 0;
203                         }
204                         fio->Fclose();
205                 }
206                 delete fio;
207         } else {
208            bank = 0;
209         }
210         p_emu->open_disk(drv, localPath.constData(), bank);
211         emit sig_update_recent_disk(drv);
212 }
213
214 #endif
215
216 #ifdef USE_TAPE
217 void EmuThreadClass::do_play_tape(QString name)
218 {
219         p_emu->play_tape(name.toLocal8Bit().constData());
220 }
221
222 void EmuThreadClass::do_rec_tape(QString name)
223 {
224         p_emu->rec_tape(name.toLocal8Bit().constData());
225 }
226
227 void EmuThreadClass::do_close_tape(void)
228 {
229         p_emu->close_tape();
230 }
231
232 # ifdef USE_TAPE_BUTTON
233 void EmuThreadClass::do_cmt_push_play(void)
234 {
235         p_emu->push_play();
236 }
237
238 void EmuThreadClass::do_cmt_push_stop(void)
239 {
240         p_emu->push_stop();
241 }
242
243 void EmuThreadClass::do_cmt_push_fast_forward(void)
244 {
245         p_emu->push_fast_forward();
246 }
247
248 void EmuThreadClass::do_cmt_push_fast_rewind(void)
249 {
250         p_emu->push_fast_rewind();
251 }
252
253 void EmuThreadClass::do_cmt_push_apss_forward(void)
254 {
255         p_emu->push_apss_forward();
256 }
257
258 void EmuThreadClass::do_cmt_push_apss_rewind(void)
259 {
260         p_emu->push_apss_rewind();
261 }
262
263 # endif
264 #endif
265
266 #ifdef USE_QD1
267 void EmuThreadClass::do_write_protect_quickdisk(int drv, bool flag)
268 {
269         //p_emu->write_protect_Qd(drv, flag);
270 }
271
272 void EmuThreadClass::do_close_quickdisk(int drv)
273 {
274         p_emu->close_quickdisk(drv);
275 }
276
277 void EmuThreadClass::do_open_quickdisk(int drv, QString path)
278 {
279         p_emu->open_quickdisk(drv, path.toLocal8Bit().constData());
280 }
281 #endif
282
283 #ifdef USE_CART1
284 void EmuThreadClass::do_close_cart(int drv)
285 {
286         p_emu->close_cart(drv);
287 }
288
289 void EmuThreadClass::do_open_cart(int drv, QString path)
290 {
291         p_emu->open_cart(drv, path.toLocal8Bit().constData());
292 }
293 #endif
294
295 #ifdef USE_LASER_DISK
296 void EmuThreadClass::do_close_laser_disk(void)
297 {
298         p_emu->close_laser_disk();
299 }
300
301 void EmuThreadClass::do_open_laser_disk(QString path)
302 {
303         p_emu->open_laser_disk(path.toLocal8Bit().constData());
304 }
305 #endif
306 #ifdef USE_BINARY_FILE1
307 void EmuThreadClass::do_load_binary(int drv, QString path)
308 {
309         p_emu->load_binary(drv, path.toLocal8Bit().constData());
310 }
311
312 void EmuThreadClass::do_save_binary(int drv, QString path)
313 {
314         p_emu->save_binary(drv, path.toLocal8Bit().constData());
315 }
316 #endif
317
318 void EmuThreadClass::print_framerate(int frames)
319 {
320         if(frames >= 0) draw_frames += frames;
321         if(calc_message) {
322                 uint32_t current_time = SDL_GetTicks();
323                         if(update_fps_time <= current_time && update_fps_time != 0) {
324                                 _TCHAR buf[256];
325                                 QString message;
326                                 int ratio = (int)(100.0 * (double)draw_frames / (double)total_frames + 0.5);
327
328 #ifdef USE_POWER_OFF
329                                 if(MainWindow->GetPowerState() == false){        
330                                         snprintf(buf, 255, _T("*Power OFF*"));
331                                 } else {
332 #endif // USE_POWER_OFF         
333                                         if(p_emu->message_count > 0) {
334                                                 snprintf(buf, 255, _T("%s - %s"), DEVICE_NAME, p_emu->message);
335                                                 p_emu->message_count--;
336                                         } else {
337                                                 snprintf(buf, 255, _T("%s - %d fps (%d %%)"), DEVICE_NAME, draw_frames, ratio);
338                                         }
339 #ifdef USE_POWER_OFF
340                                 } 
341 #endif // USE_POWER_OFF  
342               
343                                 message = buf;
344                                 emit message_changed(message);
345                                 update_fps_time += 1000;
346                                 total_frames = draw_frames = 0;
347                                 
348                         }
349                         if(update_fps_time <= current_time) {
350                                 update_fps_time = current_time + 1000;
351                         }
352                         calc_message = false;  
353                 } else {
354                         calc_message = true;
355                 }
356 }
357
358 void EmuThreadClass::do_draw_timing(bool f)
359 {
360         draw_timing = f;
361 }
362
363 void EmuThreadClass::sample_access_drv(void)
364 {
365         uint32 access_drv;
366         QString alamp;
367         QString tmpstr;
368         QString iname;
369         int i;
370 #if defined(USE_QD1)
371 # if defined(USE_ACCESS_LAMP)      
372         access_drv = p_emu->get_access_lamp();
373 # endif
374         for(i = 0; i < MAX_QD ; i++) {
375                 if(p_emu->quickdisk_inserted(i)) {
376                 //           printf("%d\n", access_drv);
377 # if defined(USE_ACCESS_LAMP)      
378                         if(i == (access_drv - 1)) {
379                                 alamp = QString::fromUtf8("● ");
380                         } else {
381                                 alamp = QString::fromUtf8("○ ");
382                         }
383                         tmpstr = QString::fromUtf8("QD");
384                         tmpstr = alamp + tmpstr + QString::number(i) + QString::fromUtf8(":");
385 # else
386                         tmpstr = QString::fromUtf8("QD");
387                         tmpstr = tmpstr + QString::number(i) + QString::fromUtf8(":");
388 # endif
389                         iname = QString::fromUtf8("*Inserted*");
390                         tmpstr = tmpstr + iname;
391                 } else {
392                         tmpstr = QString::fromUtf8("× QD") + QString::number(i) + QString::fromUtf8(":");
393                         tmpstr = tmpstr + QString::fromUtf8(" ");
394                 }
395                 if(tmpstr != qd_text[i]) {
396                         emit sig_change_osd_qd(i, tmpstr);
397                         qd_text[i] = tmpstr;
398                 }
399         }
400 #endif
401
402 #if defined(USE_FD1)
403 # if defined(USE_ACCESS_LAMP)      
404         access_drv = p_emu->get_access_lamp();
405 # endif
406         for(i = 0; i < MAX_FD; i++) {
407                 if(p_emu->disk_inserted(i)) {
408 # if defined(USE_ACCESS_LAMP)      
409                         if(i == (access_drv - 1)) {
410                                 alamp = QString::fromUtf8("<FONT COLOR=RED>●</FONT> ");
411                         } else {
412                                 alamp = QString::fromUtf8("○ ");
413                         }
414                         tmpstr = QString::fromUtf8("FD");
415                         tmpstr = alamp + tmpstr + QString::number(i) + QString::fromUtf8(":");
416 # else
417                         tmpstr = QString::fromUtf8("FD");
418                         tmpstr = tmpstr + QString::number(i) + QString::fromUtf8(":");
419 # endif
420                         if(emu->d88_file[i].bank_num > 0) {
421                                 iname = QString::fromUtf8(emu->d88_file[i].disk_name[emu->d88_file[i].cur_bank]);
422                         } else {
423                                 iname = QString::fromUtf8("*Inserted*");
424                         }
425                         tmpstr = tmpstr + iname;
426                 } else {
427                         tmpstr = QString::fromUtf8("× FD") + QString::number(i) + QString::fromUtf8(":");
428                         tmpstr = tmpstr + QString::fromUtf8(" ");
429                 }
430
431                 if(tmpstr != fd_text[i]) {
432                         emit sig_change_osd_fd(i, tmpstr);
433                         fd_text[i] = tmpstr;
434                 }
435         }
436 #endif
437 #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
438         if(p_emu->tape_inserted()) {
439                 int tape_counter = p_emu->tape_position();
440                 tmpstr = QString::fromUtf8("");
441                 if(p_emu->tape_playing()) {
442                         tmpstr = QString::fromUtf8("<FONT COLOR=BLUE>▶ </FONT>");
443                 } else if(p_emu->tape_recording()) {
444                         tmpstr = QString::fromUtf8("<FONT COLOR=RED>● </FONT>");
445                 } else {
446                         tmpstr = QString::fromUtf8("<FONT COLOR=BLACK>■ </FONT>");
447                 }
448                 if(tape_counter >= 100) {
449                         tmpstr = tmpstr + QString::fromUtf8("BOTTOM");
450                 } else if(tape_counter >= 0) {
451                         tmpstr = tmpstr + QString::number(tape_counter) + QString::fromUtf8("%");
452                 } else {
453                         tmpstr = tmpstr + QString::fromUtf8("TOP");
454                 }
455         } else {
456                 tmpstr = QString::fromUtf8("EMPTY");
457         }
458         if(tmpstr != cmt_text) {
459                 emit sig_change_osd_cmt(tmpstr);
460                 cmt_text = tmpstr;
461         }
462 #endif
463
464 }
465
466 void EmuThreadClass::doWork(const QString &params)
467 {
468         int interval = 0, sleep_period = 0;
469         int run_frames;
470         bool now_skip;
471         uint32 current_time;
472         bool first = true;
473 #ifdef SUPPORT_DUMMY_DEVICE_LED
474         uint32 led_data = 0x00000000;
475         uint32 led_data_old = 0x00000000;
476 #endif
477 #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
478         bool tape_flag;
479         int tpos;
480 #endif
481 #ifdef USE_DIG_RESOLUTION
482         int width, height;
483 #endif
484         QString ctext;
485         bool req_draw = true;
486         bool vert_line_bak = config.opengl_scanline_vert;
487         bool horiz_line_bak = config.opengl_scanline_horiz;
488         bool gl_crt_filter_bak = config.use_opengl_filters;
489         int opengl_filter_num_bak = config.opengl_filter_num;
490         int no_draw_count = 0;
491         
492         ctext.clear();
493         draw_timing = false;
494         bResetReq = false;
495         bSpecialResetReq = false;
496         bLoadStateReq = false;
497         bSaveStateReq = false;
498         bUpdateConfigReq = false;
499         bStartRecordSoundReq = false;
500         bStopRecordSoundReq = false;
501         
502         next_time = SDL_GetTicks();
503         mouse_flag = false;
504         p_emu->SetHostCpus(this->idealThreadCount());
505         
506 #if defined(USE_QD1)
507         for(int i = 0; i < 2; i++) qd_text[i].clear();
508 #endif
509 #if defined(USE_QD1)
510         for(int i = 0; i < MAX_FD; i++) fd_text[i].clear();
511 #endif
512 #if defined(USE_TAPE)
513         cmt_text.clear();
514 #endif
515         do {
516                 //p_emu->SetHostCpus(this->idealThreadCount());
517                 if(MainWindow == NULL) {
518                         if(bRunThread == false){
519                                 goto _exit;
520                         }
521                         msleep(10);
522                         continue;
523                 }
524                 if(first) {
525 #ifdef SUPPORT_DUMMY_DEVICE_LED
526                         emit sig_send_data_led((quint32)led_data);
527 #endif
528                         first = false;
529                 }
530                 interval = 0;
531                 sleep_period = 0;
532                 if(p_emu) {
533                         // drive machine
534 #ifdef USE_DIG_RESOLUTION
535                         //p_emu->get_screen_resolution(&width, &height);
536                         //emit sig_set_grid_vertical(width, false);
537                         //emit sig_set_grid_horizonal(height, false);
538 #endif
539 #ifdef USE_STATE
540                         if(bLoadStateReq != false) {
541                                 p_emu->load_state();
542                                 bLoadStateReq = false;
543                                 req_draw = true;
544                         }
545 #endif                  
546                         if(bResetReq != false) {
547                                 p_emu->reset();
548                                 bResetReq = false;
549                                 req_draw = true;
550                         }
551 #ifdef USE_SPECIAL_RESET
552                         if(bSpecialResetReq != false) {
553                                 p_emu->special_reset();
554                                 bSpecialResetReq = false;
555                         }
556 #endif
557 #ifdef USE_STATE
558                         if(bSaveStateReq != false) {
559                                 p_emu->save_state();
560                                 bSaveStateReq = false;
561                         }
562 #endif
563 #if defined(USE_MINIMUM_RENDERING)
564                         if((vert_line_bak != config.opengl_scanline_vert) ||
565                            (horiz_line_bak != config.opengl_scanline_horiz) ||
566                            (gl_crt_filter_bak != config.use_opengl_filters) ||
567                            (opengl_filter_num_bak != config.opengl_filter_num)) req_draw = true;
568                         vert_line_bak = config.opengl_scanline_vert;
569                         horiz_line_bak = config.opengl_scanline_horiz;
570                         gl_crt_filter_bak = config.use_opengl_filters;
571                         opengl_filter_num_bak = config.opengl_filter_num;
572 #endif
573                         if(bStartRecordSoundReq != false) {
574                                 p_emu->start_rec_sound();
575                                 bStartRecordSoundReq = false;
576                                 req_draw = true;
577                         }
578                         if(bStopRecordSoundReq != false) {
579                                 p_emu->stop_rec_sound();
580                                 bStopRecordSoundReq = false;
581                                 req_draw = true;
582                         }
583                         if(bUpdateConfigReq != false) {
584                                 p_emu->update_config();
585                                 bUpdateConfigReq = false;
586                                 req_draw = true;
587                         }
588                         run_frames = p_emu->run();
589                         total_frames += run_frames;
590 #if defined(USE_MINIMUM_RENDERING)
591                         req_draw |= p_emu->screen_changed();
592 #else
593                         req_draw = true;
594 #endif                  
595 #ifdef SUPPORT_DUMMY_DEVICE_LED
596                         led_data = p_emu->get_led_status();
597                         if(led_data != led_data_old) {
598                                 emit sig_send_data_led((quint32)led_data);
599                                 led_data_old = led_data;
600                         }
601 #endif
602                         sample_access_drv();
603
604                         interval += get_interval();
605                         now_skip = p_emu->now_skip() && !p_emu->now_rec_video();
606                         //p_emu->UnlockVM();
607
608                         if((prev_skip && !now_skip) || next_time == 0) {
609                                 next_time = SDL_GetTicks();
610                         }
611                         if(!now_skip) {
612                                 next_time += interval;
613                         }
614                         prev_skip = now_skip;
615                         //printf("p_emu::RUN Frames = %d SKIP=%d Interval = %d NextTime = %d\n", run_frames, now_skip, interval, next_time);
616       
617                         if(next_time > SDL_GetTicks()) {
618                                 //  update window if enough time
619                                 draw_timing = false;
620                                 if(!req_draw) {
621                                         no_draw_count++;
622                                         if(no_draw_count > (int)(FRAMES_PER_SEC / 4)) {
623                                                 req_draw = true;
624                                                 no_draw_count = 0;
625                                         }
626                                 } else {
627                                         no_draw_count = 0;
628                                 }
629                                 emit sig_draw_thread(req_draw);
630                                 skip_frames = 0;
631                         
632                                 // sleep 1 frame priod if need
633                                 current_time = SDL_GetTicks();
634                                 if((int)(next_time - current_time) >= 10) {
635                                         sleep_period = next_time - current_time;
636                                 }
637                         } else if(++skip_frames > MAX_SKIP_FRAMES) {
638                                 // update window at least once per 10 frames
639                                 draw_timing = false;
640                                 emit sig_draw_thread(true);
641                                 no_draw_count = 0;
642                                 skip_frames = 0;
643                                 uint32_t tt = SDL_GetTicks();
644                                 next_time = tt + get_interval();
645                                 sleep_period = next_time - tt;
646                         }
647                 }
648                 req_draw = false;
649                 if(bRunThread == false){
650                         goto _exit;
651                 }
652                 if(sleep_period <= 0) sleep_period = 1; 
653                 msleep(sleep_period);
654         } while(1);
655 _exit:
656         //emit quit_draw_thread();
657         AGAR_DebugLog(AGAR_LOG_DEBUG, "EmuThread : EXIT");
658         emit sig_finished();
659         this->quit();
660 }
661
662 void EmuThreadClass::doSetDisplaySize(int w, int h, int ww, int wh)
663 {
664         p_emu->suspend();
665         //p_emu->set_vm_screen_size(w, h, -1, -1, ww, wh);
666         p_emu->set_window_size(w, h, true);
667 }
668
669 void EmuThreadClass::doUpdateConfig()
670 {
671         bUpdateConfigReq = true;
672 }
673
674 void EmuThreadClass::doStartRecordSound()
675 {
676         bStartRecordSoundReq = true;
677 }
678
679 void EmuThreadClass::doStopRecordSound()
680 {
681         bStopRecordSoundReq = true;
682 }
683
684 void EmuThreadClass::doReset()
685 {
686         bResetReq = true;
687 }
688
689 void EmuThreadClass::doSpecialReset()
690 {
691         bSpecialResetReq = true;
692 }
693
694 void EmuThreadClass::doLoadState()
695 {
696         bLoadStateReq = true;
697 }
698
699 void EmuThreadClass::doSaveState()
700 {
701         bSaveStateReq = true;
702 }
703