mirror of
https://github.com/rcornwell/sims.git
synced 2026-02-26 08:44:10 +00:00
SCP: Updated to current.
This commit is contained in:
@@ -975,6 +975,18 @@ display_init(enum display_type type, int sf, void *dptr)
|
||||
fprintf(stderr, "Display initialization failed\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
display_close(void *dptr)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
free (points);
|
||||
ws_shutdown();
|
||||
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
void
|
||||
display_reset(void)
|
||||
|
||||
@@ -65,6 +65,11 @@ enum display_type {
|
||||
*/
|
||||
extern int display_init(enum display_type, int scale, void *dptr);
|
||||
|
||||
/*
|
||||
* close display
|
||||
*/
|
||||
extern void display_close(void *dptr);
|
||||
|
||||
/* return size of virtual display */
|
||||
extern int display_xpoints(void);
|
||||
extern int display_ypoints(void);
|
||||
|
||||
563
sim_disk.c
563
sim_disk.c
@@ -1241,12 +1241,10 @@ if (Scb->scb_b_bitmapblks < 127)
|
||||
ret_val = (((t_offset)Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeblks << 16) + Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeptr) * 512;
|
||||
else
|
||||
ret_val = (((t_offset)Scb->scb_r_blocks[0].scb_w_freeblks << 16) + Scb->scb_r_blocks[0].scb_w_freeptr) * 512;
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname);
|
||||
sim_printf ("Format: %12.12s ", Home.hm1_t_format);
|
||||
sim_printf ("Sectors In Volume: %u\n", (uint32)(ret_val / 512));
|
||||
}
|
||||
sim_messagef (SCPE_OK, "%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_messagef (SCPE_OK, "%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname);
|
||||
sim_messagef (SCPE_OK, "Format: %12.12s ", Home.hm1_t_format);
|
||||
sim_messagef (SCPE_OK, "Sectors In Volume: %u\n", (uint32)(ret_val / 512));
|
||||
|
||||
Return_Cleanup:
|
||||
uptr->capac = saved_capac;
|
||||
@@ -1297,10 +1295,8 @@ for (i = 0; i < 8; i++) {
|
||||
max_lbn_partnum = i;
|
||||
}
|
||||
}
|
||||
if (!sim_quiet) {
|
||||
sim_printf ("%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_printf ("Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn);
|
||||
}
|
||||
sim_messagef (SCPE_OK, "%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_messagef (SCPE_OK, "Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn);
|
||||
ret_val = ((t_offset)max_lbn) * 512;
|
||||
|
||||
Return_Cleanup:
|
||||
@@ -1308,6 +1304,475 @@ uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
/*
|
||||
* The first logical block of device cluster 1 is either:
|
||||
* 1. MFD label entry (RSTS versions through 7.x)
|
||||
* 2. Disk Pack label (RSTS version 8.0 and later)
|
||||
*/
|
||||
typedef struct _RSTS_MFDLABEL {
|
||||
uint16 ml_ulnk;
|
||||
uint16 ml_mbm1;
|
||||
uint16 ml_reserved1;
|
||||
uint16 ml_reserved2;
|
||||
uint16 ml_pcs;
|
||||
uint16 ml_pstat;
|
||||
uint16 ml_packid[2];
|
||||
} RSTS_MFDLABEL;
|
||||
|
||||
typedef struct _RSTS_PACKLABEL {
|
||||
uint16 pk_mb01;
|
||||
uint16 pk_mbm1;
|
||||
uint16 pk_mdcn;
|
||||
uint16 pk_plvl;
|
||||
#define PK_LVL0 0000
|
||||
#define PK_LVL11 0401
|
||||
#define PK_LVL12 0402
|
||||
uint16 pk_ppcs;
|
||||
uint16 pk_pstat;
|
||||
#define PK_UC_NEW 0020000
|
||||
uint16 pk_packid[2];
|
||||
uint16 pk_tapgvn[2];
|
||||
uint16 pk_bckdat;
|
||||
uint16 pk_bcktim;
|
||||
} RSTS_PACKLABEL;
|
||||
|
||||
typedef union _RSTS_ROOT {
|
||||
RSTS_MFDLABEL rt_mfd;
|
||||
RSTS_PACKLABEL rt_pack;
|
||||
uint8 rt_block[512];
|
||||
} RSTS_ROOT;
|
||||
|
||||
typedef struct _RSTS_MFDBLOCKETTE {
|
||||
uint16 mb_ulnk;
|
||||
uint16 mb_mbm1;
|
||||
uint16 mb_reserved1;
|
||||
uint16 mb_reserved2;
|
||||
uint16 mb_reserved3;
|
||||
uint16 mb_malnk;
|
||||
uint16 mb_lppn;
|
||||
uint16 mb_lid;
|
||||
#define MB_ID 0051064
|
||||
} RSTS_MFDBLOCKETTE;
|
||||
#define IS_VALID_RSTS_MFD(b) \
|
||||
((((b)->mb_ulnk == 0) || ((b)->mb_ulnk == 1)) && \
|
||||
((b)->mb_mbm1 == 0177777) && \
|
||||
((b)->mb_reserved1 == 0) && \
|
||||
((b)->mb_reserved2 == 0) && \
|
||||
((b)->mb_reserved3 == 0) && \
|
||||
((b)->mb_lppn == 0177777) && \
|
||||
((b)->mb_lid == MB_ID))
|
||||
|
||||
typedef struct _RSTS_GFDBLOCKETTE {
|
||||
uint16 gb_ulnk;
|
||||
uint16 gb_mbm1;
|
||||
uint16 gb_reserved1;
|
||||
uint16 gb_reserved2;
|
||||
uint16 gb_reserved3;
|
||||
uint16 gb_reserved4;
|
||||
uint16 gb_lppn;
|
||||
uint16 gb_lid;
|
||||
#define GB_ID 0026264
|
||||
} RSTS_GFDBLOCKETTE;
|
||||
#define IS_VALID_RSTS_GFD(b, g) \
|
||||
((((b)->gb_ulnk == 0) || ((b)->gb_ulnk == 1)) && \
|
||||
((b)->gb_mbm1 == 0177777) && \
|
||||
((b)->gb_reserved1 == 0) && \
|
||||
((b)->gb_reserved2 == 0) && \
|
||||
((b)->gb_reserved3 == 0) && \
|
||||
((b)->gb_reserved4 == 0) && \
|
||||
((b)->gb_lppn == (((g) << 8) | 0377)) && \
|
||||
((b)->gb_lid == GB_ID))
|
||||
|
||||
typedef struct _RSTS_UFDBLOCKETTE {
|
||||
uint16 ub_ulnk;
|
||||
uint16 ub_mbm1;
|
||||
uint16 ub_reserved1;
|
||||
uint16 ub_reserved2;
|
||||
uint16 ub_reserved3;
|
||||
uint16 ub_reserved4;
|
||||
uint16 ub_lppn;
|
||||
uint16 ub_lid;
|
||||
#define UB_ID 0102064
|
||||
} RSTS_UFDBLOCKETTE;
|
||||
#define IS_VALID_RSTS_UFD(b, g, u) \
|
||||
(((b)->ub_mbm1 == 0177777) && \
|
||||
((b)->ub_reserved1 == 0) && \
|
||||
((b)->ub_reserved2 == 0) && \
|
||||
((b)->ub_reserved3 == 0) && \
|
||||
((b)->ub_reserved4 == 0) && \
|
||||
((b)->ub_lppn == (((g) << 8) | (u))) && \
|
||||
((b)->ub_lid == UB_ID))
|
||||
|
||||
typedef struct _RSTS_UNAME {
|
||||
uint16 un_ulnk;
|
||||
uint16 un_unam;
|
||||
uint16 un_reserved1;
|
||||
uint16 un_reserved2;
|
||||
uint16 un_ustat;
|
||||
uint16 un_uacnt;
|
||||
uint16 un_uaa;
|
||||
uint16 un_uar;
|
||||
} RSTS_UNAME;
|
||||
|
||||
typedef struct _RSTS_FNAME {
|
||||
uint16 fn_ulnk;
|
||||
uint16 fn_unam[3];
|
||||
uint16 fn_ustat;
|
||||
uint16 fn_uacnt;
|
||||
uint16 fn_uaa;
|
||||
uint16 fn_uar;
|
||||
} RSTS_FNAME;
|
||||
|
||||
typedef struct _RSTS_ACNT {
|
||||
uint16 ac_ulnk;
|
||||
uint16 ac_udla;
|
||||
uint16 ac_usiz;
|
||||
uint16 ac_udc;
|
||||
uint16 ac_utc;
|
||||
uint16 ac_urts[2];
|
||||
uint16 ac_uclus;
|
||||
} RSTS_ACNT;
|
||||
|
||||
typedef struct _RSTS_RETR {
|
||||
uint16 rt_ulnk;
|
||||
uint16 rt_uent[7];
|
||||
#define RT_ENTRIES 7
|
||||
} RSTS_RETR;
|
||||
|
||||
typedef struct _RSTS_DCMAP {
|
||||
uint16 dc_clus;
|
||||
#define DC_MASK 0077777
|
||||
uint16 dc_map[7];
|
||||
} RSTS_DCMAP;
|
||||
|
||||
/*
|
||||
* Directory link definitions
|
||||
*/
|
||||
#define DL_USE 0000001
|
||||
#define DL_BAD 0000002
|
||||
#define DL_CHE 0000004
|
||||
#define DL_CLN 0000010
|
||||
#define DL_ENO 0000760
|
||||
#define DL_CLO 0007000
|
||||
#define DL_BLO 0170000
|
||||
|
||||
#define DLSH_ENO 4
|
||||
#define DLSH_CLO 9
|
||||
#define DLSH_BLO 12
|
||||
|
||||
#define BLOCKETTE_SZ (8 * sizeof(uint16))
|
||||
#define MAP_OFFSET (31 * BLOCKETTE_SZ)
|
||||
|
||||
#define SATT0 0073374
|
||||
#define SATT1 0076400
|
||||
#define SATT2 0075273
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct _rstsContext {
|
||||
UNIT *uptr;
|
||||
int dcshift;
|
||||
int pcs;
|
||||
char packid[8];
|
||||
t_seccnt sects;
|
||||
RSTS_DCMAP map;
|
||||
} rstsContext;
|
||||
|
||||
static char rad50[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.%0123456789";
|
||||
|
||||
static void r50Asc(uint16 val, char *buf)
|
||||
{
|
||||
buf[2] = rad50[val % 050];
|
||||
val /= 050;
|
||||
buf[1] = rad50[val % 050];
|
||||
buf[0] = rad50[val / 050];
|
||||
}
|
||||
|
||||
static t_stat rstsReadBlock(rstsContext *context, uint16 cluster, uint16 block, void *buf)
|
||||
{
|
||||
t_lba blk = (cluster << context->dcshift) + block;
|
||||
t_seccnt sects_read;
|
||||
|
||||
if ((sim_disk_rdsect(context->uptr, blk * context->sects, (uint8 *)buf, §s_read, context->sects) == SCPE_OK) &&
|
||||
(sects_read == context->sects))
|
||||
return SCPE_OK;
|
||||
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
static t_stat rstsReadBlockette(rstsContext *context, uint16 link, void *buf)
|
||||
{
|
||||
uint16 block = (link & DL_BLO) >> DLSH_BLO;
|
||||
uint16 dcn = (link & DL_CLO) >> DLSH_CLO;
|
||||
uint16 blockette = (link & DL_ENO) >> DLSH_ENO;
|
||||
uint8 temp[512];
|
||||
|
||||
if ((dcn != 7) && (blockette != 31) &&
|
||||
(block <= (context->map.dc_clus & DC_MASK))) {
|
||||
if (rstsReadBlock(context, context->map.dc_map[dcn], block, temp) == SCPE_OK) {
|
||||
memcpy(buf, &temp[blockette * BLOCKETTE_SZ], BLOCKETTE_SZ);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
static t_stat rstsFind01UFD(rstsContext *context, uint16 *ufd, uint16 *level)
|
||||
{
|
||||
uint16 dcs = 1 << context->dcshift;
|
||||
RSTS_ROOT root;
|
||||
uint16 buf[256];
|
||||
|
||||
if (rstsReadBlock(context, 1, 0, &root) == SCPE_OK) {
|
||||
/*
|
||||
* First validate fields which are common to both the MFD label and
|
||||
* Pack label - we'll use Pack label offsets here.
|
||||
*/
|
||||
if ((root.rt_pack.pk_mbm1 == 0177777) && (root.rt_pack.pk_ppcs >= dcs)) {
|
||||
char ch, *tmp = &context->packid[1];
|
||||
uint16 mfd, gfd;
|
||||
|
||||
context->pcs = root.rt_pack.pk_ppcs;
|
||||
|
||||
r50Asc(root.rt_pack.pk_packid[0], &context->packid[0]);
|
||||
r50Asc(root.rt_pack.pk_packid[1], &context->packid[3]);
|
||||
context->packid[6] = '\0';
|
||||
|
||||
/*
|
||||
* The Pack ID must consist of 1 - 6 alphanumeric characters
|
||||
* padded at the end with spaces.
|
||||
*/
|
||||
if (!isalnum(context->packid[0]))
|
||||
return SCPE_IOERR;
|
||||
|
||||
while ((ch = *tmp++) != 0) {
|
||||
if (!isalnum(ch)) {
|
||||
if (ch != ' ')
|
||||
return SCPE_IOERR;
|
||||
|
||||
while (*tmp)
|
||||
if (*tmp++ != ' ')
|
||||
return SCPE_IOERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the pack revision level and, therefore, the path to
|
||||
* [0,1]satt.sys which will allow us to determine the size of the
|
||||
* pack used by RSTS.
|
||||
*/
|
||||
if ((root.rt_pack.pk_pstat & PK_UC_NEW) == 0) {
|
||||
uint16 link = root.rt_mfd.ml_ulnk;
|
||||
RSTS_UNAME uname;
|
||||
|
||||
/*
|
||||
* Old format used by RSTS up through V07.x
|
||||
*/
|
||||
if (dcs > 16)
|
||||
return SCPE_IOERR;
|
||||
|
||||
*level = PK_LVL0;
|
||||
|
||||
memcpy(&context->map, &root.rt_block[MAP_OFFSET], BLOCKETTE_SZ);
|
||||
|
||||
/*
|
||||
* Scan the MFD name entries looking for [0,1]. Note there will
|
||||
* always be at least 1 entry.
|
||||
*/
|
||||
do {
|
||||
if (rstsReadBlockette(context, link, &uname) != SCPE_OK)
|
||||
break;
|
||||
|
||||
if (uname.un_unam == ((0 << 8) | 1)) {
|
||||
*ufd = uname.un_uar;
|
||||
return SCPE_OK;
|
||||
}
|
||||
} while ((link = uname.un_ulnk) != 0);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* New format used by RSTS V08 and later
|
||||
*/
|
||||
switch (root.rt_pack.pk_plvl) {
|
||||
case PK_LVL11:
|
||||
if (dcs > 16)
|
||||
return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case PK_LVL12:
|
||||
if (dcs > 64)
|
||||
return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
default:
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
*level = root.rt_pack.pk_plvl;
|
||||
|
||||
mfd = root.rt_pack.pk_mdcn;
|
||||
|
||||
if (rstsReadBlock(context, mfd, 0, buf) == SCPE_OK) {
|
||||
if (IS_VALID_RSTS_MFD((RSTS_MFDBLOCKETTE *)buf)) {
|
||||
if (rstsReadBlock(context, mfd, 1, buf) == SCPE_OK)
|
||||
if ((gfd = buf[0]) != 0)
|
||||
if (rstsReadBlock(context, gfd, 0, buf) == SCPE_OK)
|
||||
if (IS_VALID_RSTS_GFD((RSTS_GFDBLOCKETTE *)buf, 0)) {
|
||||
if (rstsReadBlock(context, gfd, 1, buf) == SCPE_OK)
|
||||
if ((*ufd = buf[1]) != 0)
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
static t_stat rstsLoadAndScanSATT(rstsContext *context, uint16 uaa, uint16 uar, t_offset *result)
|
||||
{
|
||||
t_offset blocks = 0;
|
||||
uint8 bitmap[8192];
|
||||
int i, j;
|
||||
RSTS_ACNT acnt;
|
||||
RSTS_RETR retr;
|
||||
|
||||
if (uar != 0) {
|
||||
if (rstsReadBlockette(context, uaa, &acnt) == SCPE_OK) {
|
||||
uint16 blocks = acnt.ac_usiz;
|
||||
uint16 offset = 0;
|
||||
|
||||
memset(bitmap, 0xFF, sizeof(bitmap));
|
||||
|
||||
if (blocks != 0) {
|
||||
do {
|
||||
int i, j;
|
||||
uint16 fcl;
|
||||
|
||||
if (rstsReadBlockette(context, uar, &retr) != SCPE_OK)
|
||||
return SCPE_IOERR;
|
||||
|
||||
for (i = 0; i < RT_ENTRIES; i++) {
|
||||
if ((fcl = retr.rt_uent[i]) == 0)
|
||||
goto scanBitmap;
|
||||
|
||||
for (j = 0; j < acnt.ac_uclus; j++) {
|
||||
if ((blocks == 0) || (offset >= sizeof(bitmap)))
|
||||
goto scanBitmap;
|
||||
|
||||
if (rstsReadBlock(context, fcl, j, &bitmap[offset]) != SCPE_OK)
|
||||
return SCPE_IOERR;
|
||||
|
||||
offset += 512;
|
||||
blocks--;
|
||||
}
|
||||
}
|
||||
} while ((uar = retr.rt_ulnk) != 0);
|
||||
|
||||
scanBitmap:
|
||||
for (i = sizeof(bitmap) - 1; i != 0; i--)
|
||||
if (bitmap[i] != 0xFF) {
|
||||
blocks = i * 8;
|
||||
for (j = 7; j >= 0; j--)
|
||||
if ((bitmap[i] & (1 << j)) == 0) {
|
||||
blocks += j + 1;
|
||||
goto scanDone;
|
||||
}
|
||||
}
|
||||
scanDone:
|
||||
*result = (blocks + 1) * context->pcs;
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
static t_offset get_rsts_filesystem_size (UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
t_addr saved_capac;
|
||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */
|
||||
uint8 buf[512];
|
||||
t_offset ret_val = (t_offset)-1;
|
||||
rstsContext context;
|
||||
|
||||
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||
return ret_val;
|
||||
saved_capac = uptr->capac;
|
||||
uptr->capac = temp_capac;
|
||||
|
||||
context.uptr = uptr;
|
||||
context.sects = 512 / ctx->sector_size;
|
||||
|
||||
/*
|
||||
* Check all possible device cluster sizes
|
||||
*/
|
||||
for (context.dcshift = 0; context.dcshift < 8; context.dcshift++) {
|
||||
uint16 ufd, level;
|
||||
|
||||
/*
|
||||
* We need to find [0,1]SATT.SYS to compute the actual size of the disk.
|
||||
* First find the DCN of the [0,1] UFD.
|
||||
*/
|
||||
if (rstsFind01UFD(&context, &ufd, &level) == SCPE_OK) {
|
||||
if (rstsReadBlock(&context, ufd, 0, buf) == SCPE_OK) {
|
||||
if (IS_VALID_RSTS_UFD((RSTS_UFDBLOCKETTE *)buf, 0, 1)) {
|
||||
uint16 link = ((RSTS_UFDBLOCKETTE *)buf)->ub_ulnk;
|
||||
RSTS_FNAME fname;
|
||||
|
||||
memcpy(&context.map, &buf[MAP_OFFSET], BLOCKETTE_SZ);
|
||||
|
||||
/*
|
||||
* Scan the UFD looking for SATT.SYS - the allocation bitmap
|
||||
*/
|
||||
do {
|
||||
if (rstsReadBlockette(&context, link, &fname) != SCPE_OK)
|
||||
break;
|
||||
|
||||
if ((fname.fn_unam[0] == SATT0) &&
|
||||
(fname.fn_unam[1] == SATT1) &&
|
||||
(fname.fn_unam[2] == SATT2)) {
|
||||
if (rstsLoadAndScanSATT(&context, fname.fn_uaa, fname.fn_uar, &ret_val) == SCPE_OK) {
|
||||
const char *fmt = "???";
|
||||
|
||||
ret_val *= 512;
|
||||
|
||||
switch (level) {
|
||||
case PK_LVL0:
|
||||
fmt = "0.0";
|
||||
break;
|
||||
|
||||
case PK_LVL11:
|
||||
fmt = "1.1";
|
||||
break;
|
||||
|
||||
case PK_LVL12:
|
||||
fmt = "1.2";
|
||||
break;
|
||||
}
|
||||
|
||||
sim_messagef(SCPE_OK, "%s%d: '%s' Contains a RSTS File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_messagef(SCPE_OK, "%s%d: Pack ID: %6.6s ", sim_dname (dptr), (int)(uptr-dptr->units), context.packid);
|
||||
sim_messagef(SCPE_OK, "Revision Level: %3s ", fmt);
|
||||
sim_messagef(SCPE_OK, "Pack Clustersize: %d\n", context.pcs);
|
||||
sim_messagef(SCPE_OK, "%s%d: Last Unallocated Sector In File System: %u\n", sim_dname (dptr), (int)(uptr-dptr->units), (uint32)(ret_val / 512));
|
||||
goto cleanup_done;
|
||||
}
|
||||
}
|
||||
} while ((link = fname.fn_ulnk) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup_done:
|
||||
uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct _RT11_HomeBlock {
|
||||
uint8 hb_b_bbtable[130];
|
||||
@@ -1484,29 +1949,27 @@ Next_Partition:
|
||||
|
||||
Return_Cleanup:
|
||||
if (partitions) {
|
||||
if (!sim_quiet) {
|
||||
const char *parttype;
|
||||
const char *parttype;
|
||||
|
||||
switch (version) {
|
||||
case HB_C_SYSVER_V3A:
|
||||
parttype = "V3A";
|
||||
break;
|
||||
switch (version) {
|
||||
case HB_C_SYSVER_V3A:
|
||||
parttype = "V3A";
|
||||
break;
|
||||
|
||||
case HB_C_SYSVER_V04:
|
||||
parttype = "V04";
|
||||
break;
|
||||
case HB_C_SYSVER_V04:
|
||||
parttype = "V04";
|
||||
break;
|
||||
|
||||
case HB_C_SYSVER_V05:
|
||||
parttype = "V05";
|
||||
break;
|
||||
case HB_C_SYSVER_V05:
|
||||
parttype = "V05";
|
||||
break;
|
||||
|
||||
default:
|
||||
parttype = "???";
|
||||
break;
|
||||
}
|
||||
sim_printf ("%s%d: '%s' Contains RT11 partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_printf ("%d valid partition%s, Type: %s, Sectors On Disk: %u\n", partitions, partitions == 1 ? "" : "s", parttype, (uint32)(ret_val / 512));
|
||||
default:
|
||||
parttype = "???";
|
||||
break;
|
||||
}
|
||||
sim_messagef (SCPE_OK, "%s%d: '%s' Contains RT11 partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
|
||||
sim_messagef (SCPE_OK, "%d valid partition%s, Type: %s, Sectors On Disk: %u\n", partitions, partitions == 1 ? "" : "s", parttype, (uint32)(ret_val / 512));
|
||||
}
|
||||
uptr->capac = saved_capac;
|
||||
return ret_val;
|
||||
@@ -1520,6 +1983,7 @@ static FILESYSTEM_CHECK checks[] = {
|
||||
&get_ods2_filesystem_size,
|
||||
&get_ods1_filesystem_size,
|
||||
&get_ultrix_filesystem_size,
|
||||
&get_rsts_filesystem_size,
|
||||
&get_rt11_filesystem_size, /* This should be the last entry
|
||||
in the table to reduce the
|
||||
possibility of matching an RT-11
|
||||
@@ -2129,19 +2593,36 @@ fprintf (st, "was created. This metadata is therefore available whenever that V
|
||||
fprintf (st, "attached to an emulated disk device in the future so the device type and\n");
|
||||
fprintf (st, "size can be automatically be configured.\n\n");
|
||||
|
||||
if (0 == (uptr-dptr->units)) {
|
||||
if (dptr->numunits > 1) {
|
||||
uint32 i;
|
||||
if (dptr->numunits > 1) {
|
||||
uint32 i, attachable_count = 0, out_count = 0, skip_count;
|
||||
|
||||
for (i=0; i < dptr->numunits; ++i)
|
||||
if (dptr->units[i].flags & UNIT_ATTABLE)
|
||||
fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i);
|
||||
for (i=0; i < dptr->numunits; ++i)
|
||||
if ((dptr->units[i].flags & UNIT_ATTABLE) &&
|
||||
!(dptr->units[i].flags & UNIT_DIS))
|
||||
++attachable_count;
|
||||
for (i=0; (i < dptr->numunits) && (out_count < 2); ++i)
|
||||
if ((dptr->units[i].flags & UNIT_ATTABLE) &&
|
||||
!(dptr->units[i].flags & UNIT_DIS)) {
|
||||
fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i);
|
||||
++out_count;
|
||||
}
|
||||
if (attachable_count > 4) {
|
||||
fprintf (st, " .\n");
|
||||
fprintf (st, " .\n");
|
||||
fprintf (st, " .\n");
|
||||
}
|
||||
else
|
||||
fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name);
|
||||
skip_count = attachable_count - 2;
|
||||
for (i=0; i < dptr->numunits; ++i)
|
||||
if ((dptr->units[i].flags & UNIT_ATTABLE) &&
|
||||
!(dptr->units[i].flags & UNIT_DIS)) {
|
||||
if (skip_count == 0)
|
||||
fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i);
|
||||
else
|
||||
--skip_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf (st, " sim> ATTACH {switches} %s diskfile\n\n", dptr->name);
|
||||
fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name);
|
||||
fprintf (st, "\n%s attach command switches\n", dptr->name);
|
||||
fprintf (st, " -R Attach Read Only.\n");
|
||||
fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n");
|
||||
@@ -2183,9 +2664,7 @@ fprintf (st, " sim> att rq2 -f vhd RA92.vhd\n");
|
||||
fprintf (st, " RQ2: creating new file\n");
|
||||
fprintf (st, " sim> sho rq2\n");
|
||||
fprintf (st, " RQ2, 1505MB, attached to RA92.vhd, write enabled, RA92, autosize, VHD format\n");
|
||||
fprintf (st, " sim> ! dir RA92.vhd\n");
|
||||
fprintf (st, " Volume in drive H is New Volume\n");
|
||||
fprintf (st, " Volume Serial Number is F8DE-510C\n\n");
|
||||
fprintf (st, " sim> dir RA92.vhd\n");
|
||||
fprintf (st, " Directory of H:\\Data\n\n");
|
||||
fprintf (st, " 04/14/2011 12:57 PM 5,120 RA92.vhd\n");
|
||||
fprintf (st, " 1 File(s) 5,120 bytes\n");
|
||||
@@ -2196,9 +2675,7 @@ fprintf (st, " RQ3: Copied 1505MB. 99%% complete.\n");
|
||||
fprintf (st, " RQ3: Copied 1505MB. Done.\n");
|
||||
fprintf (st, " sim> sh rq3\n");
|
||||
fprintf (st, " RQ3, 1505MB, attached to RA92-1.vhd, write enabled, RA92, autosize, VHD format\n");
|
||||
fprintf (st, " sim> ! dir RA92*\n");
|
||||
fprintf (st, " Volume in drive H is New Volume\n");
|
||||
fprintf (st, " Volume Serial Number is F8DE-510C\n\n");
|
||||
fprintf (st, " sim> dir RA92*\n");
|
||||
fprintf (st, " Directory of H:\\Data\n\n");
|
||||
fprintf (st, " 04/14/2011 01:12 PM 5,120 RA92-1.vhd\n");
|
||||
fprintf (st, " 04/14/2011 12:58 PM 5,120 RA92.vhd\n");
|
||||
|
||||
@@ -48,6 +48,14 @@
|
||||
#include ".git-commit-id.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Simh's git commit id would be undefined when working with an
|
||||
extracted archive (zip file or tar ball). To address this
|
||||
problem and record the commit id that the archive was created
|
||||
from, the archive creation process populates the below
|
||||
information as a consequence of the "sim_rev.h export-subst"
|
||||
line in the .gitattributes file.
|
||||
*/
|
||||
#if !defined(SIM_GIT_COMMIT_ID)
|
||||
#define SIM_GIT_COMMIT_ID $Format:%H$
|
||||
#define SIM_GIT_COMMIT_TIME $Format:%aI$
|
||||
|
||||
191
sim_video.c
191
sim_video.c
@@ -37,6 +37,10 @@ t_bool vid_mouse_b1 = FALSE;
|
||||
t_bool vid_mouse_b2 = FALSE;
|
||||
t_bool vid_mouse_b3 = FALSE;
|
||||
static VID_QUIT_CALLBACK vid_quit_callback = NULL;
|
||||
static VID_GAMEPAD_CALLBACK motion_callback[10];
|
||||
static VID_GAMEPAD_CALLBACK button_callback[10];
|
||||
static int vid_gamepad_inited = 0;
|
||||
static int vid_gamepad_ok = 0; /* Or else just joysticks. */
|
||||
|
||||
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback)
|
||||
{
|
||||
@@ -44,6 +48,41 @@ vid_quit_callback = callback;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat register_callback (void **array, int n, void *callback)
|
||||
{
|
||||
int i, j = -1;
|
||||
|
||||
if (!vid_gamepad_inited) {
|
||||
return SCPE_NOATT;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (array[i] == callback)
|
||||
return SCPE_ALATT;
|
||||
if (array[i] == NULL)
|
||||
j = i;
|
||||
}
|
||||
|
||||
if (j != -1) {
|
||||
array[j] = callback;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK callback)
|
||||
{
|
||||
int n = sizeof (motion_callback) / sizeof (callback);
|
||||
return register_callback ((void **)motion_callback, n, (void *)callback);
|
||||
}
|
||||
|
||||
t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK callback)
|
||||
{
|
||||
int n = sizeof (button_callback) / sizeof (callback);
|
||||
return register_callback ((void **)button_callback, n, (void *)callback);
|
||||
}
|
||||
|
||||
t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc)
|
||||
{
|
||||
return vid_show_video (st, uptr, val, desc);
|
||||
@@ -510,6 +549,64 @@ return SCPE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static t_stat vid_init_controllers (void)
|
||||
{
|
||||
SDL_Joystick *y;
|
||||
SDL_version ver;
|
||||
int i, n;
|
||||
|
||||
if (vid_gamepad_inited)
|
||||
return SCPE_OK;
|
||||
|
||||
/* Chech that the SDL_GameControllerFromInstanceID function is
|
||||
available at run time. */
|
||||
SDL_GetVersion(&ver);
|
||||
vid_gamepad_ok = (ver.major > 2 ||
|
||||
(ver.major == 2 && (ver.minor > 0 || ver.patch >= 4)));
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
if (vid_gamepad_ok)
|
||||
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
|
||||
if (SDL_JoystickEventState (SDL_ENABLE) < 0) {
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
if (vid_gamepad_ok && SDL_GameControllerEventState (SDL_ENABLE) < 0) {
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
n = SDL_NumJoysticks();
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (vid_gamepad_ok && SDL_IsGameController (i)) {
|
||||
SDL_GameController *x = SDL_GameControllerOpen (i);
|
||||
if (x != NULL) {
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||
"Game controller: %s\n", SDL_GameControllerNameForIndex(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
y = SDL_JoystickOpen (i);
|
||||
if (y != NULL) {
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||
"Joystick: %s\n", SDL_JoystickNameForIndex(i));
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||
"Number of axes: %d, buttons: %d\n",
|
||||
SDL_JoystickNumAxes(y),
|
||||
SDL_JoystickNumButtons(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vid_gamepad_inited = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags)
|
||||
{
|
||||
if (!vid_active) {
|
||||
@@ -538,10 +635,18 @@ if (!vid_active) {
|
||||
|
||||
vid_dev = dptr;
|
||||
|
||||
memset (motion_callback, 0, sizeof motion_callback);
|
||||
memset (button_callback, 0, sizeof button_callback);
|
||||
|
||||
stat = vid_create_window ();
|
||||
if (stat != SCPE_OK)
|
||||
return stat;
|
||||
|
||||
if (vid_init_controllers () != SCPE_OK) {
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||
"vid_open() - Failed initializing game controllers\n");
|
||||
}
|
||||
|
||||
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_open() - Success\n");
|
||||
}
|
||||
return SCPE_OK;
|
||||
@@ -553,6 +658,12 @@ if (vid_active) {
|
||||
SDL_Event user_event;
|
||||
int status;
|
||||
|
||||
vid_gamepad_inited = 0;
|
||||
memset (motion_callback, 0, sizeof motion_callback);
|
||||
memset (button_callback, 0, sizeof button_callback);
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
|
||||
vid_active = FALSE;
|
||||
if (vid_ready) {
|
||||
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_close()\n");
|
||||
@@ -1149,6 +1260,61 @@ switch (key) {
|
||||
}
|
||||
}
|
||||
|
||||
void vid_joy_motion (SDL_JoyAxisEvent *event)
|
||||
{
|
||||
int n = sizeof motion_callback / sizeof (VID_GAMEPAD_CALLBACK);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (motion_callback[i]) {
|
||||
motion_callback[i](event->which, event->axis, event->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vid_joy_button (SDL_JoyButtonEvent *event)
|
||||
{
|
||||
int n = sizeof button_callback / sizeof (VID_GAMEPAD_CALLBACK);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (button_callback[i]) {
|
||||
button_callback[i](event->which, event->button, event->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vid_controller_motion (SDL_ControllerAxisEvent *event)
|
||||
{
|
||||
SDL_JoyAxisEvent e;
|
||||
e.which = event->which;
|
||||
e.axis = event->axis;
|
||||
e.value = event->value;
|
||||
vid_joy_motion (&e);
|
||||
}
|
||||
|
||||
void vid_controller_button (SDL_ControllerButtonEvent *event)
|
||||
{
|
||||
/* SDL_GameControllerFromInstanceID is only available from SDL
|
||||
version 2.0.4, so check the version at compile time. The
|
||||
version is also checked at run time. */
|
||||
#if (SDL_MAJOR_VERSION > 2) || (SDL_MAJOR_VERSION == 2 && \
|
||||
(SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 4))
|
||||
|
||||
SDL_JoyButtonEvent e;
|
||||
SDL_GameControllerButtonBind b;
|
||||
SDL_GameController *c;
|
||||
SDL_GameControllerButton button = (SDL_GameControllerButton)event->button;
|
||||
|
||||
c = SDL_GameControllerFromInstanceID (event->which);
|
||||
b = SDL_GameControllerGetBindForButton (c, button);
|
||||
e.which = event->which;
|
||||
e.button = b.value.button;
|
||||
e.state = event->state;
|
||||
vid_joy_button (&e);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vid_key (SDL_KeyboardEvent *event)
|
||||
{
|
||||
SIM_KEY_EVENT ev;
|
||||
@@ -1691,17 +1857,36 @@ while (vid_active) {
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
vid_key ((SDL_KeyboardEvent*)&event);
|
||||
vid_key (&event.key);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
vid_mouse_button ((SDL_MouseButtonEvent*)&event);
|
||||
vid_mouse_button (&event.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
vid_mouse_move ((SDL_MouseMotionEvent*)&event);
|
||||
vid_mouse_move (&event.motion);
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION:
|
||||
vid_joy_motion (&event.jaxis);
|
||||
break;
|
||||
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
vid_joy_button (&event.jbutton);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
vid_controller_motion (&event.caxis);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
vid_controller_button (&event.cbutton);
|
||||
break;
|
||||
|
||||
#if SDL_MAJOR_VERSION != 1
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.windowID == vid_windowID) {
|
||||
|
||||
@@ -180,6 +180,9 @@ t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, i
|
||||
/* code responsible for cursor display in video) */
|
||||
typedef void (*VID_QUIT_CALLBACK)(void);
|
||||
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback);
|
||||
typedef void (*VID_GAMEPAD_CALLBACK)(int, int, int);
|
||||
t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK);
|
||||
t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK);
|
||||
t_stat vid_close (void);
|
||||
t_stat vid_poll_kb (SIM_KEY_EVENT *ev);
|
||||
t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev);
|
||||
|
||||
Reference in New Issue
Block a user