~vertigo/forthbox

b64a40cb1ceaff6f00ec0737d8ccfe825c660ab1 — Samuel A. Falvo II 4 months ago d17c16c
Reuse Oberon-07 PS/2 encoder with attribution
4 files changed, 263 insertions(+), 5 deletions(-)

M emulator/CMakeLists.txt
M emulator/main.c
A emulator/sdl-ps2.c
A emulator/sdl-ps2.h
M emulator/CMakeLists.txt => emulator/CMakeLists.txt +1 -1
@@ 3,7 3,7 @@ include(CTest)

include_directories(${SDL2_INCLUDE_DIRS})

add_executable(fbemu main.c virtual_kia.c)
add_executable(fbemu main.c virtual_kia.c sdl-ps2.c)
target_link_libraries(fbemu lib65816a ${SDL2_LIBRARIES})

add_executable(test_kia test_kia.c virtual_kia.c)

M emulator/main.c => emulator/main.c +11 -4
@@ 15,6 15,7 @@

#include <SDL2/SDL.h>
#include "virtual_kia.h"
#include "sdl-ps2.h"

#define MAX_DISK		8



@@ 170,13 171,19 @@ static int video_event(void)
	SDL_Event event;

	while (SDL_PollEvent(&event)) {
		if (event.type == SDL_QUIT)
		switch(event.type) {
		case SDL_QUIT:
			return -1;
		if (event.type == SDL_TEXTINPUT) {
			key = *event.text.text;
			printf("Typed '%c'\n", key);

		case SDL_KEYDOWN: case SDL_KEYUP:
			uint8_t ps2_bytes[MAX_PS2_CODE_LEN];
			bool down = event.key.state == SDL_PRESSED;
			int len = ps2_encode(event.key.keysym.scancode, down, ps2_bytes);
			for(int i = 0; i < len; i++) kia_push(g_kia1, ps2_bytes[i]);
			break;
		}
	}

	return 0;
}


A emulator/sdl-ps2.c => emulator/sdl-ps2.c +240 -0
@@ 0,0 1,240 @@
/**
 * @file Translate SDL scancodes to PS/2 codeset 2 scancodes.
 *
 * This file was captured on 2024-05-14 from:
 * https://raw.githubusercontent.com/pdewacht/oberon-risc-emu/master/src/sdl-ps2.c
 *
 * No modifications have been made to this file, except for replacing
 * the single-line file header with this copyright block.
 *
 * This file is licensed as follows:
 *
 * Copyright © 2014 Peter De Wachter
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.*
 */

#include <SDL.h>
#include "sdl-ps2.h"

struct k_info {
  unsigned char code;
  unsigned char type;
};

enum k_type {
  K_UNKNOWN = 0,
  K_NORMAL,
  K_EXTENDED,
  K_NUMLOCK_HACK,
  K_SHIFT_HACK,
};

static struct k_info keymap[SDL_NUM_SCANCODES];

int ps2_encode(int sdl_scancode, bool make, uint8_t out[static MAX_PS2_CODE_LEN]) {
  int i = 0;
  struct k_info info = keymap[sdl_scancode];
  switch (info.type) {
    case K_UNKNOWN: {
      break;
    }

    case K_NORMAL: {
      if (!make) {
        out[i++] = 0xF0;
      }
      out[i++] = info.code;
      break;
    }

    case K_EXTENDED: {
      out[i++] = 0xE0;
      if (!make) {
        out[i++] = 0xF0;
      }
      out[i++] = info.code;
      break;
    }

    case K_NUMLOCK_HACK: {
      // This assumes Num Lock is always active
      if (make) {
        // fake shift press
        out[i++] = 0xE0;
        out[i++] = 0x12;
        out[i++] = 0xE0;
        out[i++] = info.code;
      } else {
        out[i++] = 0xE0;
        out[i++] = 0xF0;
        out[i++] = info.code;
        // fake shift release
        out[i++] = 0xE0;
        out[i++] = 0xF0;
        out[i++] = 0x12;
      }
      break;
    }

    case K_SHIFT_HACK: {
      SDL_Keymod mod = SDL_GetModState();
      if (make) {
        // fake shift release
        if (mod & KMOD_LSHIFT) {
          out[i++] = 0xE0;
          out[i++] = 0xF0;
          out[i++] = 0x12;
        }
        if (mod & KMOD_RSHIFT) {
          out[i++] = 0xE0;
          out[i++] = 0xF0;
          out[i++] = 0x59;
        }
        out[i++] = 0xE0;
        out[i++] = info.code;
      } else {
        out[i++] = 0xE0;
        out[i++] = 0xF0;
        out[i++] = info.code;
        // fake shift press
        if (mod & KMOD_RSHIFT) {
          out[i++] = 0xE0;
          out[i++] = 0x59;
        }
        if (mod & KMOD_LSHIFT) {
          out[i++] = 0xE0;
          out[i++] = 0x12;
        }
      }
      break;
    }
  }
  return i;
}

static struct k_info keymap[SDL_NUM_SCANCODES] = {
  [SDL_SCANCODE_A] = { 0x1C, K_NORMAL },
  [SDL_SCANCODE_B] = { 0x32, K_NORMAL },
  [SDL_SCANCODE_C] = { 0x21, K_NORMAL },
  [SDL_SCANCODE_D] = { 0x23, K_NORMAL },
  [SDL_SCANCODE_E] = { 0x24, K_NORMAL },
  [SDL_SCANCODE_F] = { 0x2B, K_NORMAL },
  [SDL_SCANCODE_G] = { 0x34, K_NORMAL },
  [SDL_SCANCODE_H] = { 0x33, K_NORMAL },
  [SDL_SCANCODE_I] = { 0x43, K_NORMAL },
  [SDL_SCANCODE_J] = { 0x3B, K_NORMAL },
  [SDL_SCANCODE_K] = { 0x42, K_NORMAL },
  [SDL_SCANCODE_L] = { 0x4B, K_NORMAL },
  [SDL_SCANCODE_M] = { 0x3A, K_NORMAL },
  [SDL_SCANCODE_N] = { 0x31, K_NORMAL },
  [SDL_SCANCODE_O] = { 0x44, K_NORMAL },
  [SDL_SCANCODE_P] = { 0x4D, K_NORMAL },
  [SDL_SCANCODE_Q] = { 0x15, K_NORMAL },
  [SDL_SCANCODE_R] = { 0x2D, K_NORMAL },
  [SDL_SCANCODE_S] = { 0x1B, K_NORMAL },
  [SDL_SCANCODE_T] = { 0x2C, K_NORMAL },
  [SDL_SCANCODE_U] = { 0x3C, K_NORMAL },
  [SDL_SCANCODE_V] = { 0x2A, K_NORMAL },
  [SDL_SCANCODE_W] = { 0x1D, K_NORMAL },
  [SDL_SCANCODE_X] = { 0x22, K_NORMAL },
  [SDL_SCANCODE_Y] = { 0x35, K_NORMAL },
  [SDL_SCANCODE_Z] = { 0x1A, K_NORMAL },

  [SDL_SCANCODE_1] = { 0x16, K_NORMAL },
  [SDL_SCANCODE_2] = { 0x1E, K_NORMAL },
  [SDL_SCANCODE_3] = { 0x26, K_NORMAL },
  [SDL_SCANCODE_4] = { 0x25, K_NORMAL },
  [SDL_SCANCODE_5] = { 0x2E, K_NORMAL },
  [SDL_SCANCODE_6] = { 0x36, K_NORMAL },
  [SDL_SCANCODE_7] = { 0x3D, K_NORMAL },
  [SDL_SCANCODE_8] = { 0x3E, K_NORMAL },
  [SDL_SCANCODE_9] = { 0x46, K_NORMAL },
  [SDL_SCANCODE_0] = { 0x45, K_NORMAL },

  [SDL_SCANCODE_RETURN]    = { 0x5A, K_NORMAL },
  [SDL_SCANCODE_ESCAPE]    = { 0x76, K_NORMAL },
  [SDL_SCANCODE_BACKSPACE] = { 0x66, K_NORMAL },
  [SDL_SCANCODE_TAB]       = { 0x0D, K_NORMAL },
  [SDL_SCANCODE_SPACE]     = { 0x29, K_NORMAL },

  [SDL_SCANCODE_MINUS]        = { 0x4E, K_NORMAL },
  [SDL_SCANCODE_EQUALS]       = { 0x55, K_NORMAL },
  [SDL_SCANCODE_LEFTBRACKET]  = { 0x54, K_NORMAL },
  [SDL_SCANCODE_RIGHTBRACKET] = { 0x5B, K_NORMAL },
  [SDL_SCANCODE_BACKSLASH]    = { 0x5D, K_NORMAL },
  [SDL_SCANCODE_NONUSHASH]    = { 0x5D, K_NORMAL },  // same key as BACKSLASH

  [SDL_SCANCODE_SEMICOLON]  = { 0x4C, K_NORMAL },
  [SDL_SCANCODE_APOSTROPHE] = { 0x52, K_NORMAL },
  [SDL_SCANCODE_GRAVE]      = { 0x0E, K_NORMAL },
  [SDL_SCANCODE_COMMA]      = { 0x41, K_NORMAL },
  [SDL_SCANCODE_PERIOD]     = { 0x49, K_NORMAL },
  [SDL_SCANCODE_SLASH]      = { 0x4A, K_NORMAL },

  [SDL_SCANCODE_F1]  = { 0x05, K_NORMAL },
  [SDL_SCANCODE_F2]  = { 0x06, K_NORMAL },
  [SDL_SCANCODE_F3]  = { 0x04, K_NORMAL },
  [SDL_SCANCODE_F4]  = { 0x0C, K_NORMAL },
  [SDL_SCANCODE_F5]  = { 0x03, K_NORMAL },
  [SDL_SCANCODE_F6]  = { 0x0B, K_NORMAL },
  [SDL_SCANCODE_F7]  = { 0x83, K_NORMAL },
  [SDL_SCANCODE_F8]  = { 0x0A, K_NORMAL },
  [SDL_SCANCODE_F9]  = { 0x01, K_NORMAL },
  [SDL_SCANCODE_F10] = { 0x09, K_NORMAL },
  [SDL_SCANCODE_F11] = { 0x78, K_NORMAL },
  [SDL_SCANCODE_F12] = { 0x07, K_NORMAL },

  // Most of the keys below are not used by Oberon

  [SDL_SCANCODE_INSERT]   = { 0x70, K_NUMLOCK_HACK },
  [SDL_SCANCODE_HOME]     = { 0x6C, K_NUMLOCK_HACK },
  [SDL_SCANCODE_PAGEUP]   = { 0x7D, K_NUMLOCK_HACK },
  [SDL_SCANCODE_DELETE]   = { 0x71, K_NUMLOCK_HACK },
  [SDL_SCANCODE_END]      = { 0x69, K_NUMLOCK_HACK },
  [SDL_SCANCODE_PAGEDOWN] = { 0x7A, K_NUMLOCK_HACK },
  [SDL_SCANCODE_RIGHT]    = { 0x74, K_NUMLOCK_HACK },
  [SDL_SCANCODE_LEFT]     = { 0x6B, K_NUMLOCK_HACK },
  [SDL_SCANCODE_DOWN]     = { 0x72, K_NUMLOCK_HACK },
  [SDL_SCANCODE_UP]       = { 0x75, K_NUMLOCK_HACK },

  [SDL_SCANCODE_KP_DIVIDE]   = { 0x4A, K_SHIFT_HACK },
  [SDL_SCANCODE_KP_MULTIPLY] = { 0x7C, K_NORMAL },
  [SDL_SCANCODE_KP_MINUS]    = { 0x7B, K_NORMAL },
  [SDL_SCANCODE_KP_PLUS]     = { 0x79, K_NORMAL },
  [SDL_SCANCODE_KP_ENTER]    = { 0x5A, K_EXTENDED },
  [SDL_SCANCODE_KP_1]        = { 0x69, K_NORMAL },
  [SDL_SCANCODE_KP_2]        = { 0x72, K_NORMAL },
  [SDL_SCANCODE_KP_3]        = { 0x7A, K_NORMAL },
  [SDL_SCANCODE_KP_4]        = { 0x6B, K_NORMAL },
  [SDL_SCANCODE_KP_5]        = { 0x73, K_NORMAL },
  [SDL_SCANCODE_KP_6]        = { 0x74, K_NORMAL },
  [SDL_SCANCODE_KP_7]        = { 0x6C, K_NORMAL },
  [SDL_SCANCODE_KP_8]        = { 0x75, K_NORMAL },
  [SDL_SCANCODE_KP_9]        = { 0x7D, K_NORMAL },
  [SDL_SCANCODE_KP_0]        = { 0x70, K_NORMAL },
  [SDL_SCANCODE_KP_PERIOD]   = { 0x71, K_NORMAL },

  [SDL_SCANCODE_NONUSBACKSLASH] = { 0x61, K_NORMAL },
  [SDL_SCANCODE_APPLICATION]    = { 0x2F, K_EXTENDED },

  [SDL_SCANCODE_LCTRL]  = { 0x14, K_NORMAL },
  [SDL_SCANCODE_LSHIFT] = { 0x12, K_NORMAL },
  [SDL_SCANCODE_LALT]   = { 0x11, K_NORMAL },
  [SDL_SCANCODE_LGUI]   = { 0x1F, K_EXTENDED },
  [SDL_SCANCODE_RCTRL]  = { 0x14, K_EXTENDED },
  [SDL_SCANCODE_RSHIFT] = { 0x59, K_NORMAL },
  [SDL_SCANCODE_RALT]   = { 0x11, K_EXTENDED },
  [SDL_SCANCODE_RGUI]   = { 0x27, K_EXTENDED },
};


A emulator/sdl-ps2.h => emulator/sdl-ps2.h +11 -0
@@ 0,0 1,11 @@
#ifndef SDL_PS2_H
#define SDL_PS2_H

#include <stdbool.h>
#include <stdint.h>

#define MAX_PS2_CODE_LEN 8

int ps2_encode(int sdl_scancode, bool make, uint8_t out[static MAX_PS2_CODE_LEN]);

#endif  // SDL_PS2_H