AltairZ80: Adds SOL20 and VDM1 devices

This PR adds support for the Processor Technology VDM-1 display adapter and Sol-20 computer system. The VDM-1 was integrated into the Sol-20 but has been separated out into its own device.

This PR adds the following devices to the AltairZ80 simulator:

VDM1 - Processor Technology VDM-1 display adapter
SOL20 - Processor Technology SOL20 with SOLOS ROMs
SOL20K - SOL20 Keyboard (callback from VDM1)
SOL20T - SOL20 Tape (reads/writes cassette file images)
SOL20S - SOL20 Serial Port (TMXR capable)
SOL20P - SOL20 Printer Port (TMXR capable)
This commit is contained in:
Patrick Linstruth 2023-03-07 18:45:48 -08:00 committed by Paul Koning
parent 825a505083
commit cf9fac614c
7 changed files with 3113 additions and 30 deletions

View file

@ -77,6 +77,12 @@ extern DEVICE pmmi_dev;
extern DEVICE hayes_dev;
extern DEVICE mmd_dev;
extern DEVICE mmdm_dev;
extern DEVICE sol20_dev;
extern DEVICE sol20k_dev;
extern DEVICE sol20t_dev;
extern DEVICE sol20s_dev;
extern DEVICE sol20p_dev;
extern DEVICE vdm1_dev;
extern DEVICE cromfdc_dev;
extern DEVICE wd179x_dev;
@ -141,6 +147,13 @@ DEVICE *sim_devices[] = {
&djhdc_dev,
&mmd_dev,
&mmdm_dev,
/* Processor Technology Devices */
&sol20_dev,
&sol20k_dev,
&sol20t_dev,
&sol20s_dev,
&sol20p_dev,
&vdm1_dev,
/* MITS 88-2SIO */
&m2sio0_dev,
&m2sio1_dev,

708
AltairZ80/s100_vdm1.c Normal file
View file

@ -0,0 +1,708 @@
/* s100_vdm1.c: Processor Technology VDM-1
Copyright (c) 2023, Patrick Linstruth
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the author shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
VDM1 - Processor Technology VDM-1
*/
#include "altairz80_defs.h"
#include "sim_video.h"
#define VDM1_MARGIN (5)
#define VDM1_CHAR_XSIZE (9) /* character x size */
#define VDM1_CHAR_YSIZE (13) /* character y size */
#define VDM1_COLS (64) /* number of colums */
#define VDM1_LINES (16) /* number of rows */
#define VDM1_XSIZE (VDM1_COLS * VDM1_CHAR_XSIZE + VDM1_MARGIN * 2) /* visible width */
#define VDM1_YSIZE (VDM1_LINES * VDM1_CHAR_YSIZE + VDM1_MARGIN * 2) /* visible height */
#define VDM1_PIXELS (VDM1_XSIZE * VDM1_YSIZE) /* total number of pixels */
#define VDM1_MEM_BASE 0xcc00
#define VDM1_MEM_SIZE 1024
#define VDM1_MEM_MASK (1024 - 1)
#define VDM1_IO_BASE 0xfe
#define VDM1_IO_SIZE 1
/*
** PORT ASSIGNMENTS
*/
#define VDM1_DSTAT 0xfe /* VDM DISPLAY PARAMETER PORT */
#define VDM1_DSTAT_RMSK 0xf0 /* START ROW MASK */
#define VDM1_DSTAT_CMSK 0x0f /* START COL MASK */
/*
** Public VID_DISPLAY for other devices that may want
** to access the video display directly, such as keyboard
** events.
*/
VID_DISPLAY *vdm1_vptr = NULL;
t_stat (*vdm1_kb_callback)(SIM_KEY_EVENT *kev) = NULL;
static uint8 vdm1_ram[VDM1_MEM_SIZE];
static uint8 vdm1_dstat = 0x00;
static t_bool vdm1_dirty = FALSE;
static t_bool vdm1_reverse = FALSE;
static t_bool vdm1_blink = FALSE;
static uint16 vdm1_counter = 0;
static t_bool vdm1_active = FALSE;
static uint32 vdm1_surface[VDM1_PIXELS];
static uint32 vdm1_palette[2];
enum vdm1_switch {VDM1_NONE,
VDM1_NORMAL, VDM1_REVERSE, VDM1_BLINK, VDM1_NOBLINK,
VDM1_MODE1, VDM1_MODE2, VDM1_MODE3, VDM1_MODE4
};
static enum vdm1_switch vdm1_ctrl = VDM1_MODE4;
static enum vdm1_switch vdm1_cursor = VDM1_NOBLINK;
static enum vdm1_switch vdm1_display = VDM1_NORMAL;
const uint8 charset[128][VDM1_CHAR_YSIZE] =
{{0x00,0x7f,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x7f,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x7f,0x00,0x00,0x00},
{0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x7f,0x00,0x00,0x00},
{0x00,0x20,0x10,0x08,0x04,0x3e,0x10,0x08,0x04,0x02,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x63,0x55,0x49,0x55,0x63,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x00,0x01,0x02,0x04,0x48,0x50,0x60,0x40,0x00,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x41,0x7f,0x14,0x14,0x77,0x00,0x00,0x00},
{0x00,0x10,0x20,0x7c,0x22,0x11,0x01,0x01,0x01,0x01,0x00,0x00,0x00},
{0x00,0x00,0x08,0x04,0x02,0x7f,0x02,0x04,0x08,0x00,0x00,0x00,0x00},
{0x00,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00},
{0x00,0x00,0x08,0x08,0x08,0x49,0x2a,0x1c,0x08,0x00,0x00,0x00,0x00},
{0x00,0x08,0x08,0x2a,0x1c,0x08,0x49,0x2a,0x1c,0x08,0x00,0x00,0x00},
{0x00,0x00,0x08,0x10,0x20,0x7f,0x20,0x10,0x08,0x00,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x63,0x55,0x49,0x55,0x63,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x49,0x41,0x41,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x41,0x41,0x7f,0x41,0x41,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x1c,0x2a,0x49,0x49,0x4f,0x41,0x41,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x4f,0x49,0x49,0x2a,0x1c,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x79,0x49,0x49,0x2a,0x1c,0x00,0x00,0x00},
{0x00,0x1c,0x2a,0x49,0x49,0x79,0x41,0x41,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x00,0x11,0x0a,0x04,0x4a,0x51,0x60,0x40,0x00,0x00,0x00,0x00},
{0x00,0x3e,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x63,0x00,0x00,0x00},
{0x00,0x01,0x01,0x01,0x01,0x7f,0x01,0x01,0x01,0x01,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x22,0x14,0x08,0x14,0x22,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x1c,0x1c,0x08,0x08,0x08,0x08,0x00,0x00,0x00},
{0x00,0x3c,0x42,0x42,0x40,0x30,0x08,0x08,0x00,0x08,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x7f,0x41,0x41,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x7f,0x49,0x49,0x49,0x79,0x41,0x41,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x41,0x41,0x79,0x49,0x49,0x49,0x7f,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x41,0x41,0x4f,0x49,0x49,0x49,0x7f,0x00,0x00,0x00},
{0x00,0x7f,0x49,0x49,0x49,0x4f,0x41,0x41,0x41,0x7f,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x00},
{0x00,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x14,0x14,0x14,0x7f,0x14,0x7f,0x14,0x14,0x14,0x00,0x00,0x00},
{0x00,0x08,0x3f,0x48,0x48,0x3e,0x09,0x09,0x7e,0x08,0x00,0x00,0x00},
{0x00,0x20,0x51,0x22,0x04,0x08,0x10,0x22,0x45,0x02,0x00,0x00,0x00},
{0x00,0x38,0x44,0x44,0x28,0x10,0x29,0x46,0x46,0x39,0x00,0x00,0x00},
{0x00,0x0c,0x0c,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x00,0x00,0x00},
{0x00,0x10,0x08,0x04,0x04,0x04,0x04,0x04,0x08,0x10,0x00,0x00,0x00},
{0x00,0x00,0x08,0x49,0x2a,0x1c,0x2a,0x49,0x08,0x00,0x00,0x00,0x00},
{0x00,0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x10,0x20,0x00},
{0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00},
{0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x43,0x45,0x49,0x51,0x61,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x08,0x18,0x28,0x08,0x08,0x08,0x08,0x08,0x3e,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x01,0x02,0x1c,0x20,0x40,0x40,0x7f,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x01,0x01,0x1e,0x01,0x01,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x02,0x06,0x0a,0x12,0x22,0x42,0x7f,0x02,0x02,0x00,0x00,0x00},
{0x00,0x7f,0x40,0x40,0x7c,0x02,0x01,0x01,0x42,0x3c,0x00,0x00,0x00},
{0x00,0x1e,0x20,0x40,0x40,0x7e,0x41,0x41,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x7f,0x41,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x41,0x41,0x3e,0x41,0x41,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x41,0x41,0x3f,0x01,0x01,0x02,0x3c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x10,0x20,0x00},
{0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x10,0x08,0x04,0x02,0x01,0x02,0x04,0x08,0x10,0x00,0x00,0x00},
{0x00,0x1e,0x21,0x21,0x01,0x06,0x08,0x08,0x00,0x08,0x00,0x00,0x00},
{0x00,0x1e,0x21,0x4d,0x55,0x55,0x5e,0x40,0x20,0x1e,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x41,0x7f,0x41,0x41,0x41,0x00,0x00,0x00},
{0x00,0x7e,0x21,0x21,0x21,0x3e,0x21,0x21,0x21,0x7e,0x00,0x00,0x00},
{0x00,0x1e,0x21,0x40,0x40,0x40,0x40,0x40,0x21,0x1e,0x00,0x00,0x00},
{0x00,0x7c,0x22,0x21,0x21,0x21,0x21,0x21,0x22,0x7c,0x00,0x00,0x00},
{0x00,0x7f,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7f,0x00,0x00,0x00},
{0x00,0x7f,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00},
{0x00,0x1e,0x21,0x40,0x40,0x40,0x4f,0x41,0x21,0x1e,0x00,0x00,0x00},
{0x00,0x41,0x41,0x41,0x41,0x7f,0x41,0x41,0x41,0x41,0x00,0x00,0x00},
{0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3e,0x00,0x00,0x00},
{0x00,0x1f,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00},
{0x00,0x41,0x42,0x44,0x48,0x50,0x68,0x44,0x42,0x41,0x00,0x00,0x00},
{0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7f,0x00,0x00,0x00},
{0x00,0x41,0x63,0x55,0x49,0x49,0x41,0x41,0x41,0x41,0x00,0x00,0x00},
{0x00,0x41,0x61,0x51,0x49,0x45,0x43,0x41,0x41,0x41,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x41,0x41,0x41,0x22,0x1c,0x00,0x00,0x00},
{0x00,0x7e,0x41,0x41,0x41,0x7e,0x40,0x40,0x40,0x40,0x00,0x00,0x00},
{0x00,0x1c,0x22,0x41,0x41,0x41,0x49,0x45,0x22,0x1d,0x00,0x00,0x00},
{0x00,0x7e,0x41,0x41,0x41,0x7e,0x48,0x44,0x42,0x41,0x00,0x00,0x00},
{0x00,0x3e,0x41,0x40,0x40,0x3e,0x01,0x01,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x7f,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00},
{0x00,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x3e,0x00,0x00,0x00},
{0x00,0x41,0x41,0x41,0x22,0x22,0x14,0x14,0x08,0x08,0x00,0x00,0x00},
{0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x55,0x63,0x41,0x00,0x00,0x00},
{0x00,0x41,0x41,0x22,0x14,0x08,0x14,0x22,0x41,0x41,0x00,0x00,0x00},
{0x00,0x41,0x41,0x22,0x14,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00},
{0x00,0x7f,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x7f,0x00,0x00,0x00},
{0x00,0x3c,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x00,0x00,0x00},
{0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x00,0x00,0x00},
{0x00,0x3c,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x3c,0x00,0x00,0x00},
{0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00},
{0x00,0x18,0x18,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3c,0x02,0x3e,0x42,0x42,0x3d,0x00,0x00,0x00},
{0x00,0x40,0x40,0x40,0x5c,0x62,0x42,0x42,0x62,0x5c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x40,0x42,0x3c,0x00,0x00,0x00},
{0x00,0x02,0x02,0x02,0x3a,0x46,0x42,0x42,0x46,0x3a,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3c,0x42,0x7e,0x40,0x40,0x3c,0x00,0x00,0x00},
{0x00,0x0c,0x12,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3a,0x46,0x42,0x46,0x3a,0x02,0x02,0x42,0x3c},
{0x00,0x40,0x40,0x40,0x5c,0x62,0x42,0x42,0x42,0x42,0x00,0x00,0x00},
{0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x06,0x02,0x02,0x02,0x02,0x02,0x02,0x22,0x1c},
{0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x68,0x44,0x42,0x00,0x00,0x00},
{0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x49,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x5c,0x62,0x42,0x42,0x42,0x42,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x5c,0x62,0x42,0x42,0x62,0x5c,0x40,0x40,0x40},
{0x00,0x00,0x00,0x00,0x3a,0x46,0x42,0x42,0x46,0x3a,0x02,0x02,0x02},
{0x00,0x00,0x00,0x00,0x5c,0x62,0x40,0x40,0x40,0x40,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3c,0x42,0x30,0x0c,0x42,0x3c,0x00,0x00,0x00},
{0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x10,0x12,0x0c,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x46,0x3a,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x41,0x49,0x49,0x49,0x49,0x36,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x42,0x24,0x18,0x18,0x24,0x42,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x46,0x3a,0x02,0x42,0x3c},
{0x00,0x00,0x00,0x00,0x7e,0x04,0x08,0x10,0x20,0x7e,0x00,0x00,0x00},
{0x00,0x0e,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x0e,0x00,0x00,0x00},
{0x00,0x08,0x08,0x08,0x00,0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00},
{0x00,0x18,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x18,0x00,0x00,0x00},
{0x00,0x30,0x49,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x24,0x49,0x12,0x24,0x49,0x12,0x24,0x49,0x12,0x00,0x00,0x00}};
/* Debugging Bitmaps */
#define DBG_REG 0x0001 /* registers */
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap);
extern t_stat set_membase(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
extern t_stat exdep_cmd(int32 flag, CONST char *cptr);
static t_stat vdm1_svc(UNIT *uptr);
static t_stat vdm1_reset(DEVICE *dptr);
static t_stat vdm1_boot(int32 unitno, DEVICE *dptr);
static t_stat vdm1_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
static int32 vdm1_io(const int32 port, const int32 io, const int32 data);
static int32 vdm1_mem(int32 addr, int32 rw, int32 data);
static const char *vdm1_description(DEVICE *dptr);
static void vdm1_refresh(void);
static void vdm1_render(void);
static void vdm1_render_char(uint8 byte, uint8 x, uint8 y);
static t_stat vdm1_set_ctrl(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
static t_stat vdm1_show_ctrl(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
static t_stat vdm1_set_cursor(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
static t_stat vdm1_show_cursor(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
static t_stat vdm1_set_display(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
static t_stat vdm1_show_display(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
/* VDM1 data structures
vdm1_dev VDM1 device descriptor
vdm1_unit VDM1 unit descriptor
vdm1_reg VDM1 register list
*/
typedef struct {
PNP_INFO pnp; /* Must be first */
} VDM1_CTX;
static VDM1_CTX vdm1_ctx = {{VDM1_MEM_BASE, VDM1_MEM_SIZE, VDM1_IO_BASE, VDM1_IO_SIZE}};
UNIT vdm1_unit = {
UDATA (&vdm1_svc, 0, 0), 25000
};
REG vdm1_reg[] = {
{ HRDATAD (DSTAT, vdm1_dstat, 8, "VDM-1 display parameter register"), },
{ HRDATAD (DIRTY, vdm1_dirty, 1, "VDM-1 dirty register"), },
{ HRDATAD (BLINK, vdm1_blink, 1, "VDM-1 blink register"), },
{ NULL }
};
DEBTAB vdm1_debug[] = {
{ "REG", DBG_REG, "Register activity" },
{ "VIDEO", SIM_VID_DBG_VIDEO, "Video activity" },
{ 0 }
};
MTAB vdm1_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
&set_iobase, &show_iobase, NULL, "VDM-1 base I/O address" },
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
&set_membase, &show_membase, NULL, "VDM-1 base memory address" },
{ MTAB_XTD|MTAB_VDV, 0, "CTRL", "CTRL",
&vdm1_set_ctrl, &vdm1_show_ctrl, NULL, "VDM-1 control character switches" },
{ MTAB_XTD|MTAB_VDV, 0, "CURSOR", "CURSOR",
&vdm1_set_cursor, &vdm1_show_cursor, NULL, "VDM-1 cursor switches" },
{ MTAB_XTD|MTAB_VDV, 0, "DISPLAY", "DISPLAY",
&vdm1_set_display, &vdm1_show_display, NULL, "VDM-1 display switches" },
{ 0 }
};
DEVICE vdm1_dev = {
"VDM1", &vdm1_unit, vdm1_reg, vdm1_mod,
1, 16, 16, 1, 16, 8,
NULL, NULL, &vdm1_reset,
&vdm1_boot, NULL, NULL,
&vdm1_ctx, DEV_DEBUG | DEV_DIS | DEV_DISABLE, 0,
vdm1_debug, NULL, NULL, &vdm1_help, NULL, NULL,
&vdm1_description
};
/* VDM1 routines
vdm1_svc process event
vdm1_reset process reset
*/
t_stat vdm1_svc(UNIT *uptr)
{
SIM_KEY_EVENT kev;
vdm1_counter++;
/* Handle blink */
if ((vdm1_counter % 10 == 0) && (vdm1_cursor == VDM1_BLINK)) {
vdm1_blink = !vdm1_blink;
vdm1_dirty = TRUE;
}
if (vdm1_dirty) {
vdm1_refresh();
vdm1_dirty = TRUE;
}
if (vdm1_kb_callback != NULL) {
if (vid_poll_kb(&kev) == SCPE_OK) {
(*vdm1_kb_callback)(&kev);
}
}
sim_activate_after_abs(uptr, uptr->wait); // 25ms refresh rate
return SCPE_OK;
}
t_stat vdm1_reset(DEVICE *dptr)
{
VDM1_CTX *xptr;
t_stat r;
int i;
xptr = (VDM1_CTX *) dptr->ctxt;
if (dptr->flags & DEV_DIS) {
sim_map_resource(xptr->pnp.mem_base, xptr->pnp.mem_size, RESOURCE_TYPE_MEMORY, &vdm1_mem, "vdm1", TRUE);
sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, &vdm1_io, "vdm1", TRUE);
sim_cancel(&vdm1_unit);
if (vdm1_active) {
vdm1_active = FALSE;
return vid_close();
}
return SCPE_OK;
}
sim_map_resource(xptr->pnp.mem_base, xptr->pnp.mem_size, RESOURCE_TYPE_MEMORY, &vdm1_mem, "vdm1", FALSE);
sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, &vdm1_io, "vdm1", FALSE);
if (!vdm1_active) {
r = vid_open_window(&vdm1_vptr, &vdm1_dev, "Display", VDM1_XSIZE, VDM1_YSIZE, SIM_VID_IGNORE_VBAR | SIM_VID_RESIZABLE); /* video buffer size */
if (r != SCPE_OK) {
return r;
}
vid_set_window_size(vdm1_vptr, 800, 600);
vdm1_palette[0] = vid_map_rgb_window(vdm1_vptr, 0x00, 0x00, 0x00);
vdm1_palette[1] = vid_map_rgb_window(vdm1_vptr, 0x00, 0xFF, 0x30);
for (i = 0; i < VDM1_PIXELS; i++) {
vdm1_surface[i] = vdm1_palette[0];
}
vdm1_active = TRUE;
}
sim_activate_after_abs(&vdm1_unit, 25);
return SCPE_OK;
}
static t_stat vdm1_boot(int32 unitno, DEVICE *dptr)
{
exdep_cmd(EX_D, "-m 0 MVI A,0");
exdep_cmd(EX_D, "-m 2 OUT 0FEH");
exdep_cmd(EX_D, "-m 4 MVI C,0");
exdep_cmd(EX_D, "-m 6 MVI B,0");
exdep_cmd(EX_D, "-m 8 LXI H,0CC00H");
exdep_cmd(EX_D, "-m B DCR B");
exdep_cmd(EX_D, "-m C MOV M,B");
exdep_cmd(EX_D, "-m D INX H");
exdep_cmd(EX_D, "-m E MOV A,H");
exdep_cmd(EX_D, "-m F CPI 0D0H");
exdep_cmd(EX_D, "-m 11 JNZ 000BH");
exdep_cmd(EX_D, "-m 14 DCX H");
exdep_cmd(EX_D, "-m 15 MOV A,H");
exdep_cmd(EX_D, "-m 16 ORA A");
exdep_cmd(EX_D, "-m 17 JNZ 0012H");
exdep_cmd(EX_D, "-m 1A INR C");
exdep_cmd(EX_D, "-m 1B MOV B,C");
exdep_cmd(EX_D, "-m 1C JMP 0008H");
*((int32 *) sim_PC->loc) = 0x0000;
return SCPE_OK;
}
static int32 vdm1_io(const int32 port, const int32 io, const int32 data) {
int32 result = 0xff;
if (io == 1) { /* OUT */
if (port == VDM1_DSTAT) {
vdm1_dstat = data & 0xff;
}
}
return result;
}
/*
* VDM-1 1K Video Memory (16 x 64 characters)
*/
static int32 vdm1_mem(int32 addr, int32 rw, int32 data)
{
if (rw == 0) {
data = vdm1_ram[addr & VDM1_MEM_MASK];
}
else {
vdm1_ram[addr & VDM1_MEM_MASK] = data;
vdm1_dirty = TRUE;
}
return data;
}
t_stat vdm1_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
fprintf(st, "\nThe VDM-1 has several switches that control the video display:\n\n");
fprintf(st, "SET VDM1 CTRL=MODEx\n");
fprintf(st, "MODE1 - All control characters suppressed. Only cursor blocks\n");
fprintf(st, " are displayed. CR and VT enabled.\n");
fprintf(st, "MODE2 - Control characters blanked. CR and VT enabled.\n");
fprintf(st, "MODE3 - Control characters displayable. CR and VT enabled.\n");
fprintf(st, "MODE4 - Control characters displayable. CR and VT disabled. (default)\n\n");
fprintf(st, "SET VDM1 CURSOR=NONE,BLINK,NOBLINK\n");
fprintf(st, "NONE - All cursors suppressed.\n");
fprintf(st, "BLINK - Blinking cursor.\n");
fprintf(st, "NOBLINK - Non-blinking cursor. (default)\n\n");
fprintf(st, "SET VDM1 DISPLAY=NONE,NORMAL,REVERSE\n");
fprintf(st, "NONE - No display.\n");
fprintf(st, "NORMAL - Normal video. (default)\n");
fprintf(st, "REVERSE - Reverse video.\n\n");
fprintf(st, "VDM-1 test program displays all characters on the screen:\n");
fprintf(st, "BOOT VDM1\n\n");
return SCPE_OK;
}
const char *vdm1_description (DEVICE *dptr)
{
return "Processor Technology VDM-1 Display";
}
/*
* Draw and refresh the screen in the video window
*/
static void vdm1_refresh() {
if (vdm1_active) {
vdm1_render();
vid_draw_window(vdm1_vptr, VDM1_MARGIN, VDM1_MARGIN, VDM1_XSIZE, VDM1_YSIZE, vdm1_surface);
vid_refresh_window(vdm1_vptr);
}
}
/*
* The VDM-1 display is make up of 16 64-character rows. Each character occupies
* 1 byte in memory from CC00-CFFF.
*/
static void vdm1_render()
{
uint8 x,y,s,c,c1;
int addr = 0;
t_bool eol_blank = FALSE;
t_bool eos_blank = FALSE;
addr += (vdm1_dstat & VDM1_DSTAT_CMSK) * VDM1_COLS;
s = (vdm1_dstat & VDM1_DSTAT_RMSK) >> 4; /* Shadowing */
for (y = 0; y < VDM1_LINES; y++) {
for (x = 0; x < VDM1_COLS; x++) {
c = vdm1_ram[addr++];
c1 = c & 0x7f;
/* EOL and EOS blanking */
if (c1 == 0x0d && (vdm1_ctrl == VDM1_MODE2 || vdm1_ctrl == VDM1_MODE3)) { // CR
eol_blank = TRUE;
}
else if (c1 == 0x0b && (vdm1_ctrl == VDM1_MODE2 || vdm1_ctrl == VDM1_MODE3)) { // VT
eos_blank = TRUE;
}
/* Blanking control */
if (vdm1_display == VDM1_NONE || eol_blank || eos_blank || y < s) {
c = ' ';
}
/* Control character suppression */
if ((c1 < 0x20 || c1 == 0x7f) && (vdm1_ctrl == VDM1_MODE1 || vdm1_ctrl == VDM1_MODE2)) {
c = ' ';
}
vdm1_render_char(c, x, y);
if (addr == VDM1_MEM_SIZE) {
addr = 0;
}
}
}
}
/*
* The VDM-1 rendered characters one scan line at a time.
* The simulator renders an entire character at a time by
* rendering each character in a rectangle area in the
* video surface buffer.
*/
static void vdm1_render_char(uint8 byte, uint8 x, uint8 y)
{
uint8 rx,ry,c;
int start,pixel;
start = (x * VDM1_CHAR_XSIZE) + (VDM1_XSIZE * VDM1_CHAR_YSIZE * y);
for (ry = 0; ry < VDM1_CHAR_YSIZE; ry++) {
pixel = start + (VDM1_XSIZE * ry);
c = charset[byte & 0x7f][ry];
if (!vdm1_blink && byte & 0x80) {
c = ~(c & 0xff);
}
if (vdm1_display == VDM1_REVERSE) {
c = ~(c & 0xff);
}
for (rx = 0; rx < VDM1_CHAR_XSIZE - 1; rx++) {
vdm1_surface[pixel++] = vdm1_palette[c & (0x80 >> rx) ? !vdm1_reverse : vdm1_reverse];
}
vdm1_surface[pixel++] = vdm1_palette[(c & 0x80) ? !vdm1_reverse : vdm1_reverse];
}
}
static t_stat vdm1_set_ctrl(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (!cptr) return SCPE_IERR;
if (!strlen(cptr)) return SCPE_ARG;
/* this assumes that the parameter has already been upcased */
if (!strncmp(cptr, "MODE1", strlen(cptr))) {
vdm1_ctrl = VDM1_MODE1;
} else if (!strncmp(cptr, "MODE2", strlen(cptr))) {
vdm1_ctrl = VDM1_MODE2;
} else if (!strncmp(cptr, "MODE3", strlen(cptr))) {
vdm1_ctrl = VDM1_MODE3;
} else if (!strncmp(cptr, "MODE4", strlen(cptr))) {
vdm1_ctrl = VDM1_MODE4;
} else {
return SCPE_ARG;
}
vdm1_dirty = TRUE;
return SCPE_OK;
}
static t_stat vdm1_show_ctrl(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (!st) return SCPE_IERR;
fprintf(st, "CTRL=");
switch (vdm1_ctrl) {
case VDM1_MODE1:
fprintf(st, "MODE1");
break;
case VDM1_MODE2:
fprintf(st, "MODE2");
break;
case VDM1_MODE3:
fprintf(st, "MODE3");
break;
case VDM1_MODE4:
fprintf(st, "MODE4");
break;
default:
fprintf(st, "UNKNOWN");
break;
}
return SCPE_OK;
}
static t_stat vdm1_set_cursor(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (!cptr) return SCPE_IERR;
if (!strlen(cptr)) return SCPE_ARG;
/* this assumes that the parameter has already been upcased */
if (!strncmp(cptr, "NONE", strlen(cptr))) {
vdm1_cursor = VDM1_NONE;
} else if (!strncmp(cptr, "BLINK", strlen(cptr))) {
vdm1_cursor = VDM1_BLINK;
} else if (!strncmp(cptr, "NOBLINK", strlen(cptr))) {
vdm1_cursor = VDM1_NOBLINK;
vdm1_blink = FALSE;
} else {
return SCPE_ARG;
}
vdm1_dirty = TRUE;
return SCPE_OK;
}
static t_stat vdm1_show_cursor(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (!st) return SCPE_IERR;
fprintf(st, "CURSOR=");
switch (vdm1_cursor) {
case VDM1_NONE:
fprintf(st, "NONE");
break;
case VDM1_BLINK:
fprintf(st, "BLINK");
break;
case VDM1_NOBLINK:
fprintf(st, "NOBLINK");
break;
default:
fprintf(st, "UNKNOWN");
break;
}
return SCPE_OK;
}
static t_stat vdm1_set_display(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (!cptr) return SCPE_IERR;
if (!strlen(cptr)) return SCPE_ARG;
/* this assumes that the parameter has already been upcased */
if (!strncmp(cptr, "NONE", strlen(cptr))) {
vdm1_display = VDM1_NONE;
} else if (!strncmp(cptr, "NORMAL", strlen(cptr))) {
vdm1_display = VDM1_NORMAL;
} else if (!strncmp(cptr, "REVERSE", strlen(cptr))) {
vdm1_display = VDM1_REVERSE;
} else {
return SCPE_ARG;
}
vdm1_dirty = TRUE;
return SCPE_OK;
}
static t_stat vdm1_show_display(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (!st) return SCPE_IERR;
fprintf(st, "DISPLAY=");
switch (vdm1_display) {
case VDM1_NONE:
fprintf(st, "NONE");
break;
case VDM1_NORMAL:
fprintf(st, "NORMAL");
break;
case VDM1_REVERSE:
fprintf(st, "REVERSE");
break;
default:
fprintf(st, "UNKNOWN");
break;
}
return SCPE_OK;
}

2274
AltairZ80/sol20.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -26,7 +26,7 @@
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE LIBSDL"
/>
<Tool
Name="VCCustomBuildTool"
@ -41,7 +41,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../AltairZ80/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="inline=__inline;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
PreprocessorDefinitions="inline=__inline;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
@ -108,7 +108,7 @@
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE LIBSDL"
/>
<Tool
Name="VCCustomBuildTool"
@ -126,7 +126,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../AltairZ80/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="inline=__inline;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
PreprocessorDefinitions="inline=__inline;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -389,6 +389,14 @@
RelativePath="..\AltairZ80\s100_tdd.c"
>
</File>
<File
RelativePath="..\AltairZ80\s100_vdm1.c"
>
</File>
<File
RelativePath="..\AltairZ80\sol20.c"
>
</File>
<File
RelativePath="..\scp.c"
>

View file

@ -164,6 +164,10 @@ ifneq (3,${SIM_MAJOR})
ifneq (,$(or $(findstring pdp6,${MAKECMDGOALS}),$(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS})))
VIDEO_USEFUL = true
endif
# building the AltairZ80 could use video support
ifneq (,$(findstring altairz80,${MAKECMDGOALS}))
VIDEO_USEFUL = true
endif
endif
# building the SEL32 networking can be used
ifneq (,$(findstring sel32,${MAKECMDGOALS}))
@ -1875,6 +1879,8 @@ ALTAIR_OPT = -I ${ALTAIRD}
ALTAIRZ80D = ${SIMHD}/AltairZ80
ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
${ALTAIRZ80D}/sol20.c \
${ALTAIRZ80D}/s100_vdm1.c \
${ALTAIRZ80D}/mmd.c \
${ALTAIRZ80D}/s100_dj2d.c \
${ALTAIRZ80D}/s100_djhdc.c \
@ -1902,7 +1908,7 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
${ALTAIRZ80D}/m68k/m68kopac.c ${ALTAIRZ80D}/m68k/m68kopdm.c \
${ALTAIRZ80D}/m68k/softfloat/softfloat.c \
${ALTAIRZ80D}/m68k/m68kopnz.c ${ALTAIRZ80D}/m68k/m68kops.c ${ALTAIRZ80D}/m68ksim.c
ALTAIRZ80_OPT = -I ${ALTAIRZ80D}
ALTAIRZ80_OPT = -I ${ALTAIRZ80D} -DUSE_SIM_VIDEO ${VIDEO_CCDEFS} $(VIDEO_LDFLAGS)
GRID = ${SIMHD}/GRI

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);