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:
parent
825a505083
commit
cf9fac614c
7 changed files with 3113 additions and 30 deletions
|
@ -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
708
AltairZ80/s100_vdm1.c
Normal 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
2274
AltairZ80/sol20.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -26,7 +26,7 @@
|
|||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
Description="Check for required build dependencies & git commit id"
|
||||
CommandLine="Pre-Build-Event.cmd "$(TargetDir)$(TargetName).exe" LIBPCRE"
|
||||
CommandLine="Pre-Build-Event.cmd "$(TargetDir)$(TargetName).exe" 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 & git commit id"
|
||||
CommandLine="Pre-Build-Event.cmd "$(TargetDir)$(TargetName).exe" LIBPCRE"
|
||||
CommandLine="Pre-Build-Event.cmd "$(TargetDir)$(TargetName).exe" 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"
|
||||
>
|
||||
|
|
8
makefile
8
makefile
|
@ -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
|
||||
|
|
121
sim_video.c
121
sim_video.c
|
@ -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 "";
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue