1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-11 23:52:48 +00:00

SCP: Updated to current.

This commit is contained in:
Richard Cornwell 2023-05-09 12:22:10 -04:00
parent e4201d729a
commit 162b7eee94
10 changed files with 209 additions and 416 deletions

View File

@ -1,6 +1,6 @@
/* sim_console.c: simulator console I/O library
Copyright (c) 1993-2014, Robert M Supnik
Copyright (c) 1993-2022, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,15 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
30-Nov-22 RMS Made definitions of sim_os_fd_isatty consistent (Dave Bryan)
27-Sep-22 RMS Removed MacOS "Classic" and OS/2 support
Added sim_ttisatty
14-Jun-19 JDB Fixed argument passing in "sim_show_console"
01-Mar-19 JDB SET CONSOLE LOG now closes prior log before opening
27-Dec-18 JDB Added missing fall through comment in ControlHandler
18-Mar-18 RMS Fixed deboff not to close stdout or stderr (Dave Bryan)
31-Mar-15 RMS Backported parity feature from GitHub master
10-Nov-14 JDB Added -N option to SET CONSOLE LOG and SET CONSOLE DEBUG
02-Jan-14 RMS Added tab stop routines
18-Mar-12 RMS Removed unused reference to sim_switches (Dave Bryan)
07-Dec-11 MP Added sim_ttisatty to support reasonable behaviour (i.e.
@ -117,6 +126,13 @@
sim_set_noconsole_port Enable automatic WRU console polling
sim_set_stable_registers_state Declare that all registers are always stable
sim_ttinit - called once to get initial terminal state
sim_ttrun - called to put terminal into run state
sim_ttcmd - called to return terminal to command state
sim_ttclose - called once before the simulator exits
sim_ttisatty - called to determine if running interactively
sim_os_poll_kbd - poll for keyboard input
sim_os_putchar - output character to console
The first group is OS-independent; the second group is OS-dependent.
@ -177,7 +193,7 @@ int32 sim_dbg_int_char = 0; /* SIGINT char under deb
static t_bool sigint_message_issued = FALSE;
int32 sim_brk_char = 000; /* break character */
int32 sim_tt_pchar = 0x00002780;
#if defined (_WIN32) || defined (__OS2__) || (defined (__MWERKS__) && defined (macintosh))
#if defined (_WIN32)
int32 sim_del_char = '\b'; /* delete character */
#else
int32 sim_del_char = 0177;
@ -309,6 +325,10 @@ static t_stat sim_con_detach (UNIT *uptr)
return sim_set_notelnet (0, NULL);
}
/* Forward declaratations */
static t_stat sim_os_fd_isatty (int fd);
/* Set/show data structures */
static CTAB set_con_tab[] = {
@ -3736,284 +3756,6 @@ if (ch != 0177) {
return SCPE_OK;
}
/* OS/2 routines, from Bruce Ray and Holger Veit */
#elif defined (__OS2__)
#include <conio.h>
static t_stat sim_os_ttinit (void)
{
return SCPE_OK;
}
static t_stat sim_os_ttrun (void)
{
return SCPE_OK;
}
static t_stat sim_os_ttcmd (void)
{
return SCPE_OK;
}
static t_stat sim_os_ttclose (void)
{
return SCPE_OK;
}
static t_bool sim_os_fd_isatty (int fd)
{
return 1;
}
static t_stat sim_os_poll_kbd (void)
{
int c;
sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd()\n");
#if defined (__EMX__)
switch (c = _read_kbd(0,0,0)) { /* EMX has _read_kbd */
case -1: /* no char*/
return SCPE_OK;
case 0: /* char pending */
c = _read_kbd(0,1,0);
break;
default: /* got char */
break;
}
#else
if (!kbhit ())
return SCPE_OK;
c = getch();
#endif
if ((c & 0177) == sim_del_char)
c = 0177;
if ((c & 0177) == sim_int_char)
return SCPE_STOP;
if (sim_brk_char && ((c & 0177) == sim_brk_char))
return SCPE_BREAK;
return c | SCPE_KFLAG;
}
static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */
{
sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */
return TRUE; /* force a poll */
}
static t_stat sim_os_putchar (int32 c)
{
if (c != 0177) {
#if defined (__EMX__)
putchar (c);
#else
putch (c);
#endif
fflush (stdout);
}
return SCPE_OK;
}
/* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien and
Peter Schorn */
#elif defined (__MWERKS__) && defined (macintosh)
#include <console.h>
#include <Mactypes.h>
#include <string.h>
#include <sioux.h>
#include <unistd.h>
#include <siouxglobals.h>
#include <Traps.h>
#include <LowMem.h>
/* function prototypes */
Boolean SIOUXIsAppWindow(WindowPtr window);
void SIOUXDoMenuChoice(long menuValue);
void SIOUXUpdateMenuItems(void);
void SIOUXUpdateScrollbar(void);
int ps_kbhit(void);
int ps_getch(void);
extern pSIOUXWin SIOUXTextWindow;
static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */
static void updateCursor(void) {
WindowPtr window;
window = FrontWindow();
if (SIOUXIsAppWindow(window)) {
GrafPtr savePort;
Point localMouse;
GetPort(&savePort);
SetPort(window);
#if TARGET_API_MAC_CARBON
GetGlobalMouse(&localMouse);
#else
localMouse = LMGetMouseLocation();
#endif
GlobalToLocal(&localMouse);
if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) {
SetCursor(*iBeamCursorH);
}
else {
SetCursor(&qd.arrow);
}
TEIdle(SIOUXTextWindow->edit);
SetPort(savePort);
}
else {
SetCursor(&qd.arrow);
TEIdle(SIOUXTextWindow->edit);
}
return;
}
int ps_kbhit(void) {
EventRecord event;
int c;
updateCursor();
SIOUXUpdateScrollbar();
while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask |
highLevelEventMask | diskEvt, &event)) {
SIOUXHandleOneEvent(&event);
}
if (SIOUXQuitting) {
exit(1);
}
if (EventAvail(keyDownMask,&event)) {
c = event.message&charCodeMask;
if ((event.modifiers & cmdKey) && (c > 0x20)) {
GetNextEvent(keyDownMask, &event);
SIOUXHandleOneEvent(&event);
if (SIOUXQuitting) {
exit(1);
}
return false;
}
return true;
}
else {
return false;
}
}
int ps_getch(void) {
int c;
EventRecord event;
fflush(stdout);
updateCursor();
while(!GetNextEvent(keyDownMask,&event)) {
if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask |
highLevelEventMask | diskEvt, &event)) {
SIOUXUpdateScrollbar();
SIOUXHandleOneEvent(&event);
}
}
if (SIOUXQuitting) {
exit(1);
}
c = event.message&charCodeMask;
if ((event.modifiers & cmdKey) && (c > 0x20)) {
SIOUXUpdateMenuItems();
SIOUXDoMenuChoice(MenuKey(c));
}
if (SIOUXQuitting) {
exit(1);
}
return c;
}
/* Note that this only works if the call to sim_ttinit comes before any output to the console */
static t_stat sim_os_ttinit (void)
{
int i;
sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_ttinit()\n");
/* this blank will later be replaced by the number of characters */
char title[50] = " ";
unsigned char ptitle[50];
SIOUXSettings.autocloseonquit = TRUE;
SIOUXSettings.asktosaveonclose = FALSE;
SIOUXSettings.showstatusline = FALSE;
SIOUXSettings.columns = 80;
SIOUXSettings.rows = 40;
SIOUXSettings.toppixel = 42;
SIOUXSettings.leftpixel = 6;
iBeamCursorH = GetCursor(iBeamCursor);
strlcat(title, sim_name, sizeof(title));
strlcat(title, " Simulator", sizeof(title));
title[0] = strlen(title) - 1; /* Pascal string done */
for (i = 0; i <= title[0]; i++) { /* copy to unsigned char */
ptitle[i] = title[i];
}
SIOUXSetTitle(ptitle);
return SCPE_OK;
}
static t_stat sim_os_ttrun (void)
{
return SCPE_OK;
}
static t_stat sim_os_ttcmd (void)
{
return SCPE_OK;
}
static t_stat sim_os_ttclose (void)
{
return SCPE_OK;
}
static t_bool sim_os_fd_isatty (int fd)
{
return 1;
}
static t_stat sim_os_poll_kbd (void)
{
int c;
sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd()\n");
if (!ps_kbhit ())
return SCPE_OK;
c = ps_getch();
if ((c & 0177) == sim_del_char)
c = 0177;
if ((c & 0177) == sim_int_char)
return SCPE_STOP;
if (sim_brk_char && ((c & 0177) == sim_brk_char))
return SCPE_BREAK;
return c | SCPE_KFLAG;
}
static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */
{
sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */
return TRUE; /* force a poll */
}
static t_stat sim_os_putchar (int32 c)
{
if (c != 0177) {
putchar (c);
fflush (stdout);
}
return SCPE_OK;
}
/* BSD UNIX routines */
#elif defined (BSDTTY)
#include <sgtty.h>

View File

@ -1,6 +1,6 @@
/* sim_console.h: simulator console I/O library headers
Copyright (c) 1993-2014, Robert M Supnik
Copyright (c) 1993-2022, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-Sep-22 RMS Added sim_ttisatty
14-Dec-14 JDB [4.0] Added sim_*_char externals
02-Jan-14 RMS Added tab stop routines
17-Jan-11 MP Added buffered line capabilities
22-Jun-06 RMS Implemented SET/SHOW PCHAR

View File

@ -23,6 +23,17 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
06-Jun-22 RMS Deprecated UNIT_TEXT, deleted UNIT_RAW
10-Mar-22 JDB Modified REG macros to fix "stringizing" problem
12-Nov-21 JDB Added UNIT_EXTEND dynamic flag
17-Mar-21 JDB Added UNIT_PIPE dynamic flag
16-Feb-21 JDB Added "stride" to REG to support arrays of structures
Modified REG macros to initialize strides
21-Jan-21 JDB Added "size" and "maxval" fields to the REG structure
Modified REG macros to initialize access sizes
09-Nov-20 RMS More V4.X compatibility hooks (Mark Pizzolato)
26-Oct-19 RMS Removed MTAB_VAL definition
23-Jun-17 RMS Added #include sim_rev.h (Mark Pizzolato)
25-Sep-16 RMS Removed KBD_WAIT and friends
08-Mar-16 RMS Added shutdown invisible switch
24-Dec-14 JDB Added T_ADDR_FMT
@ -93,7 +104,7 @@
sim_devices[] array of pointers to simulated devices
sim_PC pointer to saved PC register descriptor
sim_interval simulator interval to next event
sim_stop_messages[SCPE_BASE]
sim_stop_messages[SCPE_BASE]
array of pointers to stop messages
sim_instr() instruction execution routine
sim_load() binary loader routine
@ -125,6 +136,9 @@ extern int sim_vax_snprintf(char *buf, size_t buf_size, const char *fmt, ...);
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <setjmp.h>
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
@ -152,7 +166,7 @@ extern int sim_vax_snprintf(char *buf, size_t buf_size, const char *fmt, ...);
#define USE_REGEX 1
#endif
#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC)
#if defined(__DECC)
#define __FUNCTION__ __FILE__
#endif
@ -207,7 +221,7 @@ typedef __int32 int32;
typedef unsigned __int8 uint8;
typedef unsigned __int16 uint16;
typedef unsigned __int32 uint32;
#else
#else
/* All modern/standard compiler environments */
/* any other environment needa a special case above */
#include <stdint.h>
@ -316,7 +330,7 @@ typedef uint32 t_addr;
#define SIM_INLINE inline
#define SIM_NOINLINE __attribute__ ((noinline))
#else
#define SIM_INLINE
#define SIM_INLINE
#define SIM_NOINLINE
#endif
@ -513,7 +527,7 @@ struct DEVICE {
/* mem size routine */
char *lname; /* logical name */
t_stat (*help)(FILE *st, DEVICE *dptr,
UNIT *uptr, int32 flag, const char *cptr);
UNIT *uptr, int32 flag, const char *cptr);
/* help */
t_stat (*attach_help)(FILE *st, DEVICE *dptr,
UNIT *uptr, int32 flag, const char *cptr);
@ -647,8 +661,10 @@ struct UNIT {
#define UNIT_WLK 0100000 /* hardware write lock */
#define UNIT_WPRT (UNIT_WLK|UNIT_RO)/* write protect */
/* Unused/meaningless flags */
#define UNIT_TEXT 0000000 /* text mode - no effect */
/* Deleted or deprecated */
// #define UNIT_RAW 000000 /* raw mode */
#define UNIT_TEXT 000000 /* text mode */
#define UNIT_UFMASK_31 (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF_31) - 1))
#define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1))
@ -892,10 +908,10 @@ struct MEMFILE {
size_t pos; /* data used */
};
/*
/*
The following macros exist to help populate structure contents
They are dependent on the declaration order of the fields
They are dependent on the declaration order of the fields
of the structures they exist to populate.
*/
@ -965,14 +981,14 @@ struct MEMFILE {
This specifies a arrayed register whose elements are array[0].field,
array[1].field, etc.
All above macro names from ORDATA through XRDATA have two additional
precisely related macros. The first it the above name with D appended and
has an additional parameter which is a quoted string describing the purpose
of the register which is visible when displaying HELP about a device's
All above macro names from ORDATA through XRDATA have two additional
precisely related macros. The first it the above name with D appended and
has an additional parameter which is a quoted string describing the purpose
of the register which is visible when displaying HELP about a device's
registers. The second related macro has the above name with DF appended
and has two additional parameters. The first parameter is the register
and has two additional parameters. The first parameter is the register
description, and the second is the name of a BITFIELD array which describes
the fields in the register's contents. This info is used to display the
the fields in the register's contents. This info is used to display the
register contents (via EXAMINE) along with the detailed bitfield data.
For example:
@ -997,7 +1013,7 @@ struct MEMFILE {
will occur before stringization, resulting in the wrong register name.
3. Additional REG initialization values may be supplied after a macro
invocation. If present, these begin with the "flags" field which is,
invocation. If present, these begin with the "flags" field which is,
for the most part, not specified as a macro parameter.
4. The URDATA macro is obsolescent and present for backward-compatibility.
@ -1014,8 +1030,8 @@ struct MEMFILE {
#define _RegCheck(nm,loc,rdx,wd,off,dep,desc,flds,qptr,siz,elesiz,macro) \
nm, (loc), (rdx), (wd), (off), (dep), (desc), (flds), (qptr), (siz), sizeof(*(loc)), (elesiz), #macro
/* Generic Register declaration for all fields.
If the register structure is extended, this macro will be retained and a
/* Generic Register declaration for all fields.
If the register structure is extended, this macro will be retained and a
new internal macro will be provided that populates the new register structure */
#define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \
_RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATA),(fl)

View File

@ -163,7 +163,7 @@ extern "C" {
#define ETH_MIN_PACKET 60 /* minimum ethernet packet size */
#define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */
#define ETH_MAX_JUMBO_FRAME 65536 /* maximum ethernet jumbo frame size (or Offload Segment Size) */
#define ETH_MAX_DEVICE 20 /* maximum ethernet devices */
#define ETH_MAX_DEVICE 40 /* maximum ethernet devices */
#define ETH_CRC_SIZE 4 /* ethernet CRC size */
#define ETH_FRAME_SIZE (ETH_MAX_PACKET+ETH_CRC_SIZE) /* ethernet maximum frame size */
#define ETH_MIN_JUMBO_FRAME ETH_MAX_PACKET /* Threshold size for Jumbo Frame Processing */

View File

@ -1,6 +1,6 @@
/*************************************************************************
* *
* Copyright (c) 2007-2022 Howard M. Harte. *
* Copyright (c) 2007-2023 Howard M. Harte. *
* https://github.com/hharte *
* *
* Permission is hereby granted, free of charge, to any person obtaining *
@ -55,7 +55,12 @@ DISK_INFO *diskOpenEx(FILE *fileref, uint32 isVerbose, DEVICE *device, uint32 de
{
DISK_INFO *myDisk = NULL;
myDisk = (DISK_INFO *)malloc(sizeof(DISK_INFO));
myDisk = (DISK_INFO*)calloc(1, sizeof(DISK_INFO));
if (myDisk == NULL) {
sim_printf("%s: %s(): memory allocation failure.\n", __FILE__, __FUNCTION__);
return NULL;
}
myDisk->file = fileref;
myDisk->device = device;
myDisk->debugmask = debugmask;
@ -765,6 +770,12 @@ t_stat trackWrite(DISK_INFO *myDisk,
*/
dataLen = sectorLen + 1;
sectorData = (uint8 *)malloc(dataLen);
if (sectorData == NULL) {
sim_printf("%s: %s(): memory allocation failure.\n", __FILE__, __FUNCTION__);
return SCPE_MEM;
}
memset(sectorData, fillbyte, dataLen);
sectorData[0] = SECT_RECORD_NORM;

View File

@ -31,7 +31,7 @@
#define SIM_MAJOR 4
#endif
#ifndef SIM_MINOR
#define SIM_MINOR 0
#define SIM_MINOR 1
#endif
#ifndef SIM_PATCH
#define SIM_PATCH 0

View File

@ -2370,7 +2370,36 @@ return r;
Implementation notes:
1. Erase gaps are currently supported only in SIMH (MTUF_F_STD) tape format.
1. Erase gaps are currently supported only in standard and extended SIMH
tape formats.
2. Metadatum reads either succeed and return 1 or fail and return 0. If a
read fails, and "ferror" returns false, then it must have read into the
end of the file (only these three outcomes are possible).
3. The area scan is necessary for tape image integrity to ensure that a data
record straddling the end of the erasure is truncated appropriately. The
scan is guaranteed to succeed only if it begins at a valid metadatum. If
it begins in the middle of a previously overwritten data record, then the
scan will interpret old data values as tape formatting markers. The data
record sanity checks attempt to recover from this situation, but it is
still possible to corrupt valid data that follows an erasure of an
invalid area (e.g., if the leading and trailing length words happen
to match but actually represent previously recorded data rather than
record metadata). If an application knows that the erased area will
not contain valid formatting, the "sim_tape_erase" routine should be used
instead, as it erases without first scanning the area.
4. Truncating an existing data record corresponds to overwriting part of a
record on a real tape. Reading such a record on a real drive would
produce CRC errors, due to the lost portion. In simulation, we could
change a good record (Class 0) to a bad record (Class 8). However, this
is not possible for private or reserved record classes, as that would
change the classification (consider that a private class that had
been ignored would not be once it had been truncated and changed to Class
8). Given that there is no good general solution, we do not modify
classes for truncated records, as reading a partially erased record is an
"all bets are off" operation.
*/
static t_stat tape_erase_fwd (UNIT *uptr, t_mtrlnt gap_size)

View File

@ -1,6 +1,6 @@
/* sim_timer.c: simulator timer library
Copyright (c) 1993-2010, Robert M Supnik
Copyright (c) 1993-2022, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,11 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-Sep-22 RMS Removed OS/2 and Mac "Classic" support
01-Feb-21 JDB Added cast for down-conversion
22-May-17 RMS Hacked for V4.0 CONST compatibility
23-Nov-15 RMS Fixed calibration lost path to reinitialize timer
28-Mar-15 RMS Revised to use sim_printf
21-Oct-11 MP Fixed throttling in several ways:
- Sleep for the observed clock tick size while throttling
- Recompute the throttling wait once every 10 seconds
@ -536,92 +541,6 @@ return 0;
}
#endif
#elif defined (__OS2__)
/* OS/2 routines, from Bruce Ray */
const t_bool rtc_avail = FALSE;
uint32 sim_os_msec (void)
{
return 0;
}
void sim_os_sleep (unsigned int sec)
{
}
uint32 sim_os_ms_sleep_init (void)
{
return 0;
}
uint32 sim_os_ms_sleep (unsigned int msec)
{
return 0;
}
/* Metrowerks CodeWarrior Macintosh routines, from Ben Supnik */
#elif defined (__MWERKS__) && defined (macintosh)
#include <Timer.h>
#include <Mactypes.h>
#include <sioux.h>
#include <unistd.h>
#include <siouxglobals.h>
#define NANOS_PER_MILLI 1000000
#define MILLIS_PER_SEC 1000
const t_bool rtc_avail = TRUE;
uint32 sim_os_msec (void)
{
unsigned long long micros;
UnsignedWide macMicros;
unsigned long millis;
Microseconds (&macMicros);
micros = *((unsigned long long *) &macMicros);
millis = micros / 1000LL;
return (uint32) millis;
}
void sim_os_sleep (unsigned int sec)
{
sleep (sec);
}
uint32 sim_os_ms_sleep_init (void)
{
return _compute_minimum_sleep ();
}
uint32 sim_os_ms_sleep (unsigned int milliseconds)
{
uint32 stime = sim_os_msec ();
struct timespec treq;
treq.tv_sec = milliseconds / MILLIS_PER_SEC;
treq.tv_nsec = (milliseconds % MILLIS_PER_SEC) * NANOS_PER_MILLI;
(void) nanosleep (&treq, NULL);
return sim_os_msec () - stime;
}
#if defined(NEED_CLOCK_GETTIME)
int clock_gettime(int clk_id, struct timespec *tp)
{
struct timeval cur;
if (clk_id != CLOCK_REALTIME)
return -1;
gettimeofday (&cur, NULL);
tp->tv_sec = cur.tv_sec;
tp->tv_nsec = cur.tv_usec*1000;
return 0;
}
#endif
#else
/* UNIX routines */

View File

@ -313,17 +313,19 @@ static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
*/
#define EVENT_REDRAW 1 /* redraw event for SDL */
#define EVENT_CLOSE 2 /* close event for SDL */
#define EVENT_CURSOR 3 /* new cursor for SDL */
#define EVENT_WARP 4 /* warp mouse position for SDL */
#define EVENT_DRAW 5 /* draw/blit region for SDL */
#define EVENT_SHOW 6 /* show SDL capabilities */
#define EVENT_OPEN 7 /* vid_open request */
#define EVENT_EXIT 8 /* program exit */
#define EVENT_SCREENSHOT 9 /* produce screenshot of video window */
#define EVENT_BEEP 10 /* audio beep */
#define MAX_EVENTS 20 /* max events in queue */
#define EVENT_REDRAW 1 /* redraw event for SDL */
#define EVENT_CLOSE 2 /* close event for SDL */
#define EVENT_CURSOR 3 /* new cursor for SDL */
#define EVENT_WARP 4 /* warp mouse position for SDL */
#define EVENT_DRAW 5 /* draw/blit region for SDL */
#define EVENT_SHOW 6 /* show SDL capabilities */
#define EVENT_OPEN 7 /* vid_open request */
#define EVENT_EXIT 8 /* program exit */
#define EVENT_SCREENSHOT 9 /* produce screenshot of video window */
#define EVENT_BEEP 10 /* audio beep */
#define EVENT_FULLSCREEN 11 /* fullscreen */
#define EVENT_SIZE 12 /* set window size */
#define MAX_EVENTS 20 /* max events in queue */
typedef struct {
SIM_KEY_EVENT events[MAX_EVENTS];
@ -372,6 +374,7 @@ t_bool vid_key_state[SDL_NUM_SCANCODES];
VID_DISPLAY *next;
t_bool vid_blending;
SDL_Rect *vid_dst_last;
SDL_Rect vid_rect;
uint32 *vid_data_last;
};
@ -515,7 +518,7 @@ SDL_SetHint (SDL_HINT_RENDER_DRIVER, "software");
SDL_SetHint (SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1");
#endif
status = SDL_Init (SDL_INIT_VIDEO);
status = SDL_Init (SDL_INIT_EVENTS);
if (status) {
fprintf (stderr, "SDL Video subsystem can't initialize: %s\n", SDL_GetError ());
@ -539,8 +542,10 @@ while (1) {
if (event.type == SDL_USEREVENT) {
if (event.user.code == EVENT_EXIT)
break;
if (event.user.code == EVENT_OPEN)
if (event.user.code == EVENT_OPEN) {
SDL_Init (SDL_INIT_VIDEO);
vid_video_events ((VID_DISPLAY *)event.user.data1);
}
else {
if (event.user.code == EVENT_SHOW)
vid_show_video_event ();
@ -1615,6 +1620,26 @@ if (SDL_SemWait (vid_mouse_events.sem) == 0) {
}
}
void vid_set_window_size (VID_DISPLAY *vptr, int32 w, int32 h)
{
SDL_Event user_event;
vptr->vid_rect.h = h;
vptr->vid_rect.w = w;
user_event.type = SDL_USEREVENT;
user_event.user.windowID = vptr->vid_windowID;
user_event.user.code = EVENT_SIZE;
user_event.user.data1 = NULL;
user_event.user.data2 = NULL;
#if defined (SDL_MAIN_AVAILABLE)
while (SDL_PushEvent (&user_event) < 0)
sim_os_ms_sleep (100);
#else
SDL_SetWindowSize(vptr->vid_window, w, h);
#endif
}
t_bool vid_is_fullscreen_window (VID_DISPLAY *vptr)
{
return SDL_GetWindowFlags (vptr->vid_window) & SDL_WINDOW_FULLSCREEN_DESKTOP;
@ -1627,10 +1652,22 @@ return vid_is_fullscreen_window (&vid_first);
t_stat vid_set_fullscreen_window (VID_DISPLAY *vptr, t_bool flag)
{
SDL_Event user_event;
user_event.type = SDL_USEREVENT;
user_event.user.windowID = vptr->vid_windowID;
user_event.user.code = EVENT_FULLSCREEN;
user_event.user.data1 = (flag) ? vptr : NULL;
user_event.user.data2 = NULL;
#if defined (SDL_MAIN_AVAILABLE)
while (SDL_PushEvent (&user_event) < 0)
sim_os_ms_sleep (100);
#else
if (flag)
SDL_SetWindowFullscreen (vptr->vid_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
else
SDL_SetWindowFullscreen (vptr->vid_window, 0);
#endif
return SCPE_OK;
}
@ -1659,6 +1696,12 @@ else {
r->x = 0;
r->y = (h - r->h) / 2;
}
if (vptr->vid_flags & SIM_VID_IGNORE_VBAR) {
r->w = w;
r->h = h;
r->x = 0;
r->y = 0;
}
}
void vid_update (VID_DISPLAY *vptr)
@ -1769,6 +1812,11 @@ if (!vptr->vid_texture) {
vptr->vid_format = SDL_AllocFormat (SDL_PIXELFORMAT_ARGB8888);
if (vptr->vid_flags & SIM_VID_RESIZABLE) {
SDL_SetWindowResizable(vptr->vid_window, SDL_TRUE);
SDL_RenderSetIntegerScale(vptr->vid_renderer, SDL_TRUE);
}
SDL_StopTextInput ();
vptr->vid_windowID = SDL_GetWindowID (vptr->vid_window);
@ -2033,22 +2081,27 @@ while (vid_active) {
case SDL_WINDOWEVENT_EXPOSED:
vid_update (vptr);
break;
default:
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "Did not handle window event: %d - %s\n", event.window.event, windoweventtypes[event.window.event]);
break;
}
}
break;
case SDL_USEREVENT:
/* There are 9 user events generated */
/* EVENT_REDRAW to update the display */
/* EVENT_DRAW to update a region in the display texture */
/* EVENT_SHOW to display the current SDL video capabilities */
/* EVENT_CURSOR to change the current cursor */
/* EVENT_WARP to warp the cursor position */
/* EVENT_OPEN to open a new window */
/* EVENT_CLOSE to wake up this thread and let */
/* it notice vid_active has changed */
/* EVENT_SCREENSHOT to take a screenshot */
/* EVENT_BEEP to emit a beep sound */
/* There are 11 user events generated */
/* EVENT_REDRAW to update the display */
/* EVENT_DRAW to update a region in the display texture */
/* EVENT_SHOW to display the current SDL video capabilities */
/* EVENT_CURSOR to change the current cursor */
/* EVENT_WARP to warp the cursor position */
/* EVENT_OPEN to open a new window */
/* EVENT_CLOSE to wake up this thread and let */
/* it notice vid_active has changed */
/* EVENT_SCREENSHOT to take a screenshot */
/* EVENT_BEEP to emit a beep sound */
/* EVENT_SIZE to change screen size */
/* EVENT_FULLSCREEN to change fullscreen */
while (vid_active && event.user.code) {
/* Handle Beep first since it isn't a window oriented event */
if (event.user.code == EVENT_BEEP) {
@ -2059,7 +2112,7 @@ while (vid_active) {
if (event.user.code != EVENT_OPEN) {
vptr = vid_get_event_window (&event, event.user.windowID);
if (vptr == NULL) {
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "vid_thread() - Ignored event not bound to a window\n");
sim_printf ("vid_thread() - Ignored event not bound to a window\n");
event.user.code = 0; /* Mark as done */
break;
}
@ -2104,6 +2157,17 @@ while (vid_active) {
vid_screenshot_event ();
event.user.code = 0; /* Mark as done */
}
if (event.user.code == EVENT_SIZE) {
SDL_SetWindowSize (vptr->vid_window, vptr->vid_rect.w, vptr->vid_rect.h);
event.user.code = 0; /* Mark as done */
}
if (event.user.code == EVENT_FULLSCREEN) {
if (event.user.data1 != NULL)
SDL_SetWindowFullscreen (vptr->vid_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
else
SDL_SetWindowFullscreen (vptr->vid_window, 0);
event.user.code = 0; /* Mark as done */
}
if (event.user.code == EVENT_BEEP) {
vid_beep_event ();
event.user.code = 0; /* Mark as done */
@ -2341,6 +2405,8 @@ for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
if (vid_active) {
SDL_RendererInfo info;
info.name = "";
for (vptr = &vid_first; vptr != NULL; vptr = vptr->next) {
if (vptr->vid_active_window) {
SDL_GetRendererInfo (vptr->vid_renderer, &info);
@ -2820,6 +2886,11 @@ void vid_set_cursor_position_window (VID_DISPLAY *vptr, int32 x, int32 y)
return;
}
void vid_set_window_size (VID_DISPLAY *vptr, int32 w, int32 h)
{
return;
}
const char *vid_key_name (uint32 key)
{
return "";

View File

@ -189,6 +189,8 @@ typedef struct key_event SIM_KEY_EVENT;
t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags);
#define SIM_VID_INPUTCAPTURED 1 /* Mouse and Keyboard input captured (calling */
/* code responsible for cursor display in video) */
#define SIM_VID_IGNORE_VBAR 2 /* ignore video buffer aspect ratio */
#define SIM_VID_RESIZABLE 4 /* video screen is resizable */
typedef void (*VID_QUIT_CALLBACK)(void);
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback);
typedef void (*VID_GAMEPAD_CALLBACK)(int, int, int);
@ -214,6 +216,7 @@ t_stat vid_set_fullscreen (t_bool flag);
extern int vid_active;
void vid_set_cursor_position (int32 x, int32 y); /* cursor position (set by calling code) */
void vid_set_window_size (VID_DISPLAY *vptr, int32 x, int32 y); /* window size (set by calling code) */
t_stat vid_open_window (VID_DISPLAY **vptr, DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags);
t_stat vid_close_window (VID_DISPLAY *vptr);