2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ win32 emulation i/f ]
14 #define DIRECTSOUND_VERSION 0x900
15 #define DIRECT3D_VERSION 0x900
16 //#define DIRECTINPUT_VERSION 0x500
17 #define DIRECTINPUT_VERSION 0x800
22 // output fdc debug log
23 // #define _FDC_DEBUG_LOG
24 // output i/o debug log
25 // #define _IO_DEBUG_LOG
28 #if defined(_USE_AGAR)
30 # include <agar/core.h>
31 # include <agar/gui.h>
32 # include "simd_types.h"
33 // Wrapper of WIN32->*nix
36 #define _MAX_PATH AG_PATHNAME_MAX
39 #elif defined(_USE_QT)
40 # include <SDL2/SDL.h>
41 //# include "menuclasses.h"
42 //# include "mainwidget.h"
43 //# include "qt_gldraw.h"
44 //# include "emu_utils.h"
45 //# include "qt_main.h"
46 # include "simd_types.h"
47 // Wrapper of WIN32->*nix
51 #define _MAX_PATH MAX_PATH
54 #define _MAX_PATH 2048
76 #if defined(_USE_AGAR)
77 #include "agar_input.h"
78 #elif defined(_USE_QT)
83 #if defined(_USE_AGAR) || defined(_USE_QT)
90 #define WM_RESIZE (WM_USER + 1)
91 #define WM_SOCKET0 (WM_USER + 2)
92 #define WM_SOCKET1 (WM_USER + 3)
93 #define WM_SOCKET2 (WM_USER + 4)
94 #define WM_SOCKET3 (WM_USER + 5)
97 #if defined(USE_LASER_DISC) || defined(USE_VIDEO_CAPTURE)
98 #define USE_DIRECT_SHOW
101 #ifdef USE_VIDEO_CAPTURE
102 #define MAX_CAPTURE_DEVS 8
105 #ifndef SCREEN_WIDTH_ASPECT
106 #define SCREEN_WIDTH_ASPECT SCREEN_WIDTH
108 #ifndef SCREEN_HEIGHT_ASPECT
109 #define SCREEN_HEIGHT_ASPECT SCREEN_HEIGHT
111 #ifndef WINDOW_WIDTH_ASPECT
112 #define WINDOW_WIDTH_ASPECT SCREEN_WIDTH
114 #ifndef WINDOW_HEIGHT_ASPECT
115 #define WINDOW_HEIGHT_ASPECT SCREEN_HEIGHT
118 #define WINDOW_WIDTH SCREEN_WIDTH_ASPECT
120 #ifndef WINDOW_HEIGHT
121 #define WINDOW_HEIGHT SCREEN_HEIGHT_ASPECT
124 #if defined(_USE_AGAR) || defined(_USE_SDL) || defined(_USE_QT)
131 SDL_sem **pSndApplySem;
138 #pragma comment(lib, "d3d9.lib")
139 #pragma comment(lib, "d3dx9.lib")
142 #include <d3d9types.h>
147 //#pragma comment(lib, "dinput.lib")
148 #pragma comment(lib, "dinput8.lib")
149 #pragma comment(lib, "dxguid.lib")
152 #ifdef USE_DIRECT_SHOW
153 #pragma comment(lib, "strmiids.lib")
156 EXTERN_C const CLSID CLSID_SampleGrabber;
157 EXTERN_C const CLSID CLSID_NullRenderer;
158 EXTERN_C const IID IID_ISampleGrabberCB;
159 MIDL_INTERFACE("0579154A-2B53-4994-B0D0-E773148EFF85")
160 ISampleGrabberCB : public IUnknown {
162 virtual HRESULT STDMETHODCALLTYPE SampleCB( double SampleTime,IMediaSample *pSample) = 0;
163 virtual HRESULT STDMETHODCALLTYPE BufferCB( double SampleTime,BYTE *pBuffer,long BufferLen) = 0;
165 EXTERN_C const IID IID_ISampleGrabber;
166 MIDL_INTERFACE("6B652FFF-11FE-4fce-92AD-0266B5D7C78F")
167 ISampleGrabber : public IUnknown {
169 virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot) = 0;
170 virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType) = 0;
171 virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType) = 0;
172 virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem) = 0;
173 virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( /* [out][in] */ long *pBufferSize,/* [out] */ long *pBuffer) = 0;
174 virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( /* [retval][out] */ IMediaSample **ppSample) = 0;
175 virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback,long WhichMethodToCallback) = 0;
180 #ifdef USE_LASER_DISC
181 class CMySampleGrabberCB : public ISampleGrabberCB {
185 CMySampleGrabberCB(VM *vm_ptr)
189 STDMETHODIMP_(ULONG) AddRef()
193 STDMETHODIMP_(ULONG) Release()
197 STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
199 if(riid == IID_ISampleGrabberCB || riid == IID_IUnknown) {
200 *ppv = (void *) static_cast<ISampleGrabberCB*>(this);
203 return E_NOINTERFACE;
205 STDMETHODIMP SampleCB(double SampleTime, IMediaSample *pSample)
209 STDMETHODIMP BufferCB(double dblSampleTime, BYTE *pBuffer, long lBufferSize)
211 vm->movie_sound_callback(pBuffer, lBufferSize);
220 # if defined(_USE_AGAR) || defined(_USE_SDL)
221 # elif defined(_USE_QT)
223 # include <winsock.h>
227 // check memory leaks
229 #define _CRTDBG_MAP_ALLOC
231 #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
232 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
236 #define MAX_D88_BANKS 64
241 #define SOCKET_BUFFER_MAX 0x100000
253 #if defined(_USE_AGAR) || defined(_USE_QT)
254 typedef Uint32 scrntype;
257 PAVISTREAM pAVICompressed;
258 scrntype* lpBmpSource;
259 LPBITMAPINFOHEADER pbmInfoHeader;
273 bool request_terminate;
283 #if defined(_USE_AGAR)
284 SDL_sem *pVMSemaphore; // To be thread safed.
285 #elif defined(_USE_QT)
286 QSemaphore *VMSemaphore;
289 // ----------------------------------------
291 // ----------------------------------------
292 void initialize_input();
293 void release_input();
295 void key_down_sub(int code, bool repeat);
296 void key_up_sub(int code);
298 #if !defined(_USE_AGAR) && !defined(_USE_SDL) && !defined(_USE_QT)
300 LPDIRECTINPUTDEVICE lpdikey;
301 LPDIRECTINPUTDEVICE lpdijoy;
306 uint8 keycode_conv[256];
307 uint8 key_status[256]; // windows key code mapping
308 uint32 modkey_status;
309 uint8 key_dik_prev[256];
310 #ifdef USE_SHIFT_NUMPAD_KEY
311 uint8 key_converted[256];
312 bool key_shift_pressed, key_shift_released;
316 uint32 joy_status[2]; // joystick #1, #2 (b0 = up, b1 = down, b2 = left, b3 = right, b4- = buttons
320 int mouse_status[3]; // x, y, button (b0 = left, b1 = right)
324 FIFO* autokey_buffer;
325 int autokey_phase, autokey_shift;
328 // ----------------------------------------
330 // ----------------------------------------
331 void initialize_screen();
332 void release_screen();
333 #if !defined(_USE_AGAR) && !defined(_USE_SDL) && !defined(_USE_QT)
334 void create_dib_section(HDC hdc, int width, int height, HDC *hdcDib, HBITMAP *hBmp, HBITMAP *hOldBmp, LPBYTE *lpBuf, scrntype **lpBmp, LPBITMAPINFO *lpDib);
337 int screen_width, screen_height;
338 int screen_width_aspect, screen_height_aspect;
339 int window_width, window_height;
340 int display_width, display_height;
341 bool screen_size_changed;
343 #if defined(_USE_AGAR)
345 #elif defined(_USE_QT)
349 scrntype* lpBmpSource;
350 LPBITMAPINFO lpDibSource;
351 LPBITMAPINFOHEADER pbmInfoHeader;
354 int source_width, source_height;
355 int source_width_aspect, source_height_aspect;
356 int stretched_width, stretched_height;
357 int stretch_pow_x, stretch_pow_y;
358 int screen_dest_x, screen_dest_y;
362 bool first_draw_screen;
363 bool first_invalidate;
364 bool self_invalidate;
367 #if defined(_USE_AGAR) || defined(_USE_SDL) || defined(_USE_QT)
369 #ifdef USE_SCREEN_ROTATE
375 bool render_to_SDLFB;
378 bool render_with_OpenCL;
388 _TCHAR video_file_name[_MAX_PATH];
390 _TCHAR video_file_name[AG_PATHNAME_MAX];
393 double rec_video_run_frames;
394 double rec_video_frames;
396 // LPBITMAPINFO lpDibRec;
397 // PAVIFILE pAVIFile;
398 // PAVISTREAM pAVIStream;
399 // PAVISTREAM pAVICompressed;
400 // AVICOMPRESSOPTIONS opts;
401 // DWORD dwAVIFileSize;
405 // HBITMAP hBmpRec, hOldBmpRec;
407 // scrntype* lpBmpRec;
409 bool use_video_thread;
412 AG_Thread hVideoThread;
414 //video_thread_t video_thread_param;
416 // ----------------------------------------
418 // ----------------------------------------
419 void initialize_sound();
420 void release_sound();
421 void update_sound(int* extra_frames);
422 //void AudioCallbackSDL(void *udata, Uint8 *stream, int len);
424 sdl_snddata_t snddata;
425 int sound_rate, sound_samples;
426 bool sound_ok, sound_started, now_mute;
427 SDL_AudioSpec SndSpecReq, SndSpecPresented;
428 //Uint8 iTotalVolume;
434 _TCHAR sound_file_name[_MAX_PATH];
436 _TCHAR sound_file_name[AG_PATHNAME_MAX];
444 HBITMAP hBmp, hOldBmp;
449 #ifdef USE_SCREEN_ROTATE
452 HBITMAP hBmpRotate, hOldBmpRotate;
454 scrntype* lpBmpRotate;
455 LPBITMAPINFO lpDibRotate;
460 HBITMAP hBmpStretch1, hOldBmpStretch1;
461 LPBYTE lpBufStretch1;
462 scrntype* lpBmpStretch1;
463 LPBITMAPINFO lpDibStretch1;
466 HBITMAP hBmpStretch2, hOldBmpStretch2;
467 LPBYTE lpBufStretch2;
468 scrntype* lpBmpStretch2;
469 LPBITMAPINFO lpDibStretch2;
473 LPDIRECT3DDEVICE9 lpd3d9Device;
474 LPDIRECT3DSURFACE9 lpd3d9Surface;
475 LPDIRECT3DSURFACE9 lpd3d9OffscreenSurface;
476 scrntype *lpd3d9Buffer;
477 bool render_to_d3d9Buffer;
481 _TCHAR video_file_name[_MAX_PATH];
483 double rec_video_run_frames;
484 double rec_video_frames;
487 #if defined(_USE_AGAR) || defined(_USE_SDL) || defined(_USE_QT)
489 LPBITMAPINFO lpDibRec;
491 PAVISTREAM pAVIStream;
492 PAVISTREAM pAVICompressed;
493 AVICOMPRESSOPTIONS opts;
498 HBITMAP hBmpRec, hOldBmpRec;
502 bool use_video_thread;
504 video_thread_t video_thread_param;
506 void initialize_sound();
507 void release_sound();
508 void update_sound(int* extra_frames);
510 int sound_rate, sound_samples;
511 bool sound_ok, sound_started, now_mute;
516 // ----------------------------------------
518 // ----------------------------------------
519 #if defined(_USE_AGAR) || defined(_USE_QT)
523 LPDIRECTSOUNDBUFFER lpdsb, lpdsp;
527 _TCHAR sound_file_name[_MAX_PATH];
534 #if defined(_USE_AGAR)
535 // ----------------------------------------
537 // ----------------------------------------
538 void initialize_display_agar();
539 void release_display_agar();
540 #elif defined(_USE_QT)
541 #ifdef USE_LASER_DISC
542 double movie_frame_rate;
543 int movie_sound_rate;
544 bool now_movie_play, now_movie_pause;
547 #ifdef USE_DIRECT_SHOW
548 // ----------------------------------------
550 // ----------------------------------------
551 void initialize_direct_show();
552 void release_direct_show();
553 void create_direct_show_dib_section();
554 void release_direct_show_dib_section();
556 IGraphBuilder *pGraphBuilder;
557 IBaseFilter *pVideoBaseFilter;
558 IBaseFilter *pCaptureBaseFilter;
559 ICaptureGraphBuilder2 *pCaptureGraphBuilder2;
560 ISampleGrabber *pVideoSampleGrabber;
561 IBaseFilter *pSoundBaseFilter;
562 ISampleGrabber *pSoundSampleGrabber;
563 #ifdef USE_LASER_DISC
564 CMySampleGrabberCB *pSoundCallBack;
566 IMediaControl *pMediaControl;
567 IMediaSeeking *pMediaSeeking;
568 IMediaPosition *pMediaPosition;
569 IVideoWindow *pVideoWindow;
570 IBasicVideo *pBasicVideo;
571 IBasicAudio *pBasicAudio;
572 bool bTimeFormatFrame;
573 bool bVerticalReversed;
576 HBITMAP hBmpDShow, hOldBmpDShow;
578 scrntype* lpBmpDShow;
579 LPBITMAPINFO lpDibDShow;
581 int direct_show_width, direct_show_height;
582 bool direct_show_mute[2];
583 #ifdef USE_LASER_DISC
584 double movie_frame_rate;
585 int movie_sound_rate;
586 bool now_movie_play, now_movie_pause;
588 #ifdef USE_VIDEO_CAPTURE
589 void enum_capture_devs();
590 bool connect_capture_dev(int index, bool pin);
591 int cur_capture_dev_index;
592 int num_capture_devs;
593 _TCHAR capture_dev_name[MAX_CAPTURE_DEVS][256];
598 // ----------------------------------------
600 // ----------------------------------------
602 _TCHAR path[_MAX_PATH];
609 media_status_t cart_status[MAX_CART];
612 media_status_t disk_status[MAX_FD];
615 media_status_t quickdisk_status[MAX_QD];
618 media_status_t tape_status;
620 #ifdef USE_LASER_DISC
621 media_status_t laser_disc_status;
624 void initialize_media();
626 void restore_media();
628 void clear_media_status(media_status_t *status)
630 status->path[0] = _T('\0');
631 status->wait_count = 0;
634 // ----------------------------------------
636 // ----------------------------------------
637 void initialize_printer();
638 void release_printer();
639 void reset_printer();
640 void update_printer();
641 void open_printer_file();
642 void close_printer_file();
644 _TCHAR prn_file_name[_MAX_PATH];
646 _TCHAR prn_file_name[_MAX_PATH];
649 int prn_data, prn_wait_frames;
653 // ----------------------------------------
655 // ----------------------------------------
656 void initialize_socket();
657 void release_socket();
658 void update_socket();
661 bool is_tcp[SOCKET_MAX];
662 #if !defined(_USE_QT)
663 struct sockaddr_in udpaddr[SOCKET_MAX];
665 int socket_delay[SOCKET_MAX];
666 char recv_buffer[SOCKET_MAX][SOCKET_BUFFER_MAX];
667 int recv_r_ptr[SOCKET_MAX], recv_w_ptr[SOCKET_MAX];
671 // ----------------------------------------
673 // ----------------------------------------
674 void initialize_debugger();
675 void release_debugger();
676 #if defined(_USE_AGAR)
677 AG_Thread hDebuggerThread;
678 #elif defined(_USE_QT)
679 CSP_Debugger *hDebugger;
680 QThread *hDebuggerThread;
682 HANDLE hDebuggerThread;
684 debugger_thread_t debugger_thread_param;
688 // ----------------------------------------
690 // ----------------------------------------
691 void initialize_debug_log();
692 void release_debug_log();
697 // ----------------------------------------
699 // ----------------------------------------
700 void save_state_tmp(_TCHAR* file_path);
701 bool load_state_tmp(_TCHAR* file_path);
704 // ----------------------------------------
706 // ----------------------------------------
710 #ifdef USE_SOUND_DEVICE_TYPE
711 int sound_device_type;
713 _TCHAR app_path[_MAX_PATH];
717 bool bDrawLine[SCREEN_HEIGHT];
718 uint32 *getJoyStatPtr(void) {
722 // ----------------------------------------
724 // ----------------------------------------
725 #if defined(_USE_AGAR)
726 EMU(AG_Window *hwnd, AG_Widget *hinst);
727 #elif defined(_USE_QT)
728 EMU(class Ui_MainWindow*, GLDrawClass*);
730 EMU(HWND hwnd, HINSTANCE hinst);
734 _TCHAR* application_path()
738 _TCHAR* bios_path(_TCHAR* file_name);
739 #if defined(_USE_AGAR)
740 // To be thread safety.
742 if(pVMSemaphore) SDL_SemWait(pVMSemaphore);
744 void UnlockVM(void) {
745 if(pVMSemaphore) SDL_SemPost(pVMSemaphore);
747 #elif defined(_USE_QT)
749 VMSemaphore->acquire();
751 void UnlockVM(void) {
752 VMSemaphore->release();
757 void UnlockVM(void) {
761 QImage *getPseudoVramClass(void) { return pPseudoVram;}
763 // ----------------------------------------
765 // ----------------------------------------
766 #if defined(_USE_AGAR)
767 AG_Window *main_window_handle;
768 AG_Widget *instance_handle;
771 #elif defined(_USE_QT)
772 class Ui_MainWindow *main_window_handle;
773 GLDrawClass *instance_handle;
777 HWND main_window_handle;
778 HINSTANCE instance_handle;
781 // drive virtual machine
782 int frame_interval();
785 #ifdef USE_SPECIAL_RESET
786 void special_reset();
789 void notify_power_off();
796 _TCHAR path[_MAX_PATH];
798 // _TCHAR name[128]; // Convert to UTF8
800 // } bank[MAX_D88_BANKS];
801 _TCHAR disk_name[MAX_D88_BANKS][128]; // Convert to UTF8
806 int get_access_lamp(void);
810 void open_cart(int drv, _TCHAR* file_path);
811 void close_cart(int drv);
812 bool cart_inserted(int drv);
815 void open_disk(int drv, _TCHAR* file_path, int bank);
816 void close_disk(int drv);
817 bool disk_inserted(int drv);
818 bool is_write_protected_fd(int drv);
819 void write_protect_fd(int drv, bool flag);
822 void open_quickdisk(int drv, _TCHAR* file_path);
823 void close_quickdisk(int drv);
824 bool quickdisk_inserted(int drv);
827 void play_tape(_TCHAR* file_path);
828 void rec_tape(_TCHAR* file_path);
830 bool tape_inserted();
833 return vm->get_tape_ptr();
837 #ifdef USE_TAPE_BUTTON
840 void push_fast_forward();
841 void push_fast_rewind();
842 void push_apss_forward();
843 void push_apss_rewind();
844 bool get_tape_play(void)
846 return vm->get_tape_play();
849 #ifdef USE_LASER_DISC
850 void open_laser_disc(_TCHAR* file_path);
851 void close_laser_disc();
852 bool laser_disc_inserted();
854 #ifdef USE_BINARY_FILE1
855 void load_binary(int drv, _TCHAR* file_path);
856 void save_binary(int drv, _TCHAR* file_path);
860 void start_rec_sound();
861 void stop_rec_sound();
862 void restart_rec_sound();
865 void capture_screen();
866 bool start_rec_video(int fps);
867 void stop_rec_video();
868 void restart_rec_video();
871 void update_config();
880 void key_mod(uint32 mod) {
884 void key_down(int code, bool repeat);
885 void key_up(int code);
886 void key_lost_focus()
890 uint32 recent_key_sym;
891 uint32 recent_key_mod;
892 uint32 recent_key_unicode;
894 void press_button(int num);
898 void disenable_mouse();
900 bool get_mouse_enabled()
902 return mouse_enabled;
906 void start_auto_key();
907 void stop_auto_key();
910 return (autokey_phase != 0);
915 int get_window_width(int mode);
916 int get_window_height(int mode);
917 void set_display_size(int width, int height, bool window_mode);
919 #if defined(_USE_AGAR)
920 void update_screen(AG_Widget *target);
921 #elif defined(_USE_QT)
922 void update_screen(GLDrawClass *glv);
924 void update_screen(HDC hdc);
929 first_invalidate = true;
936 #ifdef USE_VIDEO_CAPTURE
938 int get_cur_capture_dev_index()
940 return cur_capture_dev_index;
942 int get_num_capture_devs()
944 return num_capture_devs;
946 _TCHAR* get_capture_dev_name(int index)
948 return capture_dev_name[index];
950 void open_capture_dev(int index, bool pin);
951 void close_capture_dev();
952 void show_capture_dev_filter();
953 void show_capture_dev_pin();
954 void show_capture_dev_source();
959 int get_socket(int ch)
963 void socket_connected(int ch);
964 void socket_disconnected(int ch);
965 void send_data(int ch);
966 void recv_data(int ch);
971 void open_debugger(int cpu_index);
972 void close_debugger();
973 bool debugger_enabled(int cpu_index);
977 // ----------------------------------------
978 // for virtual machine
979 // ----------------------------------------
984 #if defined(_USE_AGAR)
986 #elif defined(_USE_QT)
989 PostMessage(main_window_handle, WM_CLOSE, 0, 0L);
1004 return mouse_status;
1008 void change_screen_size(int sw, int sh, int swa, int sha, int ww, int wh);
1009 int get_screen_width_aspect(void) {return screen_width_aspect;}
1010 int get_screen_height_aspect(void) {return screen_height_aspect;}
1011 scrntype* screen_buffer(int y);
1012 #ifdef USE_CRT_FILTER
1013 bool screen_skip_line;
1017 void get_host_time(cur_time_t* time);
1020 void printer_out(uint8 value);
1021 void printer_strobe(bool value);
1023 #ifdef USE_DIRECT_SHOW
1025 void get_direct_show_buffer();
1026 void mute_direct_show_dev(bool l, bool r);
1028 #ifdef USE_LASER_DISC
1029 bool open_movie_file(_TCHAR* file_path);
1030 void close_movie_file();
1036 double get_movie_frame_rate()
1038 return movie_frame_rate;
1040 int get_movie_sound_rate()
1042 return movie_sound_rate;
1044 void set_cur_movie_frame(int frame, bool relative);
1045 uint32 get_cur_movie_frame();
1047 #ifdef USE_VIDEO_CAPTURE
1048 void set_capture_dev_channel(int ch);
1054 bool init_socket_tcp(int ch);
1055 bool init_socket_udp(int ch);
1056 bool connect_socket(int ch, uint32 ipaddr, int port);
1057 void disconnect_socket(int ch);
1058 bool listen_socket(int ch);
1059 void send_data_tcp(int ch);
1060 void send_data_udp(int ch, uint32 ipaddr, int port);
1064 void out_debug_log(const _TCHAR* format, ...);
1066 void out_message(const _TCHAR* format, ...);
1068 _TCHAR message[_MAX_PATH];