From 723e34275aa0f79db15deac29ac52892b93a9d6d Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Wed, 21 Jun 2023 06:40:01 -0400 Subject: [PATCH] Add missing header. --- minichlink/terminalhelp.h | 159 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 minichlink/terminalhelp.h diff --git a/minichlink/terminalhelp.h b/minichlink/terminalhelp.h new file mode 100644 index 0000000..38cbcf1 --- /dev/null +++ b/minichlink/terminalhelp.h @@ -0,0 +1,159 @@ +// terminalhelp from mini-rv32ima. +#ifndef _TERMINALHELP_H +#define _TERMINALHELP_H + +#include <stdint.h> + +// Provides the following: +static void CaptureKeyboardInput() __attribute__((used)); +static void ResetKeyboardInput() __attribute__((used)); +static uint64_t GetTimeMicroseconds() __attribute__((used)); +static int ReadKBByte() __attribute__((used)); +static int IsKBHit() __attribute__((used)); + +#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32) + +#include <windows.h> +#include <conio.h> + +#define strtoll _strtoi64 + +static void CaptureKeyboardInput() +{ + system(""); // Poorly documented tick: Enable VT100 Windows mode. +} + +static void ResetKeyboardInput() +{ +} + +static uint64_t GetTimeMicroseconds() +{ + static LARGE_INTEGER lpf; + LARGE_INTEGER li; + + if( !lpf.QuadPart ) + QueryPerformanceFrequency( &lpf ); + + QueryPerformanceCounter( &li ); + return ((uint64_t)li.QuadPart * 1000000LL) / (uint64_t)lpf.QuadPart; +} + + +static int IsKBHit() +{ + return _kbhit(); +} + +static int ReadKBByte() +{ + // This code is kind of tricky, but used to convert windows arrow keys + // to VT100 arrow keys. + static int is_escape_sequence = 0; + int r; + if( is_escape_sequence == 1 ) + { + is_escape_sequence++; + return '['; + } + + r = _getch(); + + if( is_escape_sequence ) + { + is_escape_sequence = 0; + switch( r ) + { + case 'H': return 'A'; // Up + case 'P': return 'B'; // Down + case 'K': return 'D'; // Left + case 'M': return 'C'; // Right + case 'G': return 'H'; // Home + case 'O': return 'F'; // End + default: return r; // Unknown code. + } + } + else + { + switch( r ) + { + case 13: return 10; //cr->lf + case 224: is_escape_sequence = 1; return 27; // Escape arrow keys + default: return r; + } + } +} + +#else + +#include <sys/ioctl.h> +#include <termios.h> +#undef BS0 +#undef BS1 +#include <unistd.h> +#include <signal.h> +#include <sys/time.h> + +static void CtrlC() +{ + exit( 0 ); +} + +// Override keyboard, so we can capture all keyboard input for the VM. +static void CaptureKeyboardInput() +{ + // Hook exit, because we want to re-enable keyboard. + atexit(ResetKeyboardInput); + signal(SIGINT, CtrlC); + + struct termios term; + tcgetattr(0, &term); + term.c_lflag &= ~(ICANON | ECHO); // Disable echo as well + tcsetattr(0, TCSANOW, &term); +} + +static void ResetKeyboardInput() +{ + // Re-enable echo, etc. on keyboard. + struct termios term; + tcgetattr(0, &term); + term.c_lflag |= ICANON | ECHO; + tcsetattr(0, TCSANOW, &term); +} + +static uint64_t GetTimeMicroseconds() +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return tv.tv_usec + ((uint64_t)(tv.tv_sec)) * 1000000LL; +} + +static int is_eofd; + +static int ReadKBByte() +{ + if( is_eofd ) return 0xffffffff; + char rxchar = 0; + int rread = read(fileno(stdin), (char*)&rxchar, 1); + + if( rread > 0 ) // Tricky: getchar can't be used with arrow keys. + return rxchar; + else + return -1; +} + +static int IsKBHit() +{ + if( is_eofd ) return -1; + int byteswaiting; + ioctl(0, FIONREAD, &byteswaiting); + if( !byteswaiting && write( fileno(stdin), 0, 0 ) != 0 ) { is_eofd = 1; return -1; } // Is end-of-file for + return !!byteswaiting; +} + + +#endif + + +#endif + -- GitLab