Last active
August 20, 2026 05:34
-
-
Save umjammer/7454bbdedd9af1c9d458bf978bdecddc to your computer and use it in GitHub Desktop.
[pc-100] dedicated makefile & patch for macos w/ sdl2 for common source code project for 2025-11-09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/.gitignore b/.gitignore | |
| new file mode 100644 | |
| index 0000000..21efb0c | |
| --- /dev/null | |
| +++ b/.gitignore | |
| @@ -0,0 +1,5 @@ | |
| +*.rom | |
| +*.ROM | |
| +tmp/ | |
| +pc100 | |
| +pc100.ini | |
| diff --git a/Makefile b/Makefile | |
| new file mode 100644 | |
| index 0000000..8ab7d53 | |
| --- /dev/null | |
| +++ b/Makefile | |
| @@ -0,0 +1,67 @@ | |
| +# Makefile for PC-100 (ePC-100) using SDL2 OSD | |
| + | |
| +CXX ?= clang++ | |
| +TARGET ?= pc100 | |
| + | |
| +SDL_CFLAGS := $(shell pkg-config --cflags sdl2) | |
| +SDL_LIBS := $(shell pkg-config --libs sdl2) | |
| + | |
| +CXXFLAGS ?= -O2 -Wall | |
| +CXXFLAGS += -I src -I src/vm -I src/sdl \ | |
| + -D_PC100 -D_USE_SDL \ | |
| + -Wno-deprecated-declarations -Wno-comment \ | |
| + -Wno-deprecated-register -Wno-non-c-typedef-for-linkage \ | |
| + $(SDL_CFLAGS) | |
| + | |
| +LDFLAGS ?= | |
| +LIBS := $(SDL_LIBS) -lpthread -lz -lm | |
| + | |
| +SRCS = \ | |
| + src/common.cpp \ | |
| + src/config.cpp \ | |
| + src/debugger.cpp \ | |
| + src/emu.cpp \ | |
| + src/fifo.cpp \ | |
| + src/fileio.cpp \ | |
| + src/vm/and.cpp \ | |
| + src/vm/beep.cpp \ | |
| + src/vm/disk.cpp \ | |
| + src/vm/event.cpp \ | |
| + src/vm/i386_dasm.cpp \ | |
| + src/vm/i8251.cpp \ | |
| + src/vm/i8255.cpp \ | |
| + src/vm/i8259.cpp \ | |
| + src/vm/i86.cpp \ | |
| + src/vm/io.cpp \ | |
| + src/vm/memory.cpp \ | |
| + src/vm/msm58321.cpp \ | |
| + src/vm/noise.cpp \ | |
| + src/vm/pcm1bit.cpp \ | |
| + src/vm/upd765a.cpp \ | |
| + src/vm/pc100/crtc.cpp \ | |
| + src/vm/pc100/ioctrl.cpp \ | |
| + src/vm/pc100/kanji.cpp \ | |
| + src/vm/pc100/pc100.cpp \ | |
| + src/sdl/osd.cpp \ | |
| + src/sdl/osd_screen.cpp \ | |
| + src/sdl/osd_sound.cpp \ | |
| + src/sdl/osd_input.cpp \ | |
| + src/sdl/osd_console.cpp \ | |
| + src/sdl/main.cpp | |
| + | |
| +OBJDIR = obj | |
| +OBJS = $(patsubst src/%.cpp, $(OBJDIR)/%.o, $(SRCS)) | |
| + | |
| +all: $(TARGET) | |
| + | |
| +$(TARGET): $(OBJS) | |
| + $(CXX) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ | |
| + | |
| +$(OBJDIR)/%.o: src/%.cpp | |
| + @mkdir -p $(dir $@) | |
| + $(CXX) $(CXXFLAGS) -c $< -o $@ | |
| + | |
| +clean: | |
| + rm -rf $(OBJDIR) $(TARGET) | |
| + | |
| +.PHONY: all clean | |
| diff --git a/src/common.cpp b/src/common.cpp | |
| index e665e5c..ccbb08c 100644 | |
| --- a/src/common.cpp | |
| +++ b/src/common.cpp | |
| @@ -29,6 +29,13 @@ | |
| #pragma comment(lib, "shlwapi.lib") | |
| #else | |
| #include <time.h> | |
| + #include <unistd.h> | |
| + #include <sys/types.h> | |
| + #include <sys/stat.h> | |
| + #include <string> | |
| + #include <algorithm> | |
| + #include <cctype> | |
| + #include <wchar.h> | |
| #endif | |
| #include <math.h> | |
| #include "common.h" | |
| @@ -291,6 +298,36 @@ unsigned int DLL_PREFIX min(unsigned int a, unsigned int b) | |
| return b; | |
| } | |
| } | |
| + | |
| +size_t DLL_PREFIX max(size_t a, size_t b) | |
| +{ | |
| + return (a > b) ? a : b; | |
| +} | |
| + | |
| +size_t DLL_PREFIX max(size_t a, unsigned int b) | |
| +{ | |
| + return (a > (size_t)b) ? a : (size_t)b; | |
| +} | |
| + | |
| +size_t DLL_PREFIX max(unsigned int a, size_t b) | |
| +{ | |
| + return ((size_t)a > b) ? (size_t)a : b; | |
| +} | |
| + | |
| +size_t DLL_PREFIX min(size_t a, size_t b) | |
| +{ | |
| + return (a < b) ? a : b; | |
| +} | |
| + | |
| +size_t DLL_PREFIX min(size_t a, unsigned int b) | |
| +{ | |
| + return (a < (size_t)b) ? a : (size_t)b; | |
| +} | |
| + | |
| +size_t DLL_PREFIX min(unsigned int a, size_t b) | |
| +{ | |
| + return ((size_t)a < b) ? (size_t)a : b; | |
| +} | |
| #endif | |
| #ifndef SUPPORT_SECURE_FUNCTIONS | |
| @@ -356,7 +393,11 @@ int DLL_PREFIX my_swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t | |
| { | |
| va_list ap; | |
| va_start(ap, format); | |
| +#ifdef _WIN32 | |
| int result = vswprintf(buffer, format, ap); | |
| +#else | |
| + int result = vswprintf(buffer, sizeOfBuffer, format, ap); | |
| +#endif | |
| va_end(ap); | |
| return result; | |
| } | |
| @@ -1017,7 +1058,7 @@ const _TCHAR *DLL_PREFIX get_application_path() | |
| } else { | |
| my_tcscpy_s(app_path, _MAX_PATH, _T(".\\")); | |
| } | |
| -#else | |
| +#elif defined(_USE_QT) | |
| #if defined(Q_OS_WIN) | |
| std::string delim = "\\"; | |
| #else | |
| @@ -1029,6 +1070,8 @@ const _TCHAR *DLL_PREFIX get_application_path() | |
| std::string cpath = csppath + my_procname + delim; | |
| _my_mkdir(cpath); | |
| strncpy(app_path, cpath.c_str(), _MAX_PATH - 1); | |
| +#else | |
| + my_tcscpy_s(app_path, _MAX_PATH, _T("./")); | |
| #endif | |
| initialized = true; | |
| } | |
| diff --git a/src/common.h b/src/common.h | |
| index f41edca..5da8b73 100644 | |
| --- a/src/common.h | |
| +++ b/src/common.h | |
| @@ -109,7 +109,11 @@ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| +#ifdef _WIN32 | |
| #include <io.h> | |
| +#else | |
| +#include <unistd.h> | |
| +#endif | |
| #include <math.h> | |
| #ifdef _MSC_VER | |
| #if _MSC_VER < 1920 | |
| @@ -270,6 +274,15 @@ | |
| #ifndef UINT | |
| typedef unsigned int UINT; | |
| #endif | |
| + #ifndef LONG_PTR | |
| + typedef intptr_t LONG_PTR; | |
| + #endif | |
| + #ifndef ULONG_PTR | |
| + typedef uintptr_t ULONG_PTR; | |
| + #endif | |
| + #ifndef DWORD_PTR | |
| + typedef uintptr_t DWORD_PTR; | |
| + #endif | |
| #endif | |
| typedef union pair16_u { | |
| @@ -796,10 +809,16 @@ int16_t DLL_PREFIX ExchangeEndianS16(uint16_t x); | |
| unsigned int DLL_PREFIX max(int a, unsigned int b); | |
| unsigned int DLL_PREFIX max(unsigned int a, int b); | |
| unsigned int DLL_PREFIX max(unsigned int a, unsigned int b); | |
| + size_t DLL_PREFIX max(size_t a, size_t b); | |
| + size_t DLL_PREFIX max(size_t a, unsigned int b); | |
| + size_t DLL_PREFIX max(unsigned int a, size_t b); | |
| int DLL_PREFIX min(int a, int b); | |
| int DLL_PREFIX min(unsigned int a, int b); | |
| int DLL_PREFIX min(int a, unsigned int b); | |
| unsigned int DLL_PREFIX min(unsigned int a, unsigned int b); | |
| + size_t DLL_PREFIX min(size_t a, size_t b); | |
| + size_t DLL_PREFIX min(size_t a, unsigned int b); | |
| + size_t DLL_PREFIX min(unsigned int a, size_t b); | |
| #endif | |
| // string | |
| @@ -813,7 +832,7 @@ int16_t DLL_PREFIX ExchangeEndianS16(uint16_t x); | |
| #define _fgetts fgets | |
| #endif | |
| #ifndef _ftprintf | |
| - #define _ftprintf printf | |
| + #define _ftprintf fprintf | |
| #endif | |
| #ifndef _tfopen | |
| #define _tfopen fopen | |
| @@ -866,9 +885,18 @@ int16_t DLL_PREFIX ExchangeEndianS16(uint16_t x); | |
| #ifndef _stprintf | |
| #define _stprintf sprintf | |
| #endif | |
| + #ifndef _sntprintf | |
| + #define _sntprintf snprintf | |
| + #endif | |
| + #ifndef _snprintf | |
| + #define _snprintf snprintf | |
| + #endif | |
| #ifndef _vstprintf | |
| #define _vstprintf vsprintf | |
| #endif | |
| + #ifndef _vsntprintf | |
| + #define _vsntprintf vsnprintf | |
| + #endif | |
| #ifndef _taccess | |
| #define _taccess access | |
| #endif | |
| diff --git a/src/emu.h b/src/emu.h | |
| index e534083..4499da4 100644 | |
| --- a/src/emu.h | |
| +++ b/src/emu.h | |
| @@ -399,6 +399,8 @@ public: | |
| #if defined(OSD_QT) | |
| pthread_t debugger_thread_id; | |
| CSP_Debugger *hDebugger; | |
| +#elif defined(OSD_SDL) | |
| + pthread_t debugger_thread_id; | |
| #elif defined(OSD_WIN32) | |
| HANDLE hDebuggerThread; | |
| #else | |
| diff --git a/src/fifo.cpp b/src/fifo.cpp | |
| index d0c7aad..addf629 100644 | |
| --- a/src/fifo.cpp | |
| +++ b/src/fifo.cpp | |
| @@ -8,7 +8,9 @@ | |
| */ | |
| #include <stdlib.h> | |
| +#if defined(_WIN32) | |
| #include <malloc.h> | |
| +#endif | |
| #include "fifo.h" | |
| #include "fileio.h" | |
| diff --git a/src/fileio.cpp b/src/fileio.cpp | |
| index 13a5e0a..642648b 100644 | |
| --- a/src/fileio.cpp | |
| +++ b/src/fileio.cpp | |
| @@ -14,12 +14,10 @@ | |
| #include <iostream> | |
| #include <fstream> | |
| #include <cstdio> | |
| - #if defined(_USE_QT) | |
| - #include <sys/types.h> | |
| - #include <sys/stat.h> | |
| - #if !defined(Q_OS_WIN) | |
| - #include <unistd.h> | |
| - #endif | |
| + #include <sys/types.h> | |
| + #include <sys/stat.h> | |
| + #if !defined(Q_OS_WIN) && !defined(_WIN32) | |
| + #include <unistd.h> | |
| #endif | |
| #elif defined(_WIN32) | |
| #include <windows.h> | |
| diff --git a/src/sdl/main.cpp b/src/sdl/main.cpp | |
| new file mode 100644 | |
| index 0000000..0b986c4 | |
| --- /dev/null | |
| +++ b/src/sdl/main.cpp | |
| @@ -0,0 +1,144 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2006.08.18 - | |
| + | |
| + [ SDL2 main ] | |
| +*/ | |
| + | |
| +#include <stdio.h> | |
| +#include <stdlib.h> | |
| +#include <string.h> | |
| +#include <SDL.h> | |
| + | |
| +#include "../emu.h" | |
| +#include "../config.h" | |
| + | |
| +EMU* emu = NULL; | |
| + | |
| +int main(int argc, char *argv[]) | |
| +{ | |
| + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) { | |
| + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); | |
| + return 1; | |
| + } | |
| + | |
| + // load config | |
| + load_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME))); | |
| + | |
| + // parse command line options | |
| + int disk_drv = 0; | |
| + for (int i = 1; i < argc; ++i) { | |
| + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { | |
| + printf("Usage: %s [options] [disk_image1] [disk_image2]\n", argv[0]); | |
| + printf("Options:\n"); | |
| + printf(" -vertical, -v Set vertical monitor mode (512x720)\n"); | |
| + printf(" -horizontal, -horiz Set horizontal monitor mode (720x512)\n"); | |
| + printf(" -fdd0 <file> Insert floppy disk into Drive 0\n"); | |
| + printf(" -fdd1 <file> Insert floppy disk into Drive 1\n"); | |
| + printf(" -fullspeed Run at unthrottled maximum speed\n"); | |
| + printf(" -h, --help Show this help message\n"); | |
| + return 0; | |
| + } else if (strcmp(argv[i], "-vertical") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-vmon") == 0) { | |
| + config.monitor_type = 1; | |
| + } else if (strcmp(argv[i], "-horizontal") == 0 || strcmp(argv[i], "-horiz") == 0 || strcmp(argv[i], "-hmon") == 0) { | |
| + config.monitor_type = 0; | |
| + } else if (strcmp(argv[i], "-fullspeed") == 0) { | |
| + config.full_speed = true; | |
| + } | |
| + } | |
| + | |
| + emu = new EMU(); | |
| + | |
| +#ifdef USE_FLOPPY_DISK | |
| + // parse command line for disk images | |
| + for (int i = 1; i < argc; ++i) { | |
| + if (strcmp(argv[i], "-fdd0") == 0 && i + 1 < argc) { | |
| + emu->open_floppy_disk(0, argv[++i], 0); | |
| + } else if (strcmp(argv[i], "-fdd1") == 0 && i + 1 < argc) { | |
| + emu->open_floppy_disk(1, argv[++i], 0); | |
| + } else if (argv[i][0] != '-') { | |
| + if (disk_drv < USE_FLOPPY_DISK) { | |
| + emu->open_floppy_disk(disk_drv++, argv[i], 0); | |
| + } | |
| + } | |
| + } | |
| +#endif | |
| + | |
| + int total_frames = 0, draw_frames = 0, skip_frames = 0; | |
| + Uint32 next_time = 0; | |
| + bool prev_skip = false; | |
| + Uint32 update_fps_time = 0; | |
| + | |
| + while (!emu->get_osd()->app_quit) { | |
| + int run_frames = emu->run(); | |
| + total_frames += run_frames; | |
| + | |
| + if (emu->get_osd()->app_quit) { | |
| + break; | |
| + } | |
| + | |
| + int sleep_period = 0; | |
| + bool now_skip = (config.full_speed || emu->is_frame_skippable()) && | |
| + !emu->is_video_recording() && !emu->is_sound_recording(); | |
| + | |
| + Uint32 current_time = SDL_GetTicks(); | |
| + if ((prev_skip && !now_skip) || next_time == 0) { | |
| + next_time = current_time; | |
| + } | |
| + if (!now_skip) { | |
| + static int accum = 0; | |
| + accum += emu->get_frame_interval(); | |
| + int interval = accum >> 10; | |
| + accum -= interval << 10; | |
| + next_time += interval; | |
| + } | |
| + prev_skip = now_skip; | |
| + | |
| + current_time = SDL_GetTicks(); | |
| + if (next_time > current_time) { | |
| + draw_frames += emu->draw_screen(); | |
| + skip_frames = 0; | |
| + if ((int)(next_time - current_time) >= 1) { | |
| + sleep_period = next_time - current_time; | |
| + } | |
| + } else if (++skip_frames > (int)emu->get_frame_rate()) { | |
| + draw_frames += emu->draw_screen(); | |
| + skip_frames = 0; | |
| + next_time = SDL_GetTicks(); | |
| + } | |
| + | |
| + if (sleep_period > 0) { | |
| + SDL_Delay(sleep_period); | |
| + } | |
| + | |
| + current_time = SDL_GetTicks(); | |
| + if (update_fps_time <= current_time) { | |
| + if (update_fps_time != 0 && emu->get_osd()->sdl_window != NULL) { | |
| + char title[256]; | |
| + if (emu->message_count > 0) { | |
| + snprintf(title, sizeof(title), "%s - %s", DEVICE_NAME, emu->message); | |
| + emu->message_count--; | |
| + } else if (now_skip) { | |
| + int ratio = (int)(100.0 * (double)total_frames / emu->get_frame_rate() + 0.5); | |
| + snprintf(title, sizeof(title), "%s - Skip Frames (%d %%)", DEVICE_NAME, ratio); | |
| + } else { | |
| + int ratio = total_frames > 0 ? (int)(100.0 * (double)draw_frames / (double)total_frames + 0.5) : 0; | |
| + snprintf(title, sizeof(title), "%s - %d fps (%d %%)", DEVICE_NAME, draw_frames, ratio); | |
| + } | |
| + SDL_SetWindowTitle(emu->get_osd()->sdl_window, title); | |
| + total_frames = draw_frames = 0; | |
| + } | |
| + update_fps_time = current_time + 1000; | |
| + } | |
| + } | |
| + | |
| + save_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME))); | |
| + | |
| + delete emu; | |
| + emu = NULL; | |
| + | |
| + SDL_Quit(); | |
| + return 0; | |
| +} | |
| diff --git a/src/sdl/osd.cpp b/src/sdl/osd.cpp | |
| new file mode 100644 | |
| index 0000000..ac33b23 | |
| --- /dev/null | |
| +++ b/src/sdl/osd.cpp | |
| @@ -0,0 +1,107 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.20- | |
| + | |
| + [ SDL2 dependent ] | |
| +*/ | |
| + | |
| +#include "osd.h" | |
| + | |
| +OSD::OSD() | |
| +{ | |
| + lock_count = 0; | |
| + app_quit = false; | |
| + vm = NULL; | |
| + sdl_window = NULL; | |
| + sdl_renderer = NULL; | |
| + sdl_texture = NULL; | |
| + audio_device_id = 0; | |
| + draw_screen_buffer = NULL; | |
| + now_record_video = false; | |
| + now_record_sound = false; | |
| + rec_sound_fio = NULL; | |
| + sound_available = false; | |
| + sound_started = false; | |
| + sound_muted = false; | |
| + lost_focus = false; | |
| +#ifdef USE_SCREEN_FILTER | |
| + screen_skip_line = false; | |
| +#endif | |
| +#ifdef USE_AUTO_KEY | |
| + now_auto_key = false; | |
| +#endif | |
| +} | |
| + | |
| +OSD::~OSD() | |
| +{ | |
| +} | |
| + | |
| +void OSD::initialize(int rate, int samples) | |
| +{ | |
| + app_quit = false; | |
| + initialize_console(); | |
| + initialize_input(); | |
| + initialize_screen(); | |
| + initialize_sound(rate, samples); | |
| +} | |
| + | |
| +void OSD::release() | |
| +{ | |
| + release_console(); | |
| + release_input(); | |
| + release_screen(); | |
| + release_sound(); | |
| +} | |
| + | |
| +void OSD::power_off() | |
| +{ | |
| + app_quit = true; | |
| +} | |
| + | |
| +void OSD::suspend() | |
| +{ | |
| + mute_sound(); | |
| +} | |
| + | |
| +void OSD::restore() | |
| +{ | |
| +} | |
| + | |
| +void OSD::lock_vm() | |
| +{ | |
| + lock_count++; | |
| +} | |
| + | |
| +void OSD::unlock_vm() | |
| +{ | |
| + if(--lock_count <= 0) { | |
| + force_unlock_vm(); | |
| + } | |
| +} | |
| + | |
| +void OSD::force_unlock_vm() | |
| +{ | |
| + lock_count = 0; | |
| +} | |
| + | |
| +void OSD::sleep(uint32_t ms) | |
| +{ | |
| + SDL_Delay(ms); | |
| +} | |
| + | |
| +#ifdef USE_DEBUGGER | |
| +void OSD::start_waiting_in_debugger() | |
| +{ | |
| +} | |
| + | |
| +void OSD::finish_waiting_in_debugger() | |
| +{ | |
| +} | |
| + | |
| +void OSD::process_waiting_in_debugger() | |
| +{ | |
| + update_input(); | |
| +} | |
| +#endif | |
| diff --git a/src/sdl/osd.h b/src/sdl/osd.h | |
| new file mode 100644 | |
| index 0000000..d194e99 | |
| --- /dev/null | |
| +++ b/src/sdl/osd.h | |
| @@ -0,0 +1,434 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.20- | |
| + | |
| + [ SDL2 dependent ] | |
| +*/ | |
| + | |
| +#ifndef _SDL_OSD_H_ | |
| +#define _SDL_OSD_H_ | |
| + | |
| +#include <stdio.h> | |
| +#include <stdlib.h> | |
| +#include <string.h> | |
| +#include <stdint.h> | |
| +#include <stdbool.h> | |
| +#include <math.h> | |
| +#include <unistd.h> | |
| +#include <time.h> | |
| +#include <SDL.h> | |
| + | |
| +#include "../common.h" | |
| +#include "../config.h" | |
| +#include "../vm/vm.h" | |
| +#include "../vm/vm_template.h" | |
| + | |
| +#define SCREEN_FILTER_NONE 0 | |
| +#define SCREEN_FILTER_RGB 1 | |
| +#define SCREEN_FILTER_RF 2 | |
| + | |
| +#define OSD_CONSOLE_BLUE 1 | |
| +#define OSD_CONSOLE_GREEN 2 | |
| +#define OSD_CONSOLE_RED 4 | |
| +#define OSD_CONSOLE_INTENSITY 8 | |
| + | |
| +#ifndef VK_BACK | |
| +#define VK_LBUTTON 0x01 | |
| +#define VK_RBUTTON 0x02 | |
| +#define VK_CANCEL 0x03 | |
| +#define VK_MBUTTON 0x04 | |
| +#define VK_BACK 0x08 | |
| +#define VK_TAB 0x09 | |
| +#define VK_CLEAR 0x0C | |
| +#define VK_RETURN 0x0D | |
| +#define VK_SHIFT 0x10 | |
| +#define VK_CONTROL 0x11 | |
| +#define VK_MENU 0x12 | |
| +#define VK_PAUSE 0x13 | |
| +#define VK_CAPITAL 0x14 | |
| +#define VK_KANA 0x15 | |
| +#define VK_KANJI 0x19 | |
| +#define VK_ESCAPE 0x1B | |
| +#define VK_CONVERT 0x1C | |
| +#define VK_NONCONVERT 0x1D | |
| +#define VK_ACCEPT 0x1E | |
| +#define VK_MODECHANGE 0x1F | |
| +#define VK_SPACE 0x20 | |
| +#define VK_PRIOR 0x21 | |
| +#define VK_NEXT 0x22 | |
| +#define VK_END 0x23 | |
| +#define VK_HOME 0x24 | |
| +#define VK_LEFT 0x25 | |
| +#define VK_UP 0x26 | |
| +#define VK_RIGHT 0x27 | |
| +#define VK_DOWN 0x28 | |
| +#define VK_SELECT 0x29 | |
| +#define VK_PRINT 0x2A | |
| +#define VK_EXECUTE 0x2B | |
| +#define VK_SNAPSHOT 0x2C | |
| +#define VK_INSERT 0x2D | |
| +#define VK_DELETE 0x2E | |
| +#define VK_HELP 0x2F | |
| +#define VK_0 0x30 | |
| +#define VK_1 0x31 | |
| +#define VK_2 0x32 | |
| +#define VK_3 0x33 | |
| +#define VK_4 0x34 | |
| +#define VK_5 0x35 | |
| +#define VK_6 0x36 | |
| +#define VK_7 0x37 | |
| +#define VK_8 0x38 | |
| +#define VK_9 0x39 | |
| +#define VK_A 0x41 | |
| +#define VK_B 0x42 | |
| +#define VK_C 0x43 | |
| +#define VK_D 0x44 | |
| +#define VK_E 0x45 | |
| +#define VK_F 0x46 | |
| +#define VK_G 0x47 | |
| +#define VK_H 0x48 | |
| +#define VK_I 0x49 | |
| +#define VK_J 0x4A | |
| +#define VK_K 0x4B | |
| +#define VK_L 0x4C | |
| +#define VK_M 0x4D | |
| +#define VK_N 0x4E | |
| +#define VK_O 0x4F | |
| +#define VK_P 0x50 | |
| +#define VK_Q 0x51 | |
| +#define VK_R 0x52 | |
| +#define VK_S 0x53 | |
| +#define VK_T 0x54 | |
| +#define VK_U 0x55 | |
| +#define VK_V 0x56 | |
| +#define VK_W 0x57 | |
| +#define VK_X 0x58 | |
| +#define VK_Y 0x59 | |
| +#define VK_Z 0x5A | |
| +#define VK_LWIN 0x5B | |
| +#define VK_RWIN 0x5C | |
| +#define VK_APPS 0x5D | |
| +#define VK_SLEEP 0x5F | |
| +#define VK_NUMPAD0 0x60 | |
| +#define VK_NUMPAD1 0x61 | |
| +#define VK_NUMPAD2 0x62 | |
| +#define VK_NUMPAD3 0x63 | |
| +#define VK_NUMPAD4 0x64 | |
| +#define VK_NUMPAD5 0x65 | |
| +#define VK_NUMPAD6 0x66 | |
| +#define VK_NUMPAD7 0x67 | |
| +#define VK_NUMPAD8 0x68 | |
| +#define VK_NUMPAD9 0x69 | |
| +#define VK_MULTIPLY 0x6A | |
| +#define VK_ADD 0x6B | |
| +#define VK_SEPARATOR 0x6C | |
| +#define VK_SUBTRACT 0x6D | |
| +#define VK_DECIMAL 0x6E | |
| +#define VK_DIVIDE 0x6F | |
| +#define VK_F1 0x70 | |
| +#define VK_F2 0x71 | |
| +#define VK_F3 0x72 | |
| +#define VK_F4 0x73 | |
| +#define VK_F5 0x74 | |
| +#define VK_F6 0x75 | |
| +#define VK_F7 0x76 | |
| +#define VK_F8 0x77 | |
| +#define VK_F9 0x78 | |
| +#define VK_F10 0x79 | |
| +#define VK_F11 0x7A | |
| +#define VK_F12 0x7B | |
| +#define VK_NUMLOCK 0x90 | |
| +#define VK_SCROLL 0x91 | |
| +#define VK_LSHIFT 0xA0 | |
| +#define VK_RSHIFT 0xA1 | |
| +#define VK_LCONTROL 0xA2 | |
| +#define VK_RCONTROL 0xA3 | |
| +#define VK_LMENU 0xA4 | |
| +#define VK_RMENU 0xA5 | |
| +#define VK_OEM_1 0xBA | |
| +#define VK_OEM_PLUS 0xBB | |
| +#define VK_OEM_COMMA 0xBC | |
| +#define VK_OEM_MINUS 0xBD | |
| +#define VK_OEM_PERIOD 0xBE | |
| +#define VK_OEM_2 0xBF | |
| +#define VK_OEM_3 0xC0 | |
| +#define VK_OEM_4 0xDB | |
| +#define VK_OEM_5 0xDC | |
| +#define VK_OEM_6 0xDD | |
| +#define VK_OEM_7 0xDE | |
| +#define VK_OEM_8 0xDF | |
| +#define VK_OEM_102 0xE2 | |
| +#endif | |
| + | |
| +typedef struct bitmap_s { | |
| + inline bool initialized() | |
| + { | |
| + return (lpBmp != NULL); | |
| + } | |
| + inline scrntype_t* get_buffer(int y) | |
| + { | |
| + return lpBmp + width * (height - y - 1); | |
| + } | |
| + int width, height; | |
| + scrntype_t* lpBmp; | |
| +} bitmap_t; | |
| + | |
| +typedef struct font_s { | |
| + inline bool initialized() | |
| + { | |
| + return true; | |
| + } | |
| + _TCHAR family[64]; | |
| + int width, height, rotate; | |
| + bool bold, italic; | |
| +} font_t; | |
| + | |
| +typedef struct pen_s { | |
| + inline bool initialized() | |
| + { | |
| + return true; | |
| + } | |
| + int width; | |
| + uint8_t r, g, b; | |
| +} pen_t; | |
| + | |
| +class FIFO; | |
| +class FILEIO; | |
| + | |
| +class OSD | |
| +{ | |
| +private: | |
| + int lock_count; | |
| + | |
| + // console | |
| + void initialize_console(); | |
| + void release_console(); | |
| + int console_count; | |
| + | |
| + // input | |
| + void initialize_input(); | |
| + void release_input(); | |
| + void init_key_mapping(); | |
| + uint8_t keycode_conv[256]; | |
| + uint8_t key_status[256]; | |
| + bool key_shift_pressed, key_shift_released; | |
| + bool key_caps_locked; | |
| + bool lost_focus; | |
| + | |
| +#ifdef USE_JOYSTICK | |
| + uint32_t joy_status[4]; | |
| + int joy_num; | |
| + SDL_Joystick* joy[4]; | |
| + bool joy_to_key_status[256]; | |
| +#endif | |
| + | |
| +#ifdef USE_MOUSE | |
| + int32_t mouse_status[3]; | |
| + bool mouse_enabled; | |
| +#endif | |
| + | |
| + // screen | |
| + void initialize_screen(); | |
| + void release_screen(); | |
| + void initialize_screen_buffer(bitmap_t *buffer, int width, int height, int mode); | |
| + void release_screen_buffer(bitmap_t *buffer); | |
| + | |
| + bitmap_t vm_screen_buffer; | |
| + bitmap_t* draw_screen_buffer; | |
| + | |
| + int host_window_width, host_window_height; | |
| + bool host_window_mode; | |
| + int vm_screen_width, vm_screen_height; | |
| + int vm_window_width, vm_window_height; | |
| + int vm_window_width_aspect, vm_window_height_aspect; | |
| + int draw_screen_width, draw_screen_height; | |
| + | |
| + // sound | |
| + void initialize_sound(int rate, int samples); | |
| + void release_sound(); | |
| + | |
| + int sound_rate, sound_samples; | |
| + bool sound_available, sound_started, sound_muted; | |
| + SDL_AudioDeviceID audio_device_id; | |
| + _TCHAR sound_file_path[_MAX_PATH]; | |
| + FILEIO* rec_sound_fio; | |
| + int rec_sound_bytes; | |
| + int rec_sound_buffer_ptr; | |
| + | |
| +public: | |
| + OSD(); | |
| + ~OSD(); | |
| + | |
| + // common | |
| + VM_TEMPLATE* vm; | |
| + bool app_quit; | |
| + | |
| + void initialize(int rate, int samples); | |
| + void release(); | |
| + void power_off(); | |
| + void suspend(); | |
| + void restore(); | |
| + void lock_vm(); | |
| + void unlock_vm(); | |
| + bool is_vm_locked() | |
| + { | |
| + return (lock_count != 0); | |
| + } | |
| + void force_unlock_vm(); | |
| + void sleep(uint32_t ms); | |
| + | |
| + // debugger | |
| +#ifdef USE_DEBUGGER | |
| + void start_waiting_in_debugger(); | |
| + void finish_waiting_in_debugger(); | |
| + void process_waiting_in_debugger(); | |
| +#endif | |
| + | |
| + // console | |
| + void open_console(int width, int height, const _TCHAR* title); | |
| + void close_console(); | |
| + unsigned int get_console_code_page(); | |
| + void set_console_code_oage(unsigned int cp); | |
| + void get_console_cursor_position(int *x, int *y); | |
| + void set_console_cursor_position(int x, int y); | |
| + void set_console_text_attribute(unsigned short attr); | |
| + void write_console(const _TCHAR* buffer, unsigned int length); | |
| + void write_console_char(const char* buffer, unsigned int length); | |
| + void write_console_wchar(const wchar_t* buffer, unsigned int length); | |
| + int read_console_input(_TCHAR* buffer, unsigned int length); | |
| + bool is_console_key_pressed(int vk); | |
| + bool is_console_closed(); | |
| + void close_debugger_console(); | |
| + | |
| + // input | |
| + void update_input(); | |
| + void key_down(int code, bool extended, bool repeat); | |
| + void key_up(int code, bool extended); | |
| + void key_down_native(int code, bool repeat); | |
| + void key_up_native(int code); | |
| + void key_lost_focus() | |
| + { | |
| + lost_focus = true; | |
| + } | |
| +#ifdef USE_MOUSE | |
| + void enable_mouse(); | |
| + void disable_mouse(); | |
| + void toggle_mouse(); | |
| + bool is_mouse_enabled() | |
| + { | |
| + return mouse_enabled; | |
| + } | |
| +#endif | |
| + uint8_t* get_key_buffer() | |
| + { | |
| + return key_status; | |
| + } | |
| +#ifdef USE_JOYSTICK | |
| + uint32_t* get_joy_buffer() | |
| + { | |
| + return joy_status; | |
| + } | |
| +#endif | |
| +#ifdef USE_MOUSE | |
| + int32_t* get_mouse_buffer() | |
| + { | |
| + return mouse_status; | |
| + } | |
| +#endif | |
| +#ifdef USE_AUTO_KEY | |
| + bool now_auto_key; | |
| +#endif | |
| + | |
| + // screen | |
| + SDL_Window* sdl_window; | |
| + SDL_Renderer* sdl_renderer; | |
| + SDL_Texture* sdl_texture; | |
| + | |
| + double get_window_mode_power(int mode); | |
| + int get_window_mode_width(int mode); | |
| + int get_window_mode_height(int mode); | |
| + void set_host_window_size(int window_width, int window_height, bool window_mode); | |
| + void set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect); | |
| + void set_vm_screen_lines(int lines); | |
| + int get_vm_window_width() | |
| + { | |
| + return vm_window_width; | |
| + } | |
| + int get_vm_window_height() | |
| + { | |
| + return vm_window_height; | |
| + } | |
| + int get_vm_window_width_aspect() | |
| + { | |
| + return vm_window_width_aspect; | |
| + } | |
| + int get_vm_window_height_aspect() | |
| + { | |
| + return vm_window_height_aspect; | |
| + } | |
| + scrntype_t* get_vm_screen_buffer(int y); | |
| + int draw_screen(); | |
| + void capture_screen(); | |
| + bool start_record_video(int fps); | |
| + void stop_record_video(); | |
| + void restart_record_video(); | |
| + void add_extra_frames(int extra_frames); | |
| + bool now_record_video; | |
| +#ifdef USE_SCREEN_FILTER | |
| + bool screen_skip_line; | |
| +#endif | |
| + | |
| + // sound | |
| + void update_sound(int* extra_frames); | |
| + void mute_sound(); | |
| + void stop_sound(); | |
| + void start_record_sound(); | |
| + void stop_record_sound(); | |
| + void restart_record_sound(); | |
| + bool now_record_sound; | |
| + | |
| + // printer | |
| +#ifdef USE_PRINTER | |
| + void create_bitmap(bitmap_t *bitmap, int width, int height); | |
| + void release_bitmap(bitmap_t *bitmap); | |
| + void create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic); | |
| + void release_font(font_t *font); | |
| + void create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b); | |
| + void release_pen(pen_t *pen); | |
| + void clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b); | |
| + int get_text_width(bitmap_t *bitmap, font_t *font, const char *text); | |
| + void draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const char *text, uint8_t r, uint8_t g, uint8_t b); | |
| + void draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey); | |
| + void draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b); | |
| + void draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b); | |
| + void stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height); | |
| +#endif | |
| + void write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path); | |
| + | |
| + // socket | |
| +#ifdef USE_SOCKET | |
| + uint32_t get_socket(int ch) { return 0; } | |
| + void notify_socket_connected(int ch) {} | |
| + void notify_socket_disconnected(int ch) {} | |
| + void update_socket() {} | |
| + bool initialize_socket_tcp(int ch) { return false; } | |
| + bool initialize_socket_udp(int ch) { return false; } | |
| + bool connect_socket(int ch, uint32_t ipaddr, int port) { return false; } | |
| + void disconnect_socket(int ch) {} | |
| + bool listen_socket(int ch) { return false; } | |
| + void send_socket_data_tcp(int ch) {} | |
| + void send_socket_data_udp(int ch, uint32_t ipaddr, int port) {} | |
| + void send_socket_data(int ch) {} | |
| + void recv_socket_data(int ch) {} | |
| +#endif | |
| + | |
| + // midi | |
| +#ifdef USE_MIDI | |
| + void send_to_midi(uint8_t data) {} | |
| + bool recv_from_midi(uint8_t *data) { return false; } | |
| +#endif | |
| +}; | |
| + | |
| +#endif | |
| diff --git a/src/sdl/osd_console.cpp b/src/sdl/osd_console.cpp | |
| new file mode 100644 | |
| index 0000000..955fe51 | |
| --- /dev/null | |
| +++ b/src/sdl/osd_console.cpp | |
| @@ -0,0 +1,95 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.26- | |
| + | |
| + [ SDL2 console ] | |
| +*/ | |
| + | |
| +#include "osd.h" | |
| + | |
| +void OSD::initialize_console() | |
| +{ | |
| + console_count = 0; | |
| +} | |
| + | |
| +void OSD::release_console() | |
| +{ | |
| +} | |
| + | |
| +void OSD::open_console(int width, int height, const _TCHAR* title) | |
| +{ | |
| + console_count++; | |
| +} | |
| + | |
| +void OSD::close_console() | |
| +{ | |
| + if (console_count > 0) { | |
| + console_count--; | |
| + } | |
| +} | |
| + | |
| +unsigned int OSD::get_console_code_page() | |
| +{ | |
| + return 0; | |
| +} | |
| + | |
| +void OSD::set_console_code_oage(unsigned int cp) | |
| +{ | |
| +} | |
| + | |
| +void OSD::get_console_cursor_position(int *x, int *y) | |
| +{ | |
| + if (x) *x = 0; | |
| + if (y) *y = 0; | |
| +} | |
| + | |
| +void OSD::set_console_cursor_position(int x, int y) | |
| +{ | |
| +} | |
| + | |
| +void OSD::set_console_text_attribute(unsigned short attr) | |
| +{ | |
| +} | |
| + | |
| +void OSD::write_console(const _TCHAR* buffer, unsigned int length) | |
| +{ | |
| + printf("%s", buffer); | |
| + fflush(stdout); | |
| +} | |
| + | |
| +void OSD::write_console_char(const char* buffer, unsigned int length) | |
| +{ | |
| + printf("%s", buffer); | |
| + fflush(stdout); | |
| +} | |
| + | |
| +void OSD::write_console_wchar(const wchar_t* buffer, unsigned int length) | |
| +{ | |
| + wprintf(L"%ls", buffer); | |
| + fflush(stdout); | |
| +} | |
| + | |
| +int OSD::read_console_input(_TCHAR* buffer, unsigned int length) | |
| +{ | |
| + if (fgets(buffer, length, stdin) != NULL) { | |
| + return (int)strlen(buffer); | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| +bool OSD::is_console_key_pressed(int vk) | |
| +{ | |
| + return false; | |
| +} | |
| + | |
| +bool OSD::is_console_closed() | |
| +{ | |
| + return (console_count == 0); | |
| +} | |
| + | |
| +void OSD::close_debugger_console() | |
| +{ | |
| + close_console(); | |
| +} | |
| diff --git a/src/sdl/osd_input.cpp b/src/sdl/osd_input.cpp | |
| new file mode 100644 | |
| index 0000000..510f843 | |
| --- /dev/null | |
| +++ b/src/sdl/osd_input.cpp | |
| @@ -0,0 +1,486 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.26- | |
| + | |
| + [ SDL2 input ] | |
| +*/ | |
| + | |
| +#include "osd.h" | |
| + | |
| +static int keysym_to_vk(const SDL_Keysym& keysym) | |
| +{ | |
| + switch (keysym.sym) { | |
| + case SDLK_COLON: return VK_OEM_1; // ':' (0xBA) | |
| + case SDLK_SEMICOLON: return VK_OEM_PLUS; // ';' (0xBB) | |
| + case SDLK_AT: return VK_OEM_3; // '@' (0xC0) | |
| + case SDLK_LEFTBRACKET: return VK_OEM_4; // '[' (0xDB) | |
| + case SDLK_RIGHTBRACKET: return VK_OEM_6; // ']' (0xDD) | |
| + case SDLK_BACKSLASH: return VK_OEM_5; // '\' (0xDC) | |
| + case SDLK_CARET: return VK_OEM_7; // '^' (0xDE) | |
| + case SDLK_UNDERSCORE: return VK_OEM_102; // '_' (0xE2) | |
| + case SDLK_MINUS: return VK_OEM_MINUS; // '-' (0xBD) | |
| + case SDLK_COMMA: return VK_OEM_COMMA; // ',' (0xBC) | |
| + case SDLK_PERIOD: return VK_OEM_PERIOD; // '.' (0xBE) | |
| + case SDLK_SLASH: return VK_OEM_2; // '/' (0xBF) | |
| + case SDLK_QUOTE: return VK_OEM_1; // ''' -> ':' for US keyboard | |
| + case SDLK_EQUALS: return VK_OEM_7; // '=' -> '^' for US keyboard | |
| + | |
| + // Control / Action keys | |
| + case SDLK_RETURN: return VK_RETURN; | |
| + case SDLK_ESCAPE: return VK_ESCAPE; | |
| + case SDLK_BACKSPACE: return VK_BACK; | |
| + case SDLK_TAB: return VK_TAB; | |
| + case SDLK_SPACE: return VK_SPACE; | |
| + | |
| + // Cursor / Arrow keys | |
| + case SDLK_UP: return VK_UP; | |
| + case SDLK_DOWN: return VK_DOWN; | |
| + case SDLK_LEFT: return VK_LEFT; | |
| + case SDLK_RIGHT: return VK_RIGHT; | |
| + | |
| + // Digits 0..9 | |
| + case SDLK_0: return VK_0; | |
| + case SDLK_1: return VK_1; | |
| + case SDLK_2: return VK_2; | |
| + case SDLK_3: return VK_3; | |
| + case SDLK_4: return VK_4; | |
| + case SDLK_5: return VK_5; | |
| + case SDLK_6: return VK_6; | |
| + case SDLK_7: return VK_7; | |
| + case SDLK_8: return VK_8; | |
| + case SDLK_9: return VK_9; | |
| + | |
| + // Tenkey / Numeric Keypad | |
| + case SDLK_KP_0: return VK_NUMPAD0; | |
| + case SDLK_KP_1: return VK_NUMPAD1; | |
| + case SDLK_KP_2: return VK_NUMPAD2; | |
| + case SDLK_KP_3: return VK_NUMPAD3; | |
| + case SDLK_KP_4: return VK_NUMPAD4; | |
| + case SDLK_KP_5: return VK_NUMPAD5; | |
| + case SDLK_KP_6: return VK_NUMPAD6; | |
| + case SDLK_KP_7: return VK_NUMPAD7; | |
| + case SDLK_KP_8: return VK_NUMPAD8; | |
| + case SDLK_KP_9: return VK_NUMPAD9; | |
| + case SDLK_KP_PERIOD: return VK_DECIMAL; | |
| + case SDLK_KP_PLUS: return VK_ADD; | |
| + case SDLK_KP_MINUS: return VK_SUBTRACT; | |
| + case SDLK_KP_MULTIPLY: return VK_MULTIPLY; | |
| + case SDLK_KP_DIVIDE: return VK_DIVIDE; | |
| + case SDLK_KP_ENTER: return VK_RETURN; | |
| + case SDLK_KP_EQUALS: return VK_OEM_PLUS; | |
| + } | |
| + | |
| + switch (keysym.scancode) { | |
| + case SDL_SCANCODE_A: return VK_A; | |
| + case SDL_SCANCODE_B: return VK_B; | |
| + case SDL_SCANCODE_C: return VK_C; | |
| + case SDL_SCANCODE_D: return VK_D; | |
| + case SDL_SCANCODE_E: return VK_E; | |
| + case SDL_SCANCODE_F: return VK_F; | |
| + case SDL_SCANCODE_G: return VK_G; | |
| + case SDL_SCANCODE_H: return VK_H; | |
| + case SDL_SCANCODE_I: return VK_I; | |
| + case SDL_SCANCODE_J: return VK_J; | |
| + case SDL_SCANCODE_K: return VK_K; | |
| + case SDL_SCANCODE_L: return VK_L; | |
| + case SDL_SCANCODE_M: return VK_M; | |
| + case SDL_SCANCODE_N: return VK_N; | |
| + case SDL_SCANCODE_O: return VK_O; | |
| + case SDL_SCANCODE_P: return VK_P; | |
| + case SDL_SCANCODE_Q: return VK_Q; | |
| + case SDL_SCANCODE_R: return VK_R; | |
| + case SDL_SCANCODE_S: return VK_S; | |
| + case SDL_SCANCODE_T: return VK_T; | |
| + case SDL_SCANCODE_U: return VK_U; | |
| + case SDL_SCANCODE_V: return VK_V; | |
| + case SDL_SCANCODE_W: return VK_W; | |
| + case SDL_SCANCODE_X: return VK_X; | |
| + case SDL_SCANCODE_Y: return VK_Y; | |
| + case SDL_SCANCODE_Z: return VK_Z; | |
| + | |
| + case SDL_SCANCODE_1: return VK_1; | |
| + case SDL_SCANCODE_2: return VK_2; | |
| + case SDL_SCANCODE_3: return VK_3; | |
| + case SDL_SCANCODE_4: return VK_4; | |
| + case SDL_SCANCODE_5: return VK_5; | |
| + case SDL_SCANCODE_6: return VK_6; | |
| + case SDL_SCANCODE_7: return VK_7; | |
| + case SDL_SCANCODE_8: return VK_8; | |
| + case SDL_SCANCODE_9: return VK_9; | |
| + case SDL_SCANCODE_0: return VK_0; | |
| + | |
| + case SDL_SCANCODE_RETURN: return VK_RETURN; | |
| + case SDL_SCANCODE_ESCAPE: return VK_ESCAPE; | |
| + case SDL_SCANCODE_BACKSPACE: return VK_BACK; | |
| + case SDL_SCANCODE_TAB: return VK_TAB; | |
| + case SDL_SCANCODE_SPACE: return VK_SPACE; | |
| + | |
| + case SDL_SCANCODE_MINUS: return VK_OEM_MINUS; | |
| + case SDL_SCANCODE_EQUALS: return VK_OEM_7; | |
| + case SDL_SCANCODE_LEFTBRACKET: return VK_OEM_4; | |
| + case SDL_SCANCODE_RIGHTBRACKET: return VK_OEM_6; | |
| + case SDL_SCANCODE_BACKSLASH: return VK_OEM_5; | |
| + case SDL_SCANCODE_NONUSHASH: return VK_OEM_5; | |
| + case SDL_SCANCODE_SEMICOLON: return VK_OEM_PLUS; | |
| + case SDL_SCANCODE_APOSTROPHE: return VK_OEM_1; | |
| + case SDL_SCANCODE_GRAVE: return VK_OEM_3; | |
| + case SDL_SCANCODE_COMMA: return VK_OEM_COMMA; | |
| + case SDL_SCANCODE_PERIOD: return VK_OEM_PERIOD; | |
| + case SDL_SCANCODE_SLASH: return VK_OEM_2; | |
| + | |
| + case SDL_SCANCODE_CAPSLOCK: return VK_CAPITAL; | |
| + | |
| + case SDL_SCANCODE_F1: return VK_F1; | |
| + case SDL_SCANCODE_F2: return VK_F2; | |
| + case SDL_SCANCODE_F3: return VK_F3; | |
| + case SDL_SCANCODE_F4: return VK_F4; | |
| + case SDL_SCANCODE_F5: return VK_F5; | |
| + case SDL_SCANCODE_F6: return VK_F6; | |
| + case SDL_SCANCODE_F7: return VK_F7; | |
| + case SDL_SCANCODE_F8: return VK_F8; | |
| + case SDL_SCANCODE_F9: return VK_F9; | |
| + case SDL_SCANCODE_F10: return VK_F10; | |
| + case SDL_SCANCODE_F11: return VK_F11; | |
| + case SDL_SCANCODE_F12: return VK_F12; | |
| + | |
| + case SDL_SCANCODE_PRINTSCREEN: return VK_SNAPSHOT; | |
| + case SDL_SCANCODE_SCROLLLOCK: return VK_SCROLL; | |
| + case SDL_SCANCODE_PAUSE: return VK_PAUSE; | |
| + case SDL_SCANCODE_INSERT: return VK_INSERT; | |
| + case SDL_SCANCODE_HOME: return VK_HOME; | |
| + case SDL_SCANCODE_PAGEUP: return VK_PRIOR; | |
| + case SDL_SCANCODE_DELETE: return VK_DELETE; | |
| + case SDL_SCANCODE_END: return VK_END; | |
| + case SDL_SCANCODE_PAGEDOWN: return VK_NEXT; | |
| + case SDL_SCANCODE_RIGHT: return VK_RIGHT; | |
| + case SDL_SCANCODE_LEFT: return VK_LEFT; | |
| + case SDL_SCANCODE_DOWN: return VK_DOWN; | |
| + case SDL_SCANCODE_UP: return VK_UP; | |
| + | |
| + case SDL_SCANCODE_NUMLOCKCLEAR: return VK_NUMLOCK; | |
| + case SDL_SCANCODE_KP_DIVIDE: return VK_DIVIDE; | |
| + case SDL_SCANCODE_KP_MULTIPLY: return VK_MULTIPLY; | |
| + case SDL_SCANCODE_KP_MINUS: return VK_SUBTRACT; | |
| + case SDL_SCANCODE_KP_PLUS: return VK_ADD; | |
| + case SDL_SCANCODE_KP_ENTER: return VK_RETURN; | |
| + case SDL_SCANCODE_KP_1: return VK_NUMPAD1; | |
| + case SDL_SCANCODE_KP_2: return VK_NUMPAD2; | |
| + case SDL_SCANCODE_KP_3: return VK_NUMPAD3; | |
| + case SDL_SCANCODE_KP_4: return VK_NUMPAD4; | |
| + case SDL_SCANCODE_KP_5: return VK_NUMPAD5; | |
| + case SDL_SCANCODE_KP_6: return VK_NUMPAD6; | |
| + case SDL_SCANCODE_KP_7: return VK_NUMPAD7; | |
| + case SDL_SCANCODE_KP_8: return VK_NUMPAD8; | |
| + case SDL_SCANCODE_KP_9: return VK_NUMPAD9; | |
| + case SDL_SCANCODE_KP_0: return VK_NUMPAD0; | |
| + case SDL_SCANCODE_KP_PERIOD: return VK_DECIMAL; | |
| + case SDL_SCANCODE_KP_EQUALS: return VK_OEM_PLUS; | |
| + | |
| + case SDL_SCANCODE_NONUSBACKSLASH: return VK_OEM_102; | |
| + case SDL_SCANCODE_APPLICATION: return VK_APPS; | |
| + | |
| + case SDL_SCANCODE_LCTRL: return VK_LCONTROL; | |
| + case SDL_SCANCODE_LSHIFT: return VK_LSHIFT; | |
| + case SDL_SCANCODE_LALT: return VK_LMENU; | |
| + case SDL_SCANCODE_LGUI: return VK_LWIN; | |
| + case SDL_SCANCODE_RCTRL: return VK_RCONTROL; | |
| + case SDL_SCANCODE_RSHIFT: return VK_RSHIFT; | |
| + case SDL_SCANCODE_RALT: return VK_RMENU; | |
| + case SDL_SCANCODE_RGUI: return VK_RWIN; | |
| + | |
| + case SDL_SCANCODE_INTERNATIONAL1: return VK_OEM_102; // \ _ | |
| + case SDL_SCANCODE_INTERNATIONAL2: return VK_KANA; // Katakana/Hiragana | |
| + case SDL_SCANCODE_INTERNATIONAL3: return VK_OEM_5; // Yen | |
| + case SDL_SCANCODE_INTERNATIONAL4: return VK_CONVERT; // Henkan | |
| + case SDL_SCANCODE_INTERNATIONAL5: return VK_NONCONVERT; // Muhenkan | |
| + | |
| + case SDL_SCANCODE_LANG1: return VK_KANA; // Mac Kana key | |
| + case SDL_SCANCODE_LANG2: return VK_KANA; // Mac Eisu key | |
| + | |
| + default: return 0; | |
| + } | |
| +} | |
| + | |
| +void OSD::initialize_input() | |
| +{ | |
| + memset(key_status, 0, sizeof(key_status)); | |
| + key_shift_pressed = key_shift_released = false; | |
| + key_caps_locked = false; | |
| + lost_focus = false; | |
| + | |
| + for (int i = 0; i < 256; ++i) { | |
| + keycode_conv[i] = (uint8_t)i; | |
| + } | |
| + | |
| +#ifdef USE_JOYSTICK | |
| + memset(joy_status, 0, sizeof(joy_status)); | |
| + memset(joy_to_key_status, 0, sizeof(joy_to_key_status)); | |
| + joy_num = 0; | |
| + for (int i = 0; i < 4; ++i) { | |
| + joy[i] = NULL; | |
| + } | |
| + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { | |
| + SDL_InitSubSystem(SDL_INIT_JOYSTICK); | |
| + } | |
| + joy_num = SDL_NumJoysticks(); | |
| + for (int i = 0; i < joy_num && i < 4; ++i) { | |
| + joy[i] = SDL_JoystickOpen(i); | |
| + } | |
| +#endif | |
| + | |
| +#ifdef USE_MOUSE | |
| + memset(mouse_status, 0, sizeof(mouse_status)); | |
| + mouse_enabled = false; | |
| +#endif | |
| +} | |
| + | |
| +void OSD::release_input() | |
| +{ | |
| +#ifdef USE_JOYSTICK | |
| + for (int i = 0; i < 4; ++i) { | |
| + if (joy[i] != NULL) { | |
| + SDL_JoystickClose(joy[i]); | |
| + joy[i] = NULL; | |
| + } | |
| + } | |
| +#endif | |
| +#ifdef USE_MOUSE | |
| + disable_mouse(); | |
| +#endif | |
| +} | |
| + | |
| +void OSD::update_input() | |
| +{ | |
| +#ifdef USE_MOUSE | |
| + mouse_status[0] = 0; | |
| + mouse_status[1] = 0; | |
| +#endif | |
| + | |
| + SDL_Event event; | |
| + while (SDL_PollEvent(&event)) { | |
| + switch (event.type) { | |
| + case SDL_QUIT: | |
| + app_quit = true; | |
| + break; | |
| + | |
| + case SDL_WINDOWEVENT: | |
| + if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { | |
| + key_lost_focus(); | |
| + } | |
| + break; | |
| + | |
| + case SDL_KEYDOWN: { | |
| + int vk = keysym_to_vk(event.key.keysym); | |
| + if (vk != 0) { | |
| + bool repeat = (event.key.repeat != 0); | |
| + key_down(vk, false, repeat); | |
| + } | |
| + break; | |
| + } | |
| + | |
| + case SDL_KEYUP: { | |
| + int vk = keysym_to_vk(event.key.keysym); | |
| + if (vk != 0) { | |
| + key_up(vk, false); | |
| + } | |
| + break; | |
| + } | |
| + | |
| +#ifdef USE_MOUSE | |
| + case SDL_MOUSEMOTION: | |
| + if (mouse_enabled) { | |
| + mouse_status[0] += event.motion.xrel; | |
| + mouse_status[1] += event.motion.yrel; | |
| + } | |
| + break; | |
| + | |
| + case SDL_MOUSEBUTTONDOWN: | |
| + if (!mouse_enabled && event.button.button == SDL_BUTTON_LEFT) { | |
| + enable_mouse(); | |
| + } | |
| + if (event.button.button == SDL_BUTTON_LEFT) { | |
| + mouse_status[2] |= 1; | |
| + } else if (event.button.button == SDL_BUTTON_RIGHT) { | |
| + mouse_status[2] |= 2; | |
| + } else if (event.button.button == SDL_BUTTON_MIDDLE) { | |
| + toggle_mouse(); | |
| + } | |
| + break; | |
| + | |
| + case SDL_MOUSEBUTTONUP: | |
| + if (event.button.button == SDL_BUTTON_LEFT) { | |
| + mouse_status[2] &= ~1; | |
| + } else if (event.button.button == SDL_BUTTON_RIGHT) { | |
| + mouse_status[2] &= ~2; | |
| + } | |
| + break; | |
| +#endif | |
| + | |
| +#ifdef USE_JOYSTICK | |
| + case SDL_JOYAXISMOTION: { | |
| + int which = event.jaxis.which; | |
| + if (which >= 0 && which < 4) { | |
| + if (event.jaxis.axis == 0) { // X axis | |
| + joy_status[which] &= ~0x0000000C; // clear left/right | |
| + if (event.jaxis.value < -16384) { | |
| + joy_status[which] |= 0x00000004; // left | |
| + } else if (event.jaxis.value > 16384) { | |
| + joy_status[which] |= 0x00000008; // right | |
| + } | |
| + } else if (event.jaxis.axis == 1) { // Y axis | |
| + joy_status[which] &= ~0x00000003; // clear up/down | |
| + if (event.jaxis.value < -16384) { | |
| + joy_status[which] |= 0x00000001; // up | |
| + } else if (event.jaxis.value > 16384) { | |
| + joy_status[which] |= 0x00000002; // down | |
| + } | |
| + } | |
| + } | |
| + break; | |
| + } | |
| + | |
| + case SDL_JOYBUTTONDOWN: { | |
| + int which = event.jbutton.which; | |
| + if (which >= 0 && which < 4 && event.jbutton.button < 16) { | |
| + joy_status[which] |= (1 << (event.jbutton.button + 4)); | |
| + } | |
| + break; | |
| + } | |
| + | |
| + case SDL_JOYBUTTONUP: { | |
| + int which = event.jbutton.which; | |
| + if (which >= 0 && which < 4 && event.jbutton.button < 16) { | |
| + joy_status[which] &= ~(1 << (event.jbutton.button + 4)); | |
| + } | |
| + break; | |
| + } | |
| +#endif | |
| + default: | |
| + break; | |
| + } | |
| + } | |
| + | |
| + if (lost_focus) { | |
| + for (int i = 0; i < 256; ++i) { | |
| + if (key_status[i]) { | |
| + key_status[i] = 0; | |
| + if (vm != NULL) { | |
| + vm->key_up(i); | |
| + } | |
| + } | |
| + } | |
| + lost_focus = false; | |
| + } | |
| +} | |
| + | |
| +void OSD::key_down(int code, bool extended, bool repeat) | |
| +{ | |
| + key_down_native(code, repeat); | |
| +} | |
| + | |
| +void OSD::key_up(int code, bool extended) | |
| +{ | |
| + key_up_native(code); | |
| +} | |
| + | |
| +void OSD::key_down_native(int code, bool repeat) | |
| +{ | |
| + if (!(code == VK_LSHIFT || code == VK_RSHIFT || code == VK_LCONTROL || code == VK_RCONTROL || code == VK_LMENU || code == VK_RMENU)) { | |
| + code = keycode_conv[code & 0xff]; | |
| + } | |
| + if (key_status[code] == 0) { | |
| + repeat = false; | |
| + } | |
| + key_status[code] = 0x80; | |
| + | |
| + uint8_t prev_shift = key_status[VK_SHIFT]; | |
| + uint8_t prev_control = key_status[VK_CONTROL]; | |
| + uint8_t prev_menu = key_status[VK_MENU]; | |
| + | |
| + key_status[VK_SHIFT] = key_status[VK_LSHIFT] | key_status[VK_RSHIFT]; | |
| + key_status[VK_CONTROL] = key_status[VK_LCONTROL] | key_status[VK_RCONTROL]; | |
| + key_status[VK_MENU] = key_status[VK_LMENU] | key_status[VK_RMENU]; | |
| + | |
| + if (vm != NULL) { | |
| + if (code == VK_LSHIFT || code == VK_RSHIFT) { | |
| + if (prev_shift == 0 && key_status[VK_SHIFT] != 0) { | |
| + vm->key_down(VK_SHIFT, repeat); | |
| + } | |
| + } else if (code == VK_LCONTROL || code == VK_RCONTROL) { | |
| + if (prev_control == 0 && key_status[VK_CONTROL] != 0) { | |
| + vm->key_down(VK_CONTROL, repeat); | |
| + } | |
| + } else if (code == VK_LMENU || code == VK_RMENU) { | |
| + if (prev_menu == 0 && key_status[VK_MENU] != 0) { | |
| + vm->key_down(VK_MENU, repeat); | |
| + } | |
| + } | |
| + vm->key_down(code, repeat); | |
| + } | |
| +} | |
| + | |
| +void OSD::key_up_native(int code) | |
| +{ | |
| + if (!(code == VK_LSHIFT || code == VK_RSHIFT || code == VK_LCONTROL || code == VK_RCONTROL || code == VK_LMENU || code == VK_RMENU)) { | |
| + code = keycode_conv[code & 0xff]; | |
| + } | |
| + if (key_status[code] == 0) { | |
| + return; | |
| + } | |
| + key_status[code] = 0; | |
| + | |
| + if (vm != NULL) { | |
| + vm->key_up(code); | |
| + | |
| + uint8_t prev_shift = key_status[VK_SHIFT]; | |
| + uint8_t prev_control = key_status[VK_CONTROL]; | |
| + uint8_t prev_menu = key_status[VK_MENU]; | |
| + | |
| + key_status[VK_SHIFT] = key_status[VK_LSHIFT] | key_status[VK_RSHIFT]; | |
| + key_status[VK_CONTROL] = key_status[VK_LCONTROL] | key_status[VK_RCONTROL]; | |
| + key_status[VK_MENU] = key_status[VK_LMENU] | key_status[VK_RMENU]; | |
| + | |
| + if (code == VK_LSHIFT || code == VK_RSHIFT) { | |
| + if (prev_shift != 0 && key_status[VK_SHIFT] == 0) { | |
| + vm->key_up(VK_SHIFT); | |
| + } | |
| + } else if (code == VK_LCONTROL || code == VK_RCONTROL) { | |
| + if (prev_control != 0 && key_status[VK_CONTROL] == 0) { | |
| + vm->key_up(VK_CONTROL); | |
| + } | |
| + } else if (code == VK_LMENU || code == VK_RMENU) { | |
| + if (prev_menu != 0 && key_status[VK_MENU] == 0) { | |
| + vm->key_up(VK_MENU); | |
| + } | |
| + } | |
| + } | |
| +} | |
| + | |
| +#ifdef USE_MOUSE | |
| +void OSD::enable_mouse() | |
| +{ | |
| + if (!mouse_enabled) { | |
| + SDL_SetRelativeMouseMode(SDL_TRUE); | |
| + mouse_enabled = true; | |
| + } | |
| +} | |
| + | |
| +void OSD::disable_mouse() | |
| +{ | |
| + if (mouse_enabled) { | |
| + SDL_SetRelativeMouseMode(SDL_FALSE); | |
| + mouse_enabled = false; | |
| + } | |
| +} | |
| + | |
| +void OSD::toggle_mouse() | |
| +{ | |
| + if (mouse_enabled) { | |
| + disable_mouse(); | |
| + } else { | |
| + enable_mouse(); | |
| + } | |
| +} | |
| +#endif | |
| diff --git a/src/sdl/osd_screen.cpp b/src/sdl/osd_screen.cpp | |
| new file mode 100644 | |
| index 0000000..7fe89a2 | |
| --- /dev/null | |
| +++ b/src/sdl/osd_screen.cpp | |
| @@ -0,0 +1,316 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.20- | |
| + | |
| + [ SDL2 screen ] | |
| +*/ | |
| + | |
| +#include "osd.h" | |
| + | |
| +void OSD::initialize_screen() | |
| +{ | |
| + host_window_width = WINDOW_WIDTH; | |
| + host_window_height = WINDOW_HEIGHT; | |
| + host_window_mode = true; | |
| + | |
| + vm_screen_width = SCREEN_WIDTH; | |
| + vm_screen_height = SCREEN_HEIGHT; | |
| + vm_window_width = WINDOW_WIDTH; | |
| + vm_window_height = WINDOW_HEIGHT; | |
| + vm_window_width_aspect = WINDOW_WIDTH_ASPECT; | |
| + vm_window_height_aspect = WINDOW_HEIGHT_ASPECT; | |
| + | |
| + memset(&vm_screen_buffer, 0, sizeof(bitmap_t)); | |
| + initialize_screen_buffer(&vm_screen_buffer, vm_screen_width, vm_screen_height, 0); | |
| + draw_screen_buffer = &vm_screen_buffer; | |
| + | |
| + if (SDL_WasInit(SDL_INIT_VIDEO) == 0) { | |
| + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { | |
| + fprintf(stderr, "SDL_InitSubSystem(VIDEO) failed: %s\n", SDL_GetError()); | |
| + } | |
| + } | |
| + | |
| + sdl_window = SDL_CreateWindow( | |
| + DEVICE_NAME, | |
| + SDL_WINDOWPOS_CENTERED, | |
| + SDL_WINDOWPOS_CENTERED, | |
| + vm_window_width_aspect, | |
| + vm_window_height_aspect, | |
| + SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | |
| + ); | |
| + | |
| + if (sdl_window != NULL) { | |
| + sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); | |
| + if (sdl_renderer == NULL) { | |
| + sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0); | |
| + } | |
| + if (sdl_renderer != NULL) { | |
| + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); | |
| + SDL_RenderSetLogicalSize(sdl_renderer, vm_window_width_aspect, vm_window_height_aspect); | |
| + SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255); | |
| + SDL_RenderClear(sdl_renderer); | |
| + SDL_RenderPresent(sdl_renderer); | |
| + } | |
| + sdl_texture = SDL_CreateTexture( | |
| + sdl_renderer, | |
| + SDL_PIXELFORMAT_ARGB8888, | |
| + SDL_TEXTUREACCESS_STREAMING, | |
| + vm_screen_width, | |
| + vm_screen_height | |
| + ); | |
| + if (sdl_texture != NULL) { | |
| + SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_NONE); | |
| + } | |
| + } | |
| +} | |
| + | |
| +void OSD::release_screen() | |
| +{ | |
| + if (sdl_texture != NULL) { | |
| + SDL_DestroyTexture(sdl_texture); | |
| + sdl_texture = NULL; | |
| + } | |
| + if (sdl_renderer != NULL) { | |
| + SDL_DestroyRenderer(sdl_renderer); | |
| + sdl_renderer = NULL; | |
| + } | |
| + if (sdl_window != NULL) { | |
| + SDL_DestroyWindow(sdl_window); | |
| + sdl_window = NULL; | |
| + } | |
| + release_screen_buffer(&vm_screen_buffer); | |
| +} | |
| + | |
| +void OSD::initialize_screen_buffer(bitmap_t *buffer, int width, int height, int mode) | |
| +{ | |
| + release_screen_buffer(buffer); | |
| + buffer->width = width; | |
| + buffer->height = height; | |
| + buffer->lpBmp = (scrntype_t*)calloc(width * height, sizeof(scrntype_t)); | |
| +} | |
| + | |
| +void OSD::release_screen_buffer(bitmap_t *buffer) | |
| +{ | |
| + if (buffer->lpBmp != NULL) { | |
| + free(buffer->lpBmp); | |
| + buffer->lpBmp = NULL; | |
| + } | |
| + buffer->width = 0; | |
| + buffer->height = 0; | |
| +} | |
| + | |
| +double OSD::get_window_mode_power(int mode) | |
| +{ | |
| + if (mode + WINDOW_MODE_BASE == 2) { | |
| + return 1.5; | |
| + } else if (mode + WINDOW_MODE_BASE > 2) { | |
| + return mode + WINDOW_MODE_BASE - 1; | |
| + } | |
| + return mode + WINDOW_MODE_BASE; | |
| +} | |
| + | |
| +int OSD::get_window_mode_width(int mode) | |
| +{ | |
| + return (int)(vm_window_width_aspect * get_window_mode_power(mode) + 0.5); | |
| +} | |
| + | |
| +int OSD::get_window_mode_height(int mode) | |
| +{ | |
| + return (int)(vm_window_height_aspect * get_window_mode_power(mode) + 0.5); | |
| +} | |
| + | |
| +void OSD::set_host_window_size(int window_width, int window_height, bool window_mode) | |
| +{ | |
| + host_window_width = window_width; | |
| + host_window_height = window_height; | |
| + host_window_mode = window_mode; | |
| + if (sdl_window != NULL && window_mode) { | |
| + SDL_SetWindowSize(sdl_window, window_width, window_height); | |
| + } | |
| +} | |
| + | |
| +void OSD::set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect) | |
| +{ | |
| + vm_screen_width = screen_width; | |
| + vm_screen_height = screen_height; | |
| + vm_window_width = window_width; | |
| + vm_window_height = window_height; | |
| + vm_window_width_aspect = window_width_aspect; | |
| + vm_window_height_aspect = window_height_aspect; | |
| + | |
| + if (vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) { | |
| + initialize_screen_buffer(&vm_screen_buffer, vm_screen_width, vm_screen_height, 0); | |
| + } | |
| + if (sdl_texture != NULL && sdl_renderer != NULL) { | |
| + SDL_DestroyTexture(sdl_texture); | |
| + sdl_texture = SDL_CreateTexture( | |
| + sdl_renderer, | |
| + SDL_PIXELFORMAT_ARGB8888, | |
| + SDL_TEXTUREACCESS_STREAMING, | |
| + vm_screen_width, | |
| + vm_screen_height | |
| + ); | |
| + if (sdl_texture != NULL) { | |
| + SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_NONE); | |
| + } | |
| + SDL_RenderSetLogicalSize(sdl_renderer, vm_window_width_aspect, vm_window_height_aspect); | |
| + } | |
| +} | |
| + | |
| +void OSD::set_vm_screen_lines(int lines) | |
| +{ | |
| + vm_screen_height = lines; | |
| +} | |
| + | |
| +scrntype_t* OSD::get_vm_screen_buffer(int y) | |
| +{ | |
| + return vm_screen_buffer.get_buffer(y); | |
| +} | |
| + | |
| +int OSD::draw_screen() | |
| +{ | |
| + if (vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) { | |
| + initialize_screen_buffer(&vm_screen_buffer, vm_screen_width, vm_screen_height, 0); | |
| + if (sdl_texture != NULL && sdl_renderer != NULL) { | |
| + SDL_DestroyTexture(sdl_texture); | |
| + sdl_texture = SDL_CreateTexture( | |
| + sdl_renderer, | |
| + SDL_PIXELFORMAT_ARGB8888, | |
| + SDL_TEXTUREACCESS_STREAMING, | |
| + vm_screen_width, | |
| + vm_screen_height | |
| + ); | |
| + if (sdl_texture != NULL) { | |
| + SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_NONE); | |
| + } | |
| + } | |
| + } | |
| + | |
| +#ifdef USE_SCREEN_FILTER | |
| + screen_skip_line = false; | |
| +#endif | |
| + if (vm != NULL) { | |
| + vm->draw_screen(); | |
| + } | |
| + | |
| + if (sdl_renderer != NULL && sdl_texture != NULL) { | |
| + void* pixels = NULL; | |
| + int pitch = 0; | |
| + if (SDL_LockTexture(sdl_texture, NULL, &pixels, &pitch) == 0) { | |
| + for (int y = 0; y < vm_screen_height; ++y) { | |
| + scrntype_t* src = vm_screen_buffer.get_buffer(y); | |
| + uint32_t* dst = (uint32_t*)((uint8_t*)pixels + y * pitch); | |
| + memcpy(dst, src, vm_screen_width * sizeof(scrntype_t)); | |
| + } | |
| + SDL_UnlockTexture(sdl_texture); | |
| + } | |
| + SDL_RenderClear(sdl_renderer); | |
| + SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL); | |
| + SDL_RenderPresent(sdl_renderer); | |
| + } | |
| + return 1; | |
| +} | |
| + | |
| +void OSD::capture_screen() | |
| +{ | |
| +} | |
| + | |
| +bool OSD::start_record_video(int fps) | |
| +{ | |
| + return false; | |
| +} | |
| + | |
| +void OSD::stop_record_video() | |
| +{ | |
| +} | |
| + | |
| +void OSD::restart_record_video() | |
| +{ | |
| +} | |
| + | |
| +void OSD::add_extra_frames(int extra_frames) | |
| +{ | |
| +} | |
| + | |
| +void OSD::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path) | |
| +{ | |
| +} | |
| + | |
| +#ifdef USE_PRINTER | |
| +void OSD::create_bitmap(bitmap_t *bitmap, int width, int height) | |
| +{ | |
| + initialize_screen_buffer(bitmap, width, height, 0); | |
| +} | |
| + | |
| +void OSD::release_bitmap(bitmap_t *bitmap) | |
| +{ | |
| + release_screen_buffer(bitmap); | |
| +} | |
| + | |
| +void OSD::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic) | |
| +{ | |
| + my_tcscpy_s(font->family, 64, family); | |
| + font->width = width; | |
| + font->height = height; | |
| + font->rotate = rotate; | |
| + font->bold = bold; | |
| + font->italic = italic; | |
| +} | |
| + | |
| +void OSD::release_font(font_t *font) | |
| +{ | |
| +} | |
| + | |
| +void OSD::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b) | |
| +{ | |
| + pen->width = width; | |
| + pen->r = r; | |
| + pen->g = g; | |
| + pen->b = b; | |
| +} | |
| + | |
| +void OSD::release_pen(pen_t *pen) | |
| +{ | |
| +} | |
| + | |
| +void OSD::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b) | |
| +{ | |
| + if (bitmap != NULL && bitmap->lpBmp != NULL) { | |
| + scrntype_t col = RGB_COLOR(r, g, b); | |
| + for (int i = 0; i < bitmap->width * bitmap->height; ++i) { | |
| + bitmap->lpBmp[i] = col; | |
| + } | |
| + } | |
| +} | |
| + | |
| +int OSD::get_text_width(bitmap_t *bitmap, font_t *font, const char *text) | |
| +{ | |
| + return (int)strlen(text) * (font->width > 0 ? font->width : 8); | |
| +} | |
| + | |
| +void OSD::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const char *text, uint8_t r, uint8_t g, uint8_t b) | |
| +{ | |
| +} | |
| + | |
| +void OSD::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey) | |
| +{ | |
| +} | |
| + | |
| +void OSD::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b) | |
| +{ | |
| +} | |
| + | |
| +void OSD::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b) | |
| +{ | |
| + if (bitmap != NULL && x >= 0 && x < bitmap->width && y >= 0 && y < bitmap->height) { | |
| + scrntype_t* dest = bitmap->get_buffer(y); | |
| + dest[x] = RGB_COLOR(r, g, b); | |
| + } | |
| +} | |
| + | |
| +void OSD::stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height) | |
| +{ | |
| +} | |
| +#endif | |
| diff --git a/src/sdl/osd_sound.cpp b/src/sdl/osd_sound.cpp | |
| new file mode 100644 | |
| index 0000000..19a2506 | |
| --- /dev/null | |
| +++ b/src/sdl/osd_sound.cpp | |
| @@ -0,0 +1,165 @@ | |
| +/* | |
| + Skelton for retropc emulator | |
| + | |
| + Author : Takeda.Toshiya | |
| + Date : 2015.11.26- | |
| + | |
| + [ SDL2 sound ] | |
| +*/ | |
| + | |
| +#include "osd.h" | |
| +#include "../fileio.h" | |
| + | |
| +void OSD::initialize_sound(int rate, int samples) | |
| +{ | |
| + sound_rate = rate; | |
| + sound_samples = samples; | |
| + sound_available = sound_started = sound_muted = now_record_sound = false; | |
| + rec_sound_buffer_ptr = 0; | |
| + audio_device_id = 0; | |
| + | |
| + if (SDL_WasInit(SDL_INIT_AUDIO) == 0) { | |
| + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { | |
| + fprintf(stderr, "SDL_InitSubSystem(AUDIO) failed: %s\n", SDL_GetError()); | |
| + return; | |
| + } | |
| + } | |
| + | |
| + SDL_AudioSpec desired, obtained; | |
| + SDL_zero(desired); | |
| + desired.freq = sound_rate; | |
| + desired.format = AUDIO_S16SYS; | |
| + desired.channels = 2; | |
| + desired.samples = (samples > 0) ? (Uint16)samples : 1024; | |
| + desired.callback = NULL; | |
| + | |
| + audio_device_id = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0); | |
| + if (audio_device_id == 0) { | |
| + fprintf(stderr, "SDL_OpenAudioDevice failed: %s\n", SDL_GetError()); | |
| + return; | |
| + } | |
| + | |
| + sound_rate = obtained.freq; | |
| + SDL_PauseAudioDevice(audio_device_id, 0); | |
| + sound_available = true; | |
| + sound_started = true; | |
| +} | |
| + | |
| +void OSD::release_sound() | |
| +{ | |
| + if (audio_device_id != 0) { | |
| + SDL_CloseAudioDevice(audio_device_id); | |
| + audio_device_id = 0; | |
| + } | |
| + sound_available = false; | |
| + stop_record_sound(); | |
| +} | |
| + | |
| +void OSD::update_sound(int* extra_frames) | |
| +{ | |
| + *extra_frames = 0; | |
| + sound_muted = false; | |
| + | |
| + if (!sound_available || audio_device_id == 0) { | |
| + return; | |
| + } | |
| + | |
| + Uint32 queued_bytes = SDL_GetQueuedAudioSize(audio_device_id); | |
| + Uint32 max_queued = (Uint32)(sound_samples * 2 * sizeof(int16_t) * 4); | |
| + if (queued_bytes > max_queued) { | |
| + return; | |
| + } | |
| + | |
| + uint16_t* sound_buffer = vm->create_sound(extra_frames); | |
| + if (sound_buffer != NULL) { | |
| + int bytes = sound_samples * 2 * (int)sizeof(int16_t); | |
| + SDL_QueueAudio(audio_device_id, sound_buffer, bytes); | |
| + | |
| + if (now_record_sound && rec_sound_fio != NULL) { | |
| + rec_sound_fio->Fwrite(sound_buffer, bytes, 1); | |
| + rec_sound_bytes += bytes; | |
| + } | |
| + } | |
| +} | |
| + | |
| +void OSD::mute_sound() | |
| +{ | |
| + if (sound_available && audio_device_id != 0) { | |
| + SDL_ClearQueuedAudio(audio_device_id); | |
| + } | |
| + sound_muted = true; | |
| +} | |
| + | |
| +void OSD::stop_sound() | |
| +{ | |
| + if (sound_available && audio_device_id != 0) { | |
| + SDL_PauseAudioDevice(audio_device_id, 1); | |
| + sound_started = false; | |
| + } | |
| +} | |
| + | |
| +void OSD::start_record_sound() | |
| +{ | |
| + if (!now_record_sound) { | |
| + create_date_file_path(sound_file_path, _MAX_PATH, _T("wav")); | |
| + rec_sound_fio = new FILEIO(); | |
| + if (rec_sound_fio->Fopen(sound_file_path, FILEIO_WRITE_BINARY)) { | |
| + wav_header_t wav_header; | |
| + wav_chunk_t wav_chunk; | |
| + memset(&wav_header, 0, sizeof(wav_header)); | |
| + memset(&wav_chunk, 0, sizeof(wav_chunk)); | |
| + rec_sound_fio->Fwrite(&wav_header, sizeof(wav_header), 1); | |
| + rec_sound_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1); | |
| + rec_sound_bytes = 0; | |
| + now_record_sound = true; | |
| + } else { | |
| + delete rec_sound_fio; | |
| + rec_sound_fio = NULL; | |
| + } | |
| + } | |
| +} | |
| + | |
| +void OSD::stop_record_sound() | |
| +{ | |
| + if (now_record_sound) { | |
| + if (rec_sound_bytes == 0) { | |
| + rec_sound_fio->Fclose(); | |
| + FILEIO::RemoveFile(sound_file_path); | |
| + } else { | |
| + wav_header_t wav_header; | |
| + wav_chunk_t wav_chunk; | |
| + | |
| + memcpy(wav_header.riff_chunk.id, "RIFF", 4); | |
| + wav_header.riff_chunk.size = rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk) - 8; | |
| + memcpy(wav_header.wave, "WAVE", 4); | |
| + memcpy(wav_header.fmt_chunk.id, "fmt ", 4); | |
| + wav_header.fmt_chunk.size = 16; | |
| + wav_header.format_id = 1; | |
| + wav_header.channels = 2; | |
| + wav_header.sample_bits = 16; | |
| + wav_header.sample_rate = sound_rate; | |
| + wav_header.block_size = wav_header.channels * wav_header.sample_bits / 8; | |
| + wav_header.data_speed = wav_header.sample_rate * wav_header.block_size; | |
| + | |
| + memcpy(wav_chunk.id, "data", 4); | |
| + wav_chunk.size = rec_sound_bytes; | |
| + | |
| + rec_sound_fio->Fseek(0, FILEIO_SEEK_SET); | |
| + rec_sound_fio->Fwrite(&wav_header, sizeof(wav_header), 1); | |
| + rec_sound_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1); | |
| + rec_sound_fio->Fclose(); | |
| + } | |
| + delete rec_sound_fio; | |
| + rec_sound_fio = NULL; | |
| + now_record_sound = false; | |
| + } | |
| +} | |
| + | |
| +void OSD::restart_record_sound() | |
| +{ | |
| + bool tmp = now_record_sound; | |
| + stop_record_sound(); | |
| + if (tmp) { | |
| + start_record_sound(); | |
| + } | |
| +} | |
| diff --git a/src/vm/pc100/crtc.cpp b/src/vm/pc100/crtc.cpp | |
| index bce9fae..1cb5975 100644 | |
| --- a/src/vm/pc100/crtc.cpp | |
| +++ b/src/vm/pc100/crtc.cpp | |
| @@ -14,6 +14,10 @@ void CRTC::initialize() | |
| { | |
| // init vram | |
| memset(vram, 0, sizeof(vram)); | |
| + memset(regs, 0, sizeof(regs)); | |
| + sel = 0; | |
| + vs = 0; | |
| + cmd = 0; | |
| // init bit control | |
| shift = 0; | |
| diff --git a/src/vm/pc100/ioctrl.cpp b/src/vm/pc100/ioctrl.cpp | |
| index 8ff5ab4..1e6a3c9 100644 | |
| --- a/src/vm/pc100/ioctrl.cpp | |
| +++ b/src/vm/pc100/ioctrl.cpp | |
| @@ -17,7 +17,7 @@ | |
| static const int key_table[256] = { | |
| -1, -1, -1, -1, -1, -1, -1, -1,0x18,0x12, -1, -1, -1,0x38, -1, -1, | |
| -1,0x04,0x05,0x09, -1, -1, -1, -1, -1,0x10, -1,0x11, -1, -1, -1, -1, | |
| - 0x4A, -1, -1,0x5B,0x5A,0x15,0x13,0x16,0x14, -1, -1, -1, -1,0x17, -1, -1, | |
| + 0x4A, -1, -1,0x5B,0x5A,0x0C,0x0D,0x0B,0x0E, -1, -1, -1, -1,0x17, -1, -1, | |
| 0x27,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x26, -1, -1, -1, -1, -1, -1, | |
| -1,0x31,0x45,0x43,0x33,0x23,0x34,0x35,0x36,0x30,0x3F,0x40,0x3B,0x47,0x46,0x2B, | |
| 0x29,0x21,0x2C,0x32,0x2D,0x2F,0x44,0x22,0x3A,0x2E,0x39, -1, -1, -1, -1, -1, | |
| @@ -188,21 +188,29 @@ void IOCTRL::write_signal(int id, uint32_t data, uint32_t mask) | |
| void IOCTRL::key_down(int code) | |
| { | |
| + int vk = code; | |
| if(code == 0x14) { | |
| caps = !caps; | |
| } else if(code == 0x15) { | |
| kana = !kana; | |
| } else if((code = key_table[code & 0xff]) != -1) { | |
| - code |= 0x80; | |
| + // PC-100 keyboard: bit7=0 means MAKE (key pressed) | |
| + code &= ~0x80; | |
| + //fprintf(stderr, "[KEY_DOWN] vk=0x%02x -> pc100_scan=0x%02x, buf_val=0x%03x\n", vk, code, code | 0x100); | |
| key_buf->write(code | 0x100); | |
| update_key(); | |
| + } else { | |
| + //fprintf(stderr, "[KEY_DOWN] vk=0x%02x -> NOT MAPPED (key_table=-1)\n", vk); | |
| } | |
| } | |
| void IOCTRL::key_up(int code) | |
| { | |
| + int vk = code; | |
| if((code = key_table[code & 0xff]) != -1) { | |
| - code &= ~0x80; | |
| + // PC-100 keyboard: bit7=1 means BREAK (key released) | |
| + code |= 0x80; | |
| + //fprintf(stderr, "[KEY_UP] vk=0x%02x -> pc100_scan=0x%02x, buf_val=0x%03x\n", vk, code, code | 0x100); | |
| key_buf->write(code | 0x100); | |
| update_key(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment