From 97c56f05d530a2ad98b10be19fa620c8bca416ab Mon Sep 17 00:00:00 2001 From: Memotech Bill <64212746+Memotech-Bill@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:50:49 +0100 Subject: [PATCH] Initial draft of SDL version (currently Linux only) --- .gitignore | 3 +- CMakeLists.txt | 56 +++++++ README.md | 2 + src/memu/CMakeLists.txt | 159 +++++++++--------- src/memu/win.h | 30 ++-- src/memu/win_sdl.c | 353 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 507 insertions(+), 96 deletions(-) create mode 100644 src/memu/win_sdl.c diff --git a/.gitignore b/.gitignore index 834aeda..92fd831 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ build* run_time/memu-* run_time/portaudio* *.log -run_time/disks/*.bin \ No newline at end of file +run_time/disks/*.bin +*.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index fef48b9..94f81e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -402,6 +402,62 @@ elseif("${TARGET}" STREQUAL "Circle") COMMAND objcopy memu-circle -O binary ${KERNEL} ) +elseif("${TARGET}" STREQUAL "SDL") + + set (SDL2_DIR "/usr/lib/x86_64-linux-gnu/cmake/SDL2/") + find_package(SDL2 REQUIRED) + + set(src_defs + -DLSB_FIRST + -DDYNAMIC_ROMS + -DHAVE_CONFIG + -DALT_OPTIONS=cfg_options + -DALT_USAGE=cfg_usage + -DUNIX + -DHAVE_AUTOTYPE + -DHAVE_CFX2 + -DHAVE_CONSOLE + -DHAVE_DART + -DHAVE_DISASS + -DHAVE_JOY + -DHAVE_MFX + -DMAP_PATH + -DHAVE_OSFS + -DHAVE_SID + -DHAVE_SPEC + -DHAVE_UI + -DHAVE_VDEB + -DHAVE_VGA + -DHAVE_NFX + -DZ80_DEBUG + ) + + if(NOT (${CMAKE_VERSION} VERSION_LESS "3.12.0")) + + project(memu C) + + add_executable(memu-sdl) + + set_target_properties(memu-sdl PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/run_time + ) + + target_compile_options(memu-sdl PUBLIC -g) + target_link_options(memu-sdl PUBLIC -g) + # target_compile_options(memu-sdl PUBLIC -fsanitize=address -fsanitize=leak) + # target_link_options(memu-sdl PUBLIC -fsanitize=address -fsanitize=leak -static-libasan) + + target_compile_definitions(memu-sdl PUBLIC ${src_defs}) + + target_link_libraries(memu-sdl PUBLIC + memu_src + Z80_emu + portaudio + ${SDL2_LIBRARIES} + m + ) + endif() + else() message(FATAL_ERROR "No valid target specified in MEMU/CMakeLists.txt") diff --git a/README.md b/README.md index d4ee09d..df51f05 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ It now includes all my current ports of MEMU. It includes versions for: * Raspberry Pi: A Linux build with the ability to use GPIO to connect additional hardware. * Bare-Metal Raspberry Pi: Runs without any operating system using the Circle library. * Microsoft Windows: Does not have DART or Network emulation. +* WORK IN PROGRESS: Experimental version using SDL. SDL has experimental support for Wayland. + It may also provide a single source usable on Windows & Linux, including Networking. Work is still needed to clean the code. There are probably bugs, and there is certainly diagnostic code. diff --git a/src/memu/CMakeLists.txt b/src/memu/CMakeLists.txt index 67269fa..4f1312c 100644 --- a/src/memu/CMakeLists.txt +++ b/src/memu/CMakeLists.txt @@ -45,84 +45,6 @@ if("${TARGET}" STREQUAL "Pico") ${CMAKE_CURRENT_LIST_DIR}/win_pico.c ) -elseif("${TARGET}" STREQUAL "XWin") - set (xwin_src - ${CMAKE_CURRENT_LIST_DIR}/cfx2.c - ${CMAKE_CURRENT_LIST_DIR}/common.c - ${CMAKE_CURRENT_LIST_DIR}/config.c - ${CMAKE_CURRENT_LIST_DIR}/cpm.c - ${CMAKE_CURRENT_LIST_DIR}/ctc.c - ${CMAKE_CURRENT_LIST_DIR}/dart.c - ${CMAKE_CURRENT_LIST_DIR}/diag.c - ${CMAKE_CURRENT_LIST_DIR}/dirmap.c - ${CMAKE_CURRENT_LIST_DIR}/dirt_unix.c - ${CMAKE_CURRENT_LIST_DIR}/dis.c - ${CMAKE_CURRENT_LIST_DIR}/joy_lin.c - ${CMAKE_CURRENT_LIST_DIR}/kbd2.c - ${CMAKE_CURRENT_LIST_DIR}/main.c - ${CMAKE_CURRENT_LIST_DIR}/mem.c - ${CMAKE_CURRENT_LIST_DIR}/memu.c - ${CMAKE_CURRENT_LIST_DIR}/mfx.c - ${CMAKE_CURRENT_LIST_DIR}/mon.c - ${CMAKE_CURRENT_LIST_DIR}/monprom.c - ${CMAKE_CURRENT_LIST_DIR}/nfx.c - ${CMAKE_CURRENT_LIST_DIR}/printer.c - ${CMAKE_CURRENT_LIST_DIR}/rom_os.c - ${CMAKE_CURRENT_LIST_DIR}/rom_assem.c - ${CMAKE_CURRENT_LIST_DIR}/rom_basic.c - ${CMAKE_CURRENT_LIST_DIR}/rom_boot_type07.c - ${CMAKE_CURRENT_LIST_DIR}/rom_sdx_type07.c - ${CMAKE_CURRENT_LIST_DIR}/sdcard.c - ${CMAKE_CURRENT_LIST_DIR}/sdxfdc.c - ${CMAKE_CURRENT_LIST_DIR}/sid.c - ${CMAKE_CURRENT_LIST_DIR}/snd.c - ${CMAKE_CURRENT_LIST_DIR}/spec.c - ${CMAKE_CURRENT_LIST_DIR}/tape.c - ${CMAKE_CURRENT_LIST_DIR}/txtwin.c - ${CMAKE_CURRENT_LIST_DIR}/ui.c - ${CMAKE_CURRENT_LIST_DIR}/vdeb.c - ${CMAKE_CURRENT_LIST_DIR}/vdp.c - ${CMAKE_CURRENT_LIST_DIR}/vga.c - ${CMAKE_CURRENT_LIST_DIR}/vid.c - ${CMAKE_CURRENT_LIST_DIR}/win.c - ${CMAKE_CURRENT_LIST_DIR}/win_x.c - ) - - if( NOT (${CMAKE_VERSION} VERSION_LESS "3.12.0")) - - add_library(memu_src INTERFACE) - - target_include_directories(memu_src INTERFACE - ${CMAKE_CURRENT_LIST_DIR} - ) - - target_sources(memu_src INTERFACE ${xwin_src}) - - else() - cmake_minimum_required(VERSION 3.5) - - project(memu C) - - add_executable(memu-x ${xwin_src}) - - target_include_directories(memu-x PUBLIC - ${CMAKE_CURRENT_LIST_DIR} - ) - - target_compile_definitions(memu-x PUBLIC ${src_defs}) - - target_compile_options(memu-x PRIVATE -g) - target_link_options(memu-x PRIVATE -g) - - target_link_libraries(memu-x PUBLIC - Z80_emu - portaudio - X11 - m - ) - - endif () - elseif("${TARGET}" STREQUAL "FBuf") set (fbuf_src @@ -345,6 +267,87 @@ elseif("${TARGET}" STREQUAL "Win") ${CMAKE_CURRENT_LIST_DIR}/win_cir.c ) +elseif("${TARGET}" STREQUAL "SDL") + + set (sdl_src + ${CMAKE_CURRENT_LIST_DIR}/cfx2.c + ${CMAKE_CURRENT_LIST_DIR}/common.c + ${CMAKE_CURRENT_LIST_DIR}/config.c + ${CMAKE_CURRENT_LIST_DIR}/cpm.c + ${CMAKE_CURRENT_LIST_DIR}/ctc.c + ${CMAKE_CURRENT_LIST_DIR}/dart.c + ${CMAKE_CURRENT_LIST_DIR}/diag.c + ${CMAKE_CURRENT_LIST_DIR}/dirmap.c + ${CMAKE_CURRENT_LIST_DIR}/dirt_unix.c + ${CMAKE_CURRENT_LIST_DIR}/dis.c + ${CMAKE_CURRENT_LIST_DIR}/joy_lin.c + ${CMAKE_CURRENT_LIST_DIR}/kbd2.c + ${CMAKE_CURRENT_LIST_DIR}/main.c + ${CMAKE_CURRENT_LIST_DIR}/mem.c + ${CMAKE_CURRENT_LIST_DIR}/memu.c + ${CMAKE_CURRENT_LIST_DIR}/mfx.c + ${CMAKE_CURRENT_LIST_DIR}/mon.c + ${CMAKE_CURRENT_LIST_DIR}/monprom.c + ${CMAKE_CURRENT_LIST_DIR}/nfx.c + ${CMAKE_CURRENT_LIST_DIR}/printer.c + ${CMAKE_CURRENT_LIST_DIR}/rom_os.c + ${CMAKE_CURRENT_LIST_DIR}/rom_assem.c + ${CMAKE_CURRENT_LIST_DIR}/rom_basic.c + ${CMAKE_CURRENT_LIST_DIR}/rom_boot_type07.c + ${CMAKE_CURRENT_LIST_DIR}/rom_sdx_type07.c + ${CMAKE_CURRENT_LIST_DIR}/sdcard.c + ${CMAKE_CURRENT_LIST_DIR}/sdxfdc.c + ${CMAKE_CURRENT_LIST_DIR}/sid.c + ${CMAKE_CURRENT_LIST_DIR}/snd.c + ${CMAKE_CURRENT_LIST_DIR}/spec.c + ${CMAKE_CURRENT_LIST_DIR}/tape.c + ${CMAKE_CURRENT_LIST_DIR}/txtwin.c + ${CMAKE_CURRENT_LIST_DIR}/ui.c + ${CMAKE_CURRENT_LIST_DIR}/vdeb.c + ${CMAKE_CURRENT_LIST_DIR}/vdp.c + ${CMAKE_CURRENT_LIST_DIR}/vga.c + ${CMAKE_CURRENT_LIST_DIR}/vid.c + ${CMAKE_CURRENT_LIST_DIR}/win.c + ${CMAKE_CURRENT_LIST_DIR}/win_sdl.c + ) + + if( NOT (${CMAKE_VERSION} VERSION_LESS "3.12.0")) + + add_library(memu_src INTERFACE) + + target_include_directories(memu_src INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${SDL2_INCLUDE_DIRS} + ) + + target_sources(memu_src INTERFACE ${sdl_src}) + + else() + cmake_minimum_required(VERSION 3.5) + + project(memu C) + + add_executable(memu-x ${sdl_src}) + + target_include_directories(memu-x PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ${SDL2_INCLUDE_DIRS} + ) + + target_compile_definitions(memu-x PUBLIC ${src_defs}) + + target_compile_options(memu-x PRIVATE -g) + target_link_options(memu-x PRIVATE -g) + + target_link_libraries(memu-x PUBLIC + Z80_emu + portaudio + ${SDL2_LIBRARIES} + m + ) + + endif () + else() message(FATAL_ERROR "No valid target specified in MEMU/src/memu/CMakeLists.txt") diff --git a/src/memu/win.h b/src/memu/win.h index 8dce58c..50c8876 100644 --- a/src/memu/win.h +++ b/src/memu/win.h @@ -66,6 +66,16 @@ extern "C" { #endif +// Routines in win.c + +extern WIN *win_alloc (size_t size_win, size_t size_data); +extern void win_free (WIN *win); +extern void win_next (void); +extern void win_prev (void); +extern WIN * win_current (void); +extern void win_show_num (int n); + +// Version specific routines extern WIN *win_create( int width, int height, int width_scale, int height_scale, @@ -76,29 +86,12 @@ extern WIN *win_create( void (*keypress)(WIN *, int), void (*keyrelease)(WIN *, int) ); - -extern WIN *twin_create( - int width_scale, int height_scale, - const char *title, - const char *display, - const char *geometry, - void (*keypress)(WIN *, int), - void (*keyrelease)(WIN *, int), - BOOLEAN bMono - ); - -extern WIN *win_alloc (size_t size_win, size_t size_data); -extern void win_free (WIN *win); extern void win_delete (WIN *win); extern void win_colour (WIN *win, int idx, COL *clr); extern void win_refresh (WIN *win); extern int win_shifted_wk (int wk); extern void win_show (WIN *win); -extern void win_show_num (int n); -extern void win_next (void); -extern void win_prev (void); extern BOOLEAN win_active (WIN *win); -extern WIN * win_current (void); extern void win_term (void); extern void win_max_size (const char *display, int *pWth, int *pHgt); @@ -106,6 +99,9 @@ extern void win_max_size (const char *display, int *pWth, int *pHgt); A no-op on Windows, where we use separate threads. */ extern void win_handle_events(); +// Routines in txtwin.c +WIN *twin_create (int width_scale, int height_scale, const char *title, const char *display, const char *geometry, + void (*keypress)(WIN *, int), void (*keyrelease)(WIN *, int), BOOLEAN bMono); TXTBUF *tbuf_create (BOOLEAN bMono); void twin_delete (WIN *win); void twin_show (WIN *win); diff --git a/src/memu/win_sdl.c b/src/memu/win_sdl.c new file mode 100644 index 0000000..eb7d06f --- /dev/null +++ b/src/memu/win_sdl.c @@ -0,0 +1,353 @@ +/* win_sdl.c - An SDL implementation of the Window routines */ + +#include "win.h" +#include "kbd.h" +#include "common.h" +#include "types.h" +#include "diag.h" +#include + +// The Blit is also performing conversion from paletted to direct colou +// Doing this only seems to work if the scaling is 1 to 1. +// Hence disabled by default +#ifndef USE_SCALED_BLIT +#define USE_SCALED_BLIT 0 +#endif + +typedef struct st_win_sdl + { + int iWin; + int width, height; + int width_scale, height_scale; + int n_cols; + byte *data; + void (*keypress)(struct st_win *, int); + void (*keyrelease)(struct st_win *, int); + TXTBUF *tbuf; + /* Private SDL window data here */ + SDL_Window *sdl_win; + SDL_Surface *sdl_sfc; +#if USE_SCALED_BLIT + SDL_Surface *sdl_drw; +#else + uint32_t *pal; +#endif + } WIN_PRIV; + +static BOOLEAN bInit = FALSE; + +static void win_init (void) + { + if ( SDL_Init (SDL_INIT_VIDEO) < 0 ) + fatal ("SDL_Init Error: %s", SDL_GetError ()); + bInit = TRUE; + } + +WIN *win_create( + int width, int height, + int width_scale, int height_scale, + const char *title, + const char *display, + const char *geometry, + COL *col, int n_cols, + void (*keypress)(WIN *, int), + void (*keyrelease)(WIN *, int) + ) + { + if ( ! bInit ) win_init (); +#if USE_SCALED_BLIT + WIN_PRIV *win = (WIN_PRIV *) win_alloc (sizeof(WIN_PRIV), 0); +#else + WIN_PRIV *win = (WIN_PRIV *) win_alloc (sizeof(WIN_PRIV), width * height); +#endif + + win->width = width; + win->height = height; + win->width_scale = width_scale; + win->height_scale = height_scale; + win->n_cols = n_cols; + win->keypress = keypress; + win->keyrelease = keyrelease; + diag_message (DIAG_WIN_HW, "%s: (%p)", title, win); + + win->sdl_win = SDL_CreateWindow ( + title, + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + width * width_scale, height * height_scale, + SDL_WINDOW_SHOWN + ); + if ( win->sdl_win == NULL ) + fatal ("SDL error creating window %s: %s", title, SDL_GetError ()); + win->sdl_sfc = SDL_GetWindowSurface (win->sdl_win); + SDL_SetWindowData (win->sdl_win, "MEMU", win); + if ( win->sdl_sfc == NULL ) + fatal ("SDL error getting window surface %s: %s", title, SDL_GetError ()); +#if USE_SCALED_BLIT + win->sdl_drw = SDL_CreateRGBSurface (0, width, height, 8, 0, 0, 0, 0); + if ( win->sdl_drw == NULL ) + fatal ("SDL error creating drawing surface %s: %s", title, SDL_GetError ()); + win->data = win->sdl_drw->pixels; +#else + if ( win->sdl_sfc->format->palette == NULL ) + win->pal = (uint32_t *) emalloc (n_cols * sizeof (uint32_t)); + else + win->pal = NULL; +#endif + for (int i = 0; i < n_cols; ++i) + win_colour ((WIN *) win, i, &col[i]); + return (WIN *) win; + } + +void win_delete (WIN *win_pub) + { + if ( win_pub == NULL ) return; + WIN_PRIV *win = (WIN_PRIV *) win_pub; +#if USE_SCALED_BLIT + SDL_FreeSurface (win->sdl_drw); + win->data = NULL; +#else + if ( win->pal != NULL ) free (win->pal); +#endif + SDL_DestroyWindow (win->sdl_win); + win_free ((WIN *) win); + } + +void win_colour (WIN *win_pub, int idx, COL *clr) + { + WIN_PRIV *win = (WIN_PRIV *) win_pub; +#if USE_SCALED_BLIT + SDL_Color sdl_clr; + sdl_clr.r = clr->r; + sdl_clr.g = clr->g; + sdl_clr.b = clr->b; + sdl_clr.a = 0xFF; + SDL_SetPaletteColors (win->sdl_drw->format->palette, &sdl_clr, idx, 1); +#else + if ( win->pal == NULL ) + { + SDL_Color sdl_clr; + sdl_clr.r = clr->r; + sdl_clr.g = clr->g; + sdl_clr.b = clr->b; + sdl_clr.a = 0xFF; + SDL_SetPaletteColors (win->sdl_sfc->format->palette, &sdl_clr, idx, 1); + } + else + { + SDL_PixelFormat *f = win->sdl_sfc->format; + win->pal[idx] = ((clr->r >> f->Rloss) << f->Rshift) | ((clr->g >> f->Gloss) << f->Gshift) + | ((clr->b >> f->Bloss) << f->Bshift); + if ( f->Amask != 0 ) win->pal[idx] |= (0xFF >> f->Aloss) << f->Ashift; + } +#endif + } + +void win_refresh (WIN *win_pub) + { + WIN_PRIV *win = (WIN_PRIV *) win_pub; +#if USE_SCALED_BLIT + if ( SDL_BlitScaled (win->sdl_drw, NULL, win->sdl_sfc, NULL) ) + fatal ("%s: win %p: %d x %d (%d x %d)\n", SDL_GetError (), win, win->width, win->height, win->width_scale, win->height_scale); +#else + // uint8_t *pixels = win->sdl_sfc->pixels; + for (int iRow = 0; iRow < win->height; ++iRow) + { + for (int iHScl = 0; iHScl < win->height_scale; ++iHScl) + { + uint8_t *data = win->data + iRow * win->width; + uint8_t *pixels = win->sdl_sfc->pixels + (iRow * win->height_scale + iHScl) * win->sdl_sfc->pitch; + for (int iCol = 0; iCol < win->width; ++iCol) + { + uint32_t clr; + uint8_t *pclr = (uint8_t *) &clr; + if ( win->pal == NULL ) clr = *data; + else clr = win->pal[*data]; + for (int iWScl = 0; iWScl < win->width_scale; ++iWScl) + { +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + switch (win->sdl_sfc->format->BytesPerPixel) + { + case 1: + *pixels = clr; + break; + case 2: + *((uint16_t *)pixels) = clr; + break; + case 3: + pixels[0] = pclr[0]; + pixels[1] = pclr[1]; + pixels[2] = pclr[2]; + break; + case 4: + *((uint32_t *)pixels) = clr; + break; + } +#else + switch (win->sdl_sfc->format->BytesPerPixel) + { + case 1: + *pixels = pclr[4]; + break; + case 2: + *((uint16_t *)pixels) = *((uint16_t)&pclr[2]); + break; + case 3: + pixels[0] = pclr[1]; + pixels[1] = pclr[2]; + pixels[2] = pclr[3]; + break; + case 4: + *((uint32_t *)pixels) = clr; + break; + } +#endif + pixels += win->sdl_sfc->format->BytesPerPixel; + } + ++data; + } + } + } +#endif + SDL_UpdateWindowSurface (win->sdl_win); + } + +typedef struct s_kbd_map + { + uint32_t keycode; + int wk; + } KBD_MAP; + +// Entries in the following array must be in increasing order of SDLK_ value +// A bisection searrch is used to locate matches +static KBD_MAP kbd_map[] = { + {SDLK_DELETE, WK_Delete}, + {SDLK_CAPSLOCK, WK_Caps_Lock}, + {SDLK_F1, WK_F1}, + {SDLK_F2, WK_F2}, + {SDLK_F3, WK_F3}, + {SDLK_F4, WK_F4}, + {SDLK_F5, WK_F5}, + {SDLK_F6, WK_F6}, + {SDLK_F7, WK_F7}, + {SDLK_F8, WK_F8}, + {SDLK_F9, WK_F9}, + {SDLK_F10, WK_F10}, + {SDLK_F11, WK_F11}, + {SDLK_F12, WK_F12}, + {SDLK_SCROLLLOCK, WK_Scroll_Lock}, + {SDLK_PAUSE, WK_Pause}, + {SDLK_INSERT, WK_Insert}, + {SDLK_HOME, WK_Home}, + {SDLK_PAGEUP, WK_Page_Up}, + {SDLK_END, WK_End}, + {SDLK_PAGEDOWN, WK_Page_Down}, + {SDLK_RIGHT, WK_Right}, + {SDLK_LEFT, WK_Left}, + {SDLK_DOWN, WK_Down}, + {SDLK_UP, WK_Up}, + {SDLK_NUMLOCKCLEAR, WK_Num_Lock}, + {SDLK_KP_DIVIDE, WK_KP_Divide}, + {SDLK_KP_MULTIPLY, WK_KP_Multiply}, + {SDLK_KP_MINUS, WK_KP_Subtract}, + {SDLK_KP_PLUS, WK_KP_Add}, + {SDLK_KP_ENTER, WK_KP_Enter}, + {SDLK_KP_1, WK_KP_End}, + {SDLK_KP_2, WK_KP_Down}, + {SDLK_KP_3, WK_KP_Page_Down}, + {SDLK_KP_4, WK_KP_Left}, + {SDLK_KP_5, WK_KP_Middle}, + {SDLK_KP_6, WK_KP_Right}, + {SDLK_KP_7, WK_KP_Home}, + {SDLK_KP_8, WK_KP_Up}, + {SDLK_KP_9, WK_KP_Page_Up}, + {SDLK_APPLICATION, WK_Menu}, + {SDLK_SYSREQ, WK_Sys_Req}, + {SDLK_LCTRL, WK_Control_L}, + {SDLK_LSHIFT, WK_Shift_L}, + {SDLK_LALT, WK_PC_Alt_L}, + {SDLK_LGUI, WK_PC_Windows_L}, + {SDLK_RCTRL, WK_Control_R}, + {SDLK_RSHIFT, WK_Shift_R}, + {SDLK_RALT, WK_PC_Alt_R}, + {SDLK_RGUI, WK_PC_Windows_R}}; + +static int sdlkey_wk (int keycode) + { + if (( keycode > 0 ) && ( keycode < 127 )) return keycode; + int iFst = -1; + int iLst = sizeof (kbd_map) / sizeof (kbd_map[0]); + while ( (iLst - iFst) > 1 ) + { + int iNxt = (iFst + iLst) / 2; + if ( kbd_map[iNxt].keycode == keycode ) return kbd_map[iNxt].wk; + else if ( kbd_map[iNxt].keycode > keycode ) iLst = iNxt; + else iFst = iNxt; + } + return 0; + } + +void win_handle_events (void) + { + SDL_Event e; + while ( SDL_PollEvent (&e) != 0 ) + { + switch (e.type) + { + case SDL_WINDOWEVENT: + switch (e.window.event) + { + case SDL_WINDOWEVENT_CLOSE: + terminate("user closed window"); + break; + case SDL_WINDOWEVENT_EXPOSED: + win_refresh ((WIN *) SDL_GetWindowData (SDL_GetWindowFromID (e.window.windowID), "MEMU")); + break; + } + break; + case SDL_KEYDOWN: + if ( e.key.repeat == 0 ) + { + WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (SDL_GetWindowFromID (e.key.windowID), "MEMU"); + int wk = sdlkey_wk (e.key.keysym.sym); + if (wk > 0) win->keypress ((WIN *) win, wk); + } + break; + case SDL_KEYUP : + if ( e.key.repeat == 0 ) + { + WIN_PRIV *win = (WIN_PRIV *) SDL_GetWindowData (SDL_GetWindowFromID (e.key.windowID), "MEMU"); + int wk = sdlkey_wk (e.key.keysym.sym); + if (wk > 0) win->keyrelease ((WIN *) win, wk); + } + break; + } + } + } + +void win_show (WIN *win) + { + } + +BOOLEAN win_active (WIN *win) + { + return TRUE; + } + +void win_term (void) + { + } + +const SDL_DisplayMode **SDL_GetFullscreenDisplayModes(int displayID, int *count); + +void win_max_size (const char *display, int *pWth, int *pHgt) + { + if ( ! bInit ) win_init (); + SDL_Rect rect; + SDL_GetDisplayUsableBounds (0, &rect); + *pWth = rect.w; + *pHgt = rect.h; + } + +extern void kbd_chk_leds (int *mods) + { + }