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