若干ですがAndroid用に書き直すソースコードもあります。
これで武田さんの最新版ソースコードをベースに、Qt5.3.1でAndroid版をビルドすることが可能となります。なお個人的にAndroid端末を利用しなくなったため開発は継続されません。
http://takeda-toshiya.seesaa.net/article/397915031.html
emu.cpp
/* Skelton for retropc emulator QT Version : tanam Date : 2013.05.18 - [ QT emulation i/f ] */ #include "emu.h" // ---------------------------------------------------------------------------- // initialize // ---------------------------------------------------------------------------- EMU::EMU(QWidget *) { // timer event skip_frames=0; m_timer = new QTimer(); connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimer())); m_timer->start(1000/FPS); // load sound config static int freq_table[8] = {2000, 4000, 8000, 11025, 22050, 44100, 48000, 96000}; static double late_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4}; if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) { config.sound_frequency = 6; // default: 48KHz } if(!(0 <= config.sound_latency && config.sound_latency < 5)) { config.sound_latency = 1; // default: 100msec } sound_rate = freq_table[config.sound_frequency]; sound_samples = (int)(sound_rate * late_table[config.sound_latency] + 0.5); // initialize vm = new VM(this); initialize_input(); initialize_screen(); initialize_sound(); initialize_media(); initialize_printer(); vm->initialize_sound(sound_rate, sound_samples); vm->reset(); config.window_mode = 1; } EMU::~EMU() { release_screen(); release_sound(); release_printer(); delete vm; } // ---------------------------------------------------------------------------- // drive machine // ---------------------------------------------------------------------------- int EMU::run() { update_media(); update_printer(); // virtual machine may be driven to fill sound buffer int extra_frames = 0; update_sound(&extra_frames); // drive virtual machine if(extra_frames == 0) { vm->run(); extra_frames = 1; } return extra_frames; } void EMU::reset() { // reset virtual machine vm->reset(); // reset printer reset_printer(); } // ---------------------------------------------------------------------------- // user interface // ---------------------------------------------------------------------------- void EMU::initialize_media() { #ifdef USE_CART1 memset(&cart_status, 0, sizeof(cart_status)); #endif #ifdef USE_FD1 memset(disk_status, 0, sizeof(disk_status)); #endif #ifdef USE_TAPE memset(&tape_status, 0, sizeof(tape_status)); #endif } void EMU::update_media() { #ifdef USE_FD1 for(int drv = 0; drv < 8; drv++) { if(disk_status[drv].wait_count != 0 && --disk_status[drv].wait_count == 0) { vm->open_disk(drv, disk_status[drv].path, disk_status[drv].offset); } } #endif #ifdef USE_TAPE if(tape_status.wait_count != 0 && --tape_status.wait_count == 0) { if(tape_status.play) { vm->play_tape(tape_status.path); } else { vm->rec_tape(tape_status.path); } } #endif } void EMU::restore_media() { #ifdef USE_CART1 if(cart_status.path[0] != _T('\0')) { vm->open_cart(0, cart_status.path); } #endif #ifdef USE_FD1 for(int drv = 0; drv < 8; drv++) { if(disk_status[drv].path[0] != _T('\0')) { vm->open_disk(drv, disk_status[drv].path, disk_status[drv].offset); } } #endif #ifdef USE_TAPE if(tape_status.path[0] != _T('\0')) { if(tape_status.play) { vm->play_tape(tape_status.path); } else { tape_status.path[0] = _T('\0'); } } #endif } #ifdef USE_CART1 void EMU::open_cart(int drv, _TCHAR* file_path) { vm->open_cart(drv, file_path); _tcscpy(cart_status.path, file_path); } void EMU::close_cart(int drv) { vm->close_cart(drv); clear_media_status(&cart_status); } bool EMU::cart_inserted(int drv) { return vm->cart_inserted(drv); } #endif #ifdef USE_FD1 void EMU::open_disk(int drv, _TCHAR* file_path, int offset) { if(vm->disk_inserted(drv)) { vm->close_disk(drv); // wait 0.5sec disk_status[drv].wait_count = (int)(FRAMES_PER_SEC / 2); } else if(disk_status[drv].wait_count == 0) { vm->open_disk(drv, file_path, offset); } _tcscpy(disk_status[drv].path, file_path); disk_status[drv].offset = offset; } void EMU::close_disk(int drv) { vm->close_disk(drv); clear_media_status(&disk_status[drv]); } bool EMU::disk_inserted(int drv) { return vm->disk_inserted(drv); } #endif #ifdef USE_TAPE void EMU::play_tape(_TCHAR* file_path) { if(vm->tape_inserted()) { vm->close_tape(); // wait 0.5sec tape_status.wait_count = (int)(FRAMES_PER_SEC / 2); } else if(tape_status.wait_count == 0) { vm->play_tape(file_path); } _tcscpy(tape_status.path, file_path); tape_status.play = true; } void EMU::rec_tape(_TCHAR* file_path) { if(vm->tape_inserted()) { vm->close_tape(); // wait 0.5sec tape_status.wait_count = (int)(FRAMES_PER_SEC / 2); } else if(tape_status.wait_count == 0) { vm->rec_tape(file_path); } _tcscpy(tape_status.path, file_path); tape_status.play = false; } void EMU::close_tape() { vm->close_tape(); clear_media_status(&tape_status); } bool EMU::tape_inserted() { return vm->tape_inserted(); } #endif void EMU::onTimer() { run(); if (++skip_frames >MAX_SKIP_FRAMES) { draw_screen(); skip_frames=0; } update(); return; } _TCHAR* EMU::bios_path(_TCHAR* file_name) { static _TCHAR file_path[_MAX_PATH]; _stprintf(file_path, _T("/sdcard/rom/%s"), file_name); return file_path; } // ---------------------------------------------------------------------------- // printer // ---------------------------------------------------------------------------- void EMU::initialize_printer() { prn_fio = new FILEIO(); prn_data = -1; prn_strobe = false; } void EMU::release_printer() { delete prn_fio; } void EMU::reset_printer() { prn_fio->Fclose(); prn_data = -1; prn_strobe = false; } void EMU::update_printer() { if(prn_fio->IsOpened() && --prn_wait_frames == 0) { prn_fio->Fclose(); } } void EMU::printer_out(uint8 value) { prn_data = value; } void EMU::printer_strobe(bool value) { bool falling = (prn_strobe && !value); prn_strobe = value; if(falling) { if(!prn_fio->IsOpened()) { if(prn_data == -1) { return; } cur_time_t time; _TCHAR file_name[_MAX_PATH]; /// get_host_time(&time); _stprintf(file_name, _T("prn_%d-%0.2d-%0.2d_%0.2d-%0.2d-%0.2d.txt"), time.year, time.month, time.day, time.hour, time.minute, time.second); prn_fio->Fopen(bios_path(file_name), FILEIO_WRITE_BINARY); } prn_fio->Fputc(prn_data); // wait 10sec #ifdef SUPPORT_VARIABLE_TIMING prn_wait_frames = (int)(vm->frame_rate() * 10.0 + 0.5); #else prn_wait_frames = (int)(FRAMES_PER_SEC * 10.0 + 0.5); #endif } } void EMU::out_debug(const _TCHAR* format, ...) { #ifdef _DEBUG_LOG va_list ap; _TCHAR buffer[1024]; va_start(ap, format); _vstprintf(buffer, format, ap); #ifdef _DEBUG_CONSOLE DWORD dwWritten; WriteConsole(hConsole, buffer, _tcslen(buffer), &dwWritten, NULL); #endif #ifdef _DEBUG_FILE if(debug) { _ftprintf(debug, _T("%s"), buffer); } #endif va_end(ap); #endif } void EMU::out_message(const _TCHAR* format) { qDebug(format); return; }
emu.h
/* Skelton for retropc emulator QT Version : tanam Date : 2013.05.18 - [ QT emulation i/f ] */ #ifndef _EMU_H_ #define _EMU_H_ #include <QApplication> #include <QtCore> #include <QtWidgets> #include <QKeyEvent> #include <QPainter> #include <QTimer> #include <windows.h> #include "common.h" #include "vm/vm.h" #include "res/resource.h" #include "config.h" #include "fileio.h" #ifndef WINDOW_WIDTH #define WINDOW_WIDTH SCREEN_WIDTH #endif #ifndef WINDOW_HEIGHT #define WINDOW_HEIGHT SCREEN_HEIGHT #endif #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) #define __assume exit class EMU : public QWidget { Q_OBJECT protected: VM* vm; void paintEvent(QPaintEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); void mousePressEvent(QMouseEvent *); protected slots: void onTimer(); private: QTimer *m_timer; int skip_frames; void ShowPopup(); // ---------------------------------------- // input // ---------------------------------------- void initialize_input(); void release_input(); void update_input(); uint8 key_status[256]; // windows key code mapping uint32 joy_status[3]; // joystick #1, #2 (b0 = up, b1 = down, b2 = left, b3 = right, b4- = buttons int joy_num; uint32 joy_mask[3]; int mouse_status[3]; // x, y, button (b0 = left, b1 = right) bool mouse_enabled; // ---------------------------------------- // screen // ---------------------------------------- void initialize_screen(); void release_screen(); // screen settings int screen_width, screen_height; int window_width, window_height; // screen buffer unsigned char *scrbuf; // ---------------------------------------- // sound // ---------------------------------------- void initialize_sound(); void release_sound(); void update_sound(int* extra_frames); int sound_rate, sound_samples; bool sound_ok, sound_started, now_mute; // ---------------------------------------- // media // ---------------------------------------- typedef struct { _TCHAR path[_MAX_PATH]; bool play; int offset; int wait_count; } media_status_t; #ifdef USE_CART1 media_status_t cart_status; #endif #ifdef USE_FD1 media_status_t disk_status[8]; #endif #ifdef USE_TAPE media_status_t tape_status; #endif void initialize_media(); void update_media(); void restore_media(); void clear_media_status(media_status_t *status) { status->path[0] = _T('\0'); status->wait_count = 0; } // ---------------------------------------- // printer // ---------------------------------------- void initialize_printer(); void release_printer(); void reset_printer(); void update_printer(); FILEIO *prn_fio; int prn_data, prn_wait_frames; bool prn_strobe; public: // ---------------------------------------- // initialize // ---------------------------------------- EMU(QWidget *parent = 0); ~EMU(); _TCHAR app_path[_MAX_PATH]; _TCHAR* application_path() { return app_path; } _TCHAR* bios_path(_TCHAR* file_name); // drive virtual machine int x; int y; int run(); void reset(); // user interface #ifdef USE_CART1 void open_cart(int drv, _TCHAR* file_path); void close_cart(int drv); bool cart_inserted(int drv); #endif #ifdef USE_FD1 void open_disk(int drv, _TCHAR* file_path, int offset); void close_disk(int drv); bool disk_inserted(int drv); #endif #ifdef USE_TAPE void play_tape(_TCHAR* file_path); void rec_tape(_TCHAR* file_path); void close_tape(); bool tape_inserted(); #endif // screen int get_window_width(int mode); int get_window_height(int mode); void draw_screen(); // sound void mute_sound(); // ---------------------------------------- // for virtual machine // ---------------------------------------- // input device uint8* key_buffer() { return key_status; } uint32* joy_buffer() { return joy_status; } int* mouse_buffer() { return mouse_status; } // screen scrntype* screen_buffer(int y); // printer void printer_out(uint8 value); void printer_strobe(bool value); // debug log void out_debug(const _TCHAR* format, ...); void out_message(const _TCHAR* format); void out_message(const _TCHAR* format, int){out_message(format);}; }; #endif
config.cpp
/* Skelton for retropc emulator Author : Takeda.Toshiya Date : 2006.08.18 - [ config ] */ #include <windows.h> #include <stdlib.h> #include <stdio.h> #include "config.h" config_t config; #ifndef WIN32 BOOL WritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, _TCHAR* String, LPCTSTR lpFileName) { return false; } LPCTSTR GetModuleFileName(LPCTSTR a, LPCTSTR b, int c) { return 0; } LPCTSTR GetPrivateProfileString(LPCTSTR a, LPCTSTR b, LPCTSTR c, LPCTSTR d, int e, LPCTSTR f) { return 0; } int GetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, int Value, LPCTSTR lpFileName) { return -1; } int GetFullPathName(_TCHAR *config_path, int max_path, _TCHAR *app_path, _TCHAR **ptr) { int pt = _tcslen(app_path); while(pt >= 0 && app_path[pt] != _T('\\')) { pt--; } *ptr = &app_path[pt + 1]; } #endif BOOL WritePrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, int Value, LPCTSTR lpFileName) { _TCHAR String[32]; _stprintf(String, _T("%d"), Value); return WritePrivateProfileString(lpAppName, lpKeyName, String, lpFileName); } (省略)
fileio.cpp
/* Skelton for retropc emulator Author : Takeda.Toshiya Date : 2006.08.18 - [ file i/o ] */ #include "fileio.h" #ifndef WIN32 #define FILE_ATTRIBUTE_DIRECTORY -1 #define FILE_ATTRIBUTE_READONLY -1 DWORD GetFileAttributes(_TCHAR *filename) { return -1; } void DeleteFile(_TCHAR *filename) { return; } #endif FILEIO::FILEIO() { fp = NULL; } (省略)
vm/fmgen/file.cpp
// $Id: file.cpp,v 1.6 1999/12/28 11:14:05 cisc Exp $ #include "headers.h" #include "file.h" #ifndef WIN32 #define ERROR_FILE_NOT_FOUND 0 #define ERROR_SHARING_VIOLATION 1 HANDLE CreateFile(const _TCHAR* filename, DWORD access, DWORD share, int a, DWORD creation, int b, int c) { return NULL; } void CloseHandle(HANDLE hfile) { return; } int GetLastError(void) { return 0; } int32 ReadFile(HANDLE hfile, const void *dest, int32 size, DWORD* readsize, int a) { return 0; } int32 WriteFile(HANDLE hfile, const void *dest, int32 size, DWORD* writtensize, int a) { return 0; } int32 SetFilePointer(HANDLE hfile, int32 pos, int a, DWORD wmethod) { return 0; } int32 SetEndOfFile(HANDLE hfile) { return 0; } #endif // --------------------------------------------------------------------------- // 構築/消滅 // --------------------------------------------------------------------------- FileIO::FileIO() { flags = 0; } (省略)