AndroidでもSDLが不要となったため、QtMultimediaを利用してWindowsとAndroid両方で実行出来るソースコードに書き直して行きます。
qtmain.cpp
/* Skelton for retropc emulator Qt Version : tanam Date : 2013.05.18 - */ #include "emu.h" int main(int argc, char **argv) { // qt init QApplication app(argc, argv); // load config load_config(); // create window EMU* emu; emu=new EMU(); emu->show(); emu->resize(emu->get_window_width(config.window_mode), emu->get_window_height(config.window_mode)); QSize size = emu->size(); emu->x=(size.width() - emu->get_window_width(config.window_mode)) / 2; emu->y=(size.height() - emu->get_window_height(config.window_mode)) /2 ; // main loop return app.exec(); }
qt_input.cpp
/* Skelton for retropc emulator QT Version : tanam Date : 2013.05.18 - */ #include "emu.h" #include "vm/vm.h" #include "fifo.h" #include "fileio.h" #define KEY_KEEP_FRAMES 3 #define COUNTOF(arr) (sizeof(arr) / sizeof((arr)[0])) // QT -> VR Keycode Table std::map<int, int> VKTable; static const struct { int InKey; // QT Keycode int VKey; // VR Keycode } VKeyDef[] = { { Qt::Key_unknown, 0xFF }, { Qt::Key_1, '1' }, // 1 ! { Qt::Key_Exclam, '1' }, // 1 ! { Qt::Key_2, '2' }, // 2 " { Qt::Key_QuoteDbl, '2' }, // 2 " { Qt::Key_3, '3' }, // 3 # { Qt::Key_NumberSign, '3' }, // 3 # { Qt::Key_4, '4' }, // 4 $ { Qt::Key_Dollar, '4' }, // 4 $ { Qt::Key_5, '5' }, // 5 % { Qt::Key_Percent, '5' }, // 5 % { Qt::Key_6, '6' }, // 6 & { Qt::Key_Ampersand, '6' }, // 6 & { Qt::Key_7, '7' }, // 7 ' { Qt::Key_Apostrophe, '7' }, // 7 ' { Qt::Key_8, '8' }, // 8 ( { Qt::Key_ParenLeft, '8' }, // 8 ( { Qt::Key_9, '9' }, // 9 ) { Qt::Key_ParenRight, '9' }, // 9 ) { Qt::Key_0, '0' }, // 0 { Qt::Key_Minus, 0xBD }, // - = { Qt::Key_Equal, 0xBD }, // - = { Qt::Key_AsciiCircum, 0xDE }, // ^ ~ { Qt::Key_AsciiTilde, 0xDE }, // ^ ~ { Qt::Key_Backspace, 0x2E }, // Delete { Qt::Key_Insert, 0x2D }, // Insert { Qt::Key_Escape, 0x1B }, // ESC { Qt::Key_Q, 'Q' }, // q Q { Qt::Key_W, 'W' }, // w W { Qt::Key_E, 'E' }, // e E { Qt::Key_R, 'R' }, // r R { Qt::Key_T, 'T' }, // t T { Qt::Key_Y, 'Y' }, // y Y { Qt::Key_U, 'U' }, // u U { Qt::Key_I, 'I' }, // i I { Qt::Key_O, 'O' }, // o O { Qt::Key_P, 'P' }, // p P { Qt::Key_At, 0xC0 }, // @ ` { Qt::Key_QuoteLeft, 0xC0 }, // @ ` { Qt::Key_BracketLeft, 0xDB }, // [ { { Qt::Key_BraceLeft, 0xDB }, // [ { { Qt::Key_Return, 0x0D }, // CR { Qt::Key_Up, 0x26 }, // ↑ { Qt::Key_Down, 0x28 }, // ↓ { Qt::Key_Left, 0x25 }, // ← { Qt::Key_Right, 0x27 }, // → { Qt::Key_Control, 0x11 }, // L-Ctrl { Qt::Key_A, 'A' }, // a A { Qt::Key_S, 'S' }, // s S { Qt::Key_D, 'D' }, // d D { Qt::Key_F, 'F' }, // f F { Qt::Key_G, 'G' }, // g G { Qt::Key_H, 'H' }, // h H { Qt::Key_J, 'J' }, // j J { Qt::Key_K, 'K' }, // k K { Qt::Key_L, 'L' }, // l L { Qt::Key_Semicolon, 0xBB }, // ; + { Qt::Key_Plus, 0xBB }, // ; + { Qt::Key_Colon, 0xBA }, // : * { Qt::Key_Asterisk, 0xBA }, // : * { Qt::Key_BracketRight,0xDD }, // ] } { Qt::Key_BraceRight, 0xDD }, // ] } { Qt::Key_Shift, 0x10 }, // L-Shift { Qt::Key_Z, 'Z' }, // z Z { Qt::Key_X, 'X' }, // x X { Qt::Key_C, 'C' }, // c C { Qt::Key_V, 'V' }, // v V { Qt::Key_B, 'B' }, // b B { Qt::Key_N, 'N' }, // n N { Qt::Key_M, 'M' }, // m M { Qt::Key_Comma, 0xBC }, // , < { Qt::Key_Less, 0xBC }, // , < { Qt::Key_Period, 0xBE }, // . > { Qt::Key_Greater, 0xBE }, // . > { Qt::Key_Slash, 0xBF }, // / ? { Qt::Key_Question, 0xBF }, // / ? { Qt::Key_End, 0xDC }, // EN { Qt::Key_F1, 0x70 }, // F1 { Qt::Key_F2, 0x71 }, // F2 { Qt::Key_F3, 0x72 }, // F3 { Qt::Key_F4, 0x73 }, // F4 { Qt::Key_F5, 0x74 }, // F5 { Qt::Key_F6, 0x75 }, // KANA { Qt::Key_F7, 0x76 }, // KATA { Qt::Key_F8, 0x77 }, // GRAPH { Qt::Key_F9, 0x78 }, // STOP { Qt::Key_Space, 0x20 }, // Space { Qt::Key_Home, 0x24 }, // Home { Qt::Key_Delete, 0x2E }, // Delete { Qt::Key_PageUp, 0x21 }, // PAGE { Qt::Key_PageDown, 0x22 }, // PAGE { Qt::Key_Tab, 0x09 }, // TAB { Qt::Key_Backslash, 0xE2 }, // RO { Qt::Key_Menu, 0x1B }, // ESCAPE { Qt::Key_Alt, 0x1B }, // ALT { Qt::Key_AudioRewind, 0x77 }, // GRAPH { Qt::Key_Forward, 0x78 }, // STOP { 0, 0x1B }, // MENU }; int OSD_ConvertKeyCode( int scode ) { if(VKTable.count(scode) == 0){ qDebug("keycode %x unknown\n", scode); return 0xff; } return VKTable[scode]; } void EMU::keyPressEvent(QKeyEvent *event) { bool keep_frames = false; int code = OSD_ConvertKeyCode(event->key()); key_status[code] = keep_frames ? KEY_KEEP_FRAMES : 0x80; if (code == 0xFF) ShowPopup(); return; } void EMU::keyReleaseEvent(QKeyEvent *event) { int code = OSD_ConvertKeyCode(event->key()); /// qDebug("r:keycode %x -> %x\n", event->key(), code); bool keep_frames = false; if (key_status[code]) key_status[code] &= 0x7f; return; } void EMU::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) ShowPopup(); return; } void EMU::initialize_input() { // initialize status memset(key_status, 0, sizeof(key_status)); memset(joy_status, 0, sizeof(joy_status)); // initialize keycode convert table for( int i=0; i < COUNTOF(VKeyDef); i++ ) VKTable[VKeyDef[i].InKey] = VKeyDef[i].VKey; }
qt_screen.cpp
/* Skelton for retropc emulator QT Version : tanam Date : 2013.05.18 - */ #include "emu.h" QAction* addCommand(QMenu* menu, QString label, int id, bool checkable = false) { QAction* action = menu->addAction(label); action->setProperty("MenuID", id); action->setCheckable(checkable); return action; } void EMU::ShowPopup() { QSize size = this->size(); QAction* selectedAction = NULL; QMenu menu; menu.setStyleSheet("* {background-color: white; color: black; selection-color: white; selection-background-color: black}"); QMenu* systemMenu = menu.addMenu("Control"); menu.addSeparator(); addCommand(systemMenu, "Reset", ID_RESET); systemMenu->addSeparator(); addCommand(systemMenu, "Exit", ID_EXIT); QMenu* cartMenu1 = menu.addMenu("CART"); addCommand(cartMenu1, "Insert", ID_OPEN_CART1); addCommand(cartMenu1, "Eject", ID_CLOSE_CART1); QMenu* diskMenu1 = menu.addMenu("FD1"); addCommand(diskMenu1, "Insert", ID_OPEN_FD1); addCommand(diskMenu1, "Eject", ID_CLOSE_FD1); QMenu* tapeMenu = menu.addMenu("CMT"); addCommand(tapeMenu, "Play", ID_PLAY_TAPE); addCommand(tapeMenu, "Rec", ID_REC_TAPE); tapeMenu->addSeparator(); addCommand(tapeMenu, "Close", ID_CLOSE_TAPE); QMenu* screenMenu = menu.addMenu("Screen"); addCommand(screenMenu, "Window x1", ID_SCREEN_WINDOW1); addCommand(screenMenu, "Window x2", ID_SCREEN_WINDOW2); addCommand(screenMenu, "Window x3", ID_SCREEN_WINDOW3); addCommand(screenMenu, "Window x4", ID_SCREEN_WINDOW4); selectedAction = menu.exec(QCursor::pos()); QString path=NULL; if (selectedAction != NULL) { int id = selectedAction->property("MenuID").value<int>(); switch (id) { case ID_RESET: reset(); break; case ID_EXIT: exit(0); case ID_OPEN_CART1: path=QFileDialog::getOpenFileName(NULL, "Game Cartridge", "/sdcard/rom/", "*.*"); if (path!=NULL) open_cart(0, (_TCHAR *)path.toStdString().c_str()); break; case ID_SCREEN_WINDOW1: case ID_SCREEN_WINDOW2: case ID_SCREEN_WINDOW3: case ID_SCREEN_WINDOW4: config.window_mode = (id - ID_SCREEN_WINDOW1) + 1; this->resize(get_window_width(config.window_mode), get_window_height(config.window_mode)); size=this->size(); x=(size.width() - get_window_width(config.window_mode)) / 2; y=(size.height() - get_window_height(config.window_mode)) /2 ; break; case ID_OPEN_FD1: path=QFileDialog::getOpenFileName(NULL, "Floppy Disk Image [Insert]", "/sdcard/disk/", "*.*"); open_disk(0, (_TCHAR *)path.toStdString().c_str(),0); break; case ID_CLOSE_FD1: close_disk(0); break; case ID_PLAY_TAPE: path=QFileDialog::getOpenFileName(NULL, "Play Tape Image [Insert]", "/sdcard/tape/", "*.*"); play_tape((_TCHAR *)path.toStdString().c_str()); break; case ID_REC_TAPE: path=QFileDialog::getOpenFileName(NULL, "Rec Tape Image [Insert]", "/sdcard/tape/", "*.*"); rec_tape((_TCHAR *)path.toStdString().c_str()); break; case ID_CLOSE_TAPE: close_tape(); break; } } return; } void EMU::paintEvent(QPaintEvent *) { QPainter painter(this); #if defined(_PC6601) || defined(_PC6001MK2) || defined(_PC6601SR) || defined(_PC6001MK2SR) #if defined(_PC6601SR) || defined(_PC6001MK2SR) QImage img(static_cast<uchar*>(scrbuf), 640, 400, QImage::Format_RGB32); #else QImage img(static_cast<uchar*>(scrbuf), 320, 200, QImage::Format_RGB32); #endif #else QImage img(static_cast<uchar*>(scrbuf), 256, 192, QImage::Format_RGB32); #endif QImage imgscaled=img.scaled(get_window_width(config.window_mode), get_window_height(config.window_mode)); painter.drawPixmap(x, y, QPixmap::fromImage(imgscaled)); return; } void EMU::draw_screen() { vm->draw_screen(); } scrntype* EMU::screen_buffer(int y) { return (scrntype*)(scrbuf) + screen_width * y; } void EMU::initialize_screen() { screen_width = SCREEN_WIDTH; screen_height = SCREEN_HEIGHT; window_width = WINDOW_WIDTH; window_height = WINDOW_HEIGHT; scrbuf=(unsigned char *)malloc(screen_width * screen_height * 4); memset(scrbuf, 0, screen_width * screen_height * 4); } void EMU::release_screen() { free(scrbuf); } int EMU::get_window_width(int mode) { return window_width * mode; } int EMU::get_window_height(int mode) { return window_height * mode; }
qt_sound.cpp
/* Skelton for retropc emulator QT Version : tanam Date : 2013.05.18 - */ #include "emu.h" #include "vm/vm.h" #include "fileio.h" /* sound */ #include <QtCore> #include <QtWidgets> #include <QtMultimedia> #define SOUND_FREQUENCY 48000 #define SOUND_SAMPLES_SIZE 2612 QPointer<QIODevice> audioBuffer = NULL; QPointer<QAudioOutput> audioOutput = NULL; void EMU::initialize_sound() { sound_ok = sound_started = now_mute = false; qRegisterMetaType<QAudio::State>(); QAudioFormat format; format.setCodec("audio/pcm"); format.setChannelCount(2); format.setSampleRate(SOUND_FREQUENCY); format.setSampleSize(16); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); if(audioOutput){ audioOutput->deleteLater(); } QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); if (!info.isFormatSupported(format)) { qWarning()<<"raw audio format not supported by backend, cannot play audio."; format = info.nearestFormat(format); } audioOutput = new QAudioOutput(info, format); audioOutput->moveToThread(qApp->thread()); audioOutput->setParent(qApp); if(audioOutput){ if(audioOutput->state() == QAudio::SuspendedState){ audioOutput->resume(); } else { audioBuffer = audioOutput->start(); sound_ok = sound_started = true; } } } void EMU::release_sound() { if(audioOutput){ audioOutput->stop(); } return; } void EMU::update_sound(int* extra_frames) { *extra_frames = 0; now_mute = false; if(sound_ok) { // sound buffer must be updated uint16* sound_buffer = vm->create_sound(extra_frames); if(audioBuffer){ audioBuffer->write((const char*)sound_buffer, SOUND_SAMPLES_SIZE * 2 * sizeof(short)); } } return; } void EMU::mute_sound() { if(sound_ok) { if (now_mute) { if(audioOutput){ audioOutput->suspend(); } now_mute = false; } else { if(audioOutput){ if(audioOutput->state() == QAudio::SuspendedState){ audioOutput->resume(); } else { audioBuffer = audioOutput->start(); } } } } }