Skip to content

Instantly share code, notes, and snippets.

@umjammer
Last active August 20, 2026 05:34
Show Gist options
  • Select an option

  • Save umjammer/7454bbdedd9af1c9d458bf978bdecddc to your computer and use it in GitHub Desktop.

Select an option

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
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