From d137282519fdb8bf9fdefd333926a7c2b6ad94e1 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 17 Apr 2019 19:49:09 -0400 Subject: [PATCH] SCP: Updated to current. --- scp.c | 19 ++- sim_BuildROMs.c | 1 + sim_defs.h | 3 +- sim_ether.c | 152 +++++++++++-------- sim_serial.c | 2 +- sim_sock.h | 6 +- sim_tape.c | 384 ++++++++++++++++++++++++++++++++++++++---------- sim_tape.h | 8 +- sim_video.c | 24 ++- sim_video.h | 2 +- 10 files changed, 442 insertions(+), 159 deletions(-) diff --git a/scp.c b/scp.c index 09d5d96..e06ab8d 100644 --- a/scp.c +++ b/scp.c @@ -4095,7 +4095,7 @@ return ap; Token "%0" represents the command file name. - The input sequence "\%" represents a literal "%", and "\\" represents a + The input sequence "%%" represents a literal "%", and "\\" represents a literal "\". All other character combinations are rendered literally. Omitted parameters result in null-string substitutions. @@ -4202,11 +4202,16 @@ for (; *ip && (op < oend); ) { ++ip; } else { - get_glyph_nc (ip, gbuf, '%'); /* get the literal name */ - ap = _sim_get_env_special (gbuf, rbuf, sizeof (rbuf)); - ip += strlen (gbuf); - if (*ip == '%') - ++ip; + if (*ip == '\0') { /* is this a bare % at end of line? */ + *op++ = '%'; /* leave it there as a literal percent sign */ + } + else { + get_glyph_nc (ip, gbuf, '%'); /* get the literal name */ + ap = _sim_get_env_special (gbuf, rbuf, sizeof (rbuf)); + ip += strlen (gbuf); + if (*ip == '%') + ++ip; + } } } if (ap) { /* non-null arg? */ @@ -7281,6 +7286,7 @@ for (i = 0; i < (device_count + sim_internal_device_count); i++) {/* loop thru d WRITE_I (uptr->wait); WRITE_I (uptr->buf); WRITE_I (uptr->recsize); + WRITE_I (uptr->tape_eom); WRITE_I (uptr->capac); /* [V3.5] capacity */ fprintf (sfile, "%.0f\n", uptr->usecs_remaining);/* [V4.0] remaining wait */ WRITE_I (uptr->pos); @@ -7532,6 +7538,7 @@ for ( ;; ) { /* device loop */ READ_I (uptr->wait); READ_I (uptr->buf); READ_I (uptr->recsize); + READ_I (uptr->tape_eom); } old_capac = uptr->capac; /* save current capacity */ if (v35) { /* [V3.5+] capacity */ diff --git a/sim_BuildROMs.c b/sim_BuildROMs.c index 750e286..fb654c6 100644 --- a/sim_BuildROMs.c +++ b/sim_BuildROMs.c @@ -45,6 +45,7 @@ struct ROM_File_Descriptor { {"VAX/ka610.bin", "VAX/vax_ka610_bin.h", 16384, 0xFFEF3312, "vax_ka610_bin"}, {"VAX/ka750_new.bin", "VAX/vax_ka750_bin_new.h", 1024, 0xFFFE7BE5, "vax_ka750_bin_new", "From ROM set: E40A9, E41A9, E42A9, E43A9 (Boots: A=DD, B=DB, C=DU"}, {"VAX/ka750_old.bin", "VAX/vax_ka750_bin_old.h", 1024, 0xFFFEBAA5, "vax_ka750_bin_old", "From ROM set: 990A9, 948A9, 906A9, 905A9 (Boots: A=DD, B=DM, C=DL, D=DU"}, + {"VAX/vcb02.bin", "VAX/vax_vcb02_bin.h", 16384, 0xFFF1D2AD, "vax_vcb02_bin"}, {"VAX/vmb.exe", "VAX/vax_vmb_exe.h", 44544, 0xFFC014BB, "vax_vmb_exe"}, {"PDP11/lunar11/lunar.lda", "PDP11/pdp11_vt_lunar_rom.h", 13824 , 0xFFF15D00, "lunar_lda"}, {"PDP11/dazzledart/dazzle.lda", "PDP11/pdp11_dazzle_dart_rom.h", 6096, 0xFFF83848, "dazzle_lda"}, diff --git a/sim_defs.h b/sim_defs.h index f6e085d..4a5b8d4 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -591,7 +591,8 @@ struct UNIT { uint16 us9; /* device specific */ uint16 us10; /* device specific */ void *tmxr; /* TMXR linkage */ - uint32 recsize; /* Tape info */ + uint32 recsize; /* Tape specific info */ + t_addr tape_eom; /* Tape specific info */ t_bool (*cancel)(UNIT *); double usecs_remaining; /* time balance for long delays */ char *uname; /* Unit name */ diff --git a/sim_ether.c b/sim_ether.c index 1081008..ecf756c 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1202,7 +1202,7 @@ int load_pcap(void) { /* define functions with dynamic revectoring */ void pcap_close(pcap_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { p_pcap_close(a); } } @@ -1213,7 +1213,7 @@ int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e #else int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_int32 e) { #endif - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_compile(a, b, c, d, e); } else { return 0; @@ -1221,7 +1221,7 @@ int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_i } int pcap_datalink(pcap_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_datalink(a); } else { return 0; @@ -1229,7 +1229,7 @@ int pcap_datalink(pcap_t* a) { } int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_dispatch(a, b, c, d); } else { return 0; @@ -1237,7 +1237,7 @@ int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { } int pcap_findalldevs(pcap_if_t** a, char* b) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_findalldevs(a, b); } else { *a = 0; @@ -1247,22 +1247,22 @@ int pcap_findalldevs(pcap_if_t** a, char* b) { } void pcap_freealldevs(pcap_if_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { p_pcap_freealldevs(a); } } void pcap_freecode(struct bpf_program* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { p_pcap_freecode(a); } } char* pcap_geterr(pcap_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_geterr(a); } else { - return (char*) 0; + return (char*) ""; } } @@ -1284,15 +1284,15 @@ pcap_t* pcap_open_live(const char* a, int b, int c, int d, char* e) { #ifdef _WIN32 int pcap_setmintocopy(pcap_t* a, int b) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_setmintocopy(a, b); } else { - return 0; + return -1; } } HANDLE pcap_getevent(pcap_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_getevent(a); } else { return (HANDLE) 0; @@ -1302,7 +1302,7 @@ HANDLE pcap_getevent(pcap_t* a) { #else #ifdef MUST_DO_SELECT int pcap_get_selectable_fd(pcap_t* a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_get_selectable_fd(a); } else { return 0; @@ -1311,7 +1311,7 @@ int pcap_get_selectable_fd(pcap_t* a) { #endif int pcap_fileno(pcap_t * a) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_fileno(a); } else { return 0; @@ -1320,7 +1320,7 @@ int pcap_fileno(pcap_t * a) { #endif int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_sendpacket(a, b, c); } else { return 0; @@ -1328,7 +1328,7 @@ int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { } int pcap_setfilter(pcap_t* a, struct bpf_program* b) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_setfilter(a, b); } else { return 0; @@ -1336,7 +1336,7 @@ int pcap_setfilter(pcap_t* a, struct bpf_program* b) { } int pcap_setnonblock(pcap_t* a, int nonblock, char *errbuf) { - if (load_pcap() != 0) { + if (a && (load_pcap() != 0)) { return p_pcap_setnonblock(a, nonblock, errbuf); } else { return 0; @@ -2182,7 +2182,13 @@ else { /* !tap: */ } #endif /* xBSD */ #if defined(_WIN32) - pcap_setmintocopy ((pcap_t*)(*handle), 0); + if ((pcap_setmintocopy ((pcap_t*)(*handle), 0) == -1) || + (pcap_getevent ((pcap_t*)(*handle)) == NULL)) { + pcap_close ((pcap_t*)(*handle)); + errbuf[PCAP_ERRBUF_SIZE-1] = '\0'; + snprintf (errbuf, PCAP_ERRBUF_SIZE-1, "pcap can't initialize API for interface: %s", savname); + return SCPE_OPENERR; + } #endif #if !defined (USE_READER_THREAD) #ifdef USE_SETNONBLOCK @@ -4170,6 +4176,10 @@ int errors = 0; t_stat r; DEVICE eth_tst; ETH_DEV dev; +int eth_num; +int eth_opened; +ETH_LIST eth_list[ETH_MAX_DEVICE]; +int eth_device_count; int reflections, all_multicast, promiscuous; char buf[116+66*ETH_FILTER_MAX]; char mac[20]; @@ -4215,59 +4225,83 @@ int bpf_compile_skip_count = 0; memset (ð_tst, 0, sizeof(eth_tst)); -eth_open(&dev, "eth0", ð_tst, 1); -for (reflections=0; reflections<=1; reflections++) { - for (all_multicast=0; all_multicast<=1; all_multicast++) { - for (promiscuous=0; promiscuous<=1; promiscuous++) { - for (addr_count=1; addr_count<=2; addr_count++) { - for (hash_listindex=0; hash_listindex<=1; hash_listindex++) { - for (host_phy_addr_listindex=0; host_phy_addr_listindex<=1; host_phy_addr_listindex++) { - int i; - char errbuf[PCAP_ERRBUF_SIZE]; +eth_device_count = eth_devices(ETH_MAX_DEVICE, eth_list); +eth_opened = 0; +for (eth_num=0; eth_numname, eth_num, sim_error_text (r)); + continue; + } + ++eth_opened; + for (reflections=0; reflections<=1; reflections++) { + for (all_multicast=0; all_multicast<=1; all_multicast++) { + for (promiscuous=0; promiscuous<=1; promiscuous++) { + for (addr_count=1; addr_count<=2; addr_count++) { + for (hash_listindex=0; hash_listindex<=1; hash_listindex++) { + for (host_phy_addr_listindex=0; host_phy_addr_listindex<=1; host_phy_addr_listindex++) { + int i; + char errbuf[PCAP_ERRBUF_SIZE]; + + ++bpf_count; + r = eth_bpf_filter (&dev, addr_count, &filter_address[0], + all_multicast, promiscuous, reflections, + &filter_address[0], + host_phy_addr_list[host_phy_addr_listindex], + hash_list[hash_listindex], + buf); + if (r != SCPE_OK) { + ++bpf_construct_error_count; + sim_printf ("Eth: Error producing a BPF filter for:\n"); SIM_PRINT_BPF_ARGUMENTS; - sim_printf ("Eth: BPF string is: |%s|\n", buf); } - if (dev.eth_api == ETH_API_PCAP) { - struct bpf_program bpf; - - if (pcap_compile ((pcap_t*)dev.handle, &bpf, buf, 1, (bpf_u_int32)0) < 0) { - ++bpf_compile_error_count; - sprintf(errbuf, "%s", pcap_geterr((pcap_t*)dev.handle)); - sim_printf("Eth: pcap_compile error: %s\n", errbuf); - if (!(sim_switches & SWMASK('D'))) { - /* show erroneous BPF string */ - SIM_PRINT_BPF_ARGUMENTS; - sim_printf ("Eth: BPF string is: |%s|\n", buf); - } + else { + if (sim_switches & SWMASK('D')) { + SIM_PRINT_BPF_ARGUMENTS; + sim_printf ("Eth: BPF string is: |%s|\n", buf); } - pcap_freecode(&bpf); + if (dev.eth_api == ETH_API_PCAP) { + struct bpf_program bpf; + + if (pcap_compile ((pcap_t*)dev.handle, &bpf, buf, 1, (bpf_u_int32)0) < 0) { + ++bpf_compile_error_count; + sprintf(errbuf, "%s", pcap_geterr((pcap_t*)dev.handle)); + sim_printf("Eth: pcap_compile error: %s\n", errbuf); + if (!(sim_switches & SWMASK('D'))) { + /* show erroneous BPF string */ + SIM_PRINT_BPF_ARGUMENTS; + sim_printf ("Eth: BPF string is: |%s|\n", buf); + } + } + pcap_freecode(&bpf); + } + else + ++bpf_compile_skip_count; } - else - ++bpf_compile_skip_count; } } } } } } + eth_close(&dev); } -eth_close(&dev); -sim_printf ("BPF Filter Count: %d\n", bpf_count); + +if (eth_opened == 0) { + errors = 1; + sim_printf ("%s: No testable LAN interfaces found\n", dptr->name); + } +if (bpf_count) + sim_printf ("BPF Filter Count: %d\n", bpf_count); if (bpf_construct_error_count) sim_printf ("BPF Construct Errors: %d\n", bpf_construct_error_count); if (bpf_compile_error_count) diff --git a/sim_serial.c b/sim_serial.c index c5e10f4..dc13960 100644 --- a/sim_serial.c +++ b/sim_serial.c @@ -811,7 +811,7 @@ if (bits_to_clear&TMXR_MDM_RTS) } if (incoming_bits) { DWORD ModemStat; - if (GetCommModemStatus (port->hPort, &ModemStat)) { + if (!GetCommModemStatus (port->hPort, &ModemStat)) { sim_error_serial ("GetCommModemStatus", (int) GetLastError ()); return SCPE_IOERR; } diff --git a/sim_sock.h b/sim_sock.h index 326720c..6cf4365 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -90,8 +90,10 @@ extern "C" { #endif #define WSAEACCES EACCES #define WSAEINTR EINTR -#define INVALID_SOCKET ((SOCKET)-1) -#define SOCKET_ERROR -1 +#define INVALID_SOCKET ((SOCKET)-1) +#if !defined(SOCKET_ERROR) +#define SOCKET_ERROR (-1) +#endif #endif #if defined (VMS) /* VMS unique */ diff --git a/sim_tape.c b/sim_tape.c index 4df727b..e720c7a 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -102,7 +102,7 @@ struct sim_tape_fmt { const char *name; /* name */ - int32 uflags; /* unit flags */ + int32 uflags; /* unit flags */ t_addr bot; /* bot test */ t_addr eom_remnant; /* potentially unprocessed data */ }; @@ -113,7 +113,7 @@ static struct sim_tape_fmt fmts[MTUF_N_FMT] = { { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) }, { "P7B", 0, 0, 0 }, { "AWS", 0, 0, 0 }, -/* { "TPF", UNIT_RO, 0 }, */ + { "TAR", 0, 0, 0 }, { NULL, 0, 0 } }; @@ -132,7 +132,7 @@ static t_stat sim_tape_ioerr (UNIT *uptr); static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat); static t_stat sim_tape_aws_wrdata (UNIT *uptr, uint8 *buf, t_mtrlnt bc); static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize); -static t_stat sim_tape_scan_tape (UNIT *uptr); +static t_stat sim_tape_validate_tape (UNIT *uptr); static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map); static void sim_tape_data_trace (UNIT *uptr, const uint8 *data, size_t len, const char* txt, int detail, uint32 reason); static t_stat tape_erase_fwd (UNIT *uptr, t_mtrlnt gap_size); @@ -479,14 +479,31 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL) if (sim_switches & SWMASK ('F')) { /* format spec? */ cptr = get_glyph (cptr, gbuf, 0); /* get spec */ if (*cptr == 0) /* must be more */ - return SCPE_2FARG; + return sim_messagef (SCPE_2FARG, "Missing Format specifier and filename to attach\n"); if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) return sim_messagef (SCPE_ARG, "Invalid Tape Format: %s\n", gbuf); sim_switches = sim_switches & ~(SWMASK ('F')); /* Record Format specifier already processed */ auto_format = TRUE; } -if (MT_GET_FMT (uptr) == MTUF_F_TPC) - sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC tapes */ +if (MT_GET_FMT (uptr) == MTUF_F_TAR) { + if (sim_switches & SWMASK ('B')) { /* Record Size (blocking factor)? */ + uint32 recsize; + + cptr = get_glyph (cptr, gbuf, 0); /* get spec */ + if (*cptr == 0) /* must be more */ + return sim_messagef (SCPE_2FARG, "Missing Record Size and filename to attach\n"); + recsize = (uint32) get_uint (gbuf, 10, 65536, &r); + if ((r != SCPE_OK) || (recsize == 0)) + return sim_messagef (SCPE_ARG, "Invalid Tape Record Size: %s\n", gbuf); + uptr->recsize = recsize; + sim_switches = sim_switches & ~(SWMASK ('B')); /* Record Blocking Factor */ + } + if (uptr->recsize == 0) + uptr->recsize = TAR_DFLT_RECSIZE; + } +if ((MT_GET_FMT (uptr) == MTUF_F_TPC) || + (MT_GET_FMT (uptr) == MTUF_F_TAR)) + sim_switches |= SWMASK ('R'); /* Force ReadOnly attach for TPC and TAR tapes */ r = attach_unit (uptr, (CONST char *)cptr); /* attach unit */ if (r != SCPE_OK) /* error? */ return sim_messagef (r, "Can't open tape image: %s\n", cptr); @@ -522,12 +539,17 @@ switch (MT_GET_FMT (uptr)) { /* case on format */ sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */ break; + case MTUF_F_TAR: /* TAR */ + uptr->hwmark = (t_addr)sim_fsize (uptr->fileref); + break; + default: break; } if (r == SCPE_OK) { - sim_tape_scan_tape (uptr); + + sim_tape_validate_tape (uptr); sim_tape_rewind (uptr); @@ -568,7 +590,7 @@ if (ctx) sim_tape_clr_async (uptr); -MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */ +MT_CLR_INMRK (uptr); /* Not within an AWS or TAR tapemark */ r = detach_unit (uptr); /* detach unit */ if (r != SCPE_OK) return r; @@ -578,12 +600,14 @@ switch (f) { /* case on format */ if (uptr->filebuf) /* free map */ free (uptr->filebuf); uptr->filebuf = NULL; - uptr->hwmark = 0; break; default: break; } +uptr->hwmark = 0; +uptr->recsize = 0; +uptr->tape_eom = 0; sim_tape_rewind (uptr); free (uptr->tape_ctx); @@ -615,9 +639,16 @@ fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n"); fprintf (st, " virtual tape will be attempted).\n"); fprintf (st, " -F Open the indicated tape container in a specific format (default\n"); -fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n"); +fprintf (st, " is SIMH, alternatives are E11, TPC, P7B, AWS and TAR)\n"); +fprintf (st, " -B For TAR format tapes, the record size for data read from the\n"); +fprintf (st, " specified file. This record size will be used for all but\n"); +fprintf (st, " possibly the last record which will be what remains unread.\n"); +fprintf (st, " The default TAR record size is 10240.\n"); fprintf (st, " -V Display some summary information about the record structure\n"); -fprintf (st, " contained in the tape structure.\n"); +fprintf (st, " contained in the tape image scan performed when it is attached.\n"); +fprintf (st, " -L Display detailed record size counts observed during attach\n"); +fprintf (st, " validation pass\n"); +fprintf (st, " contained in the tape image scan performed when it is attached.\n"); fprintf (st, " -D Causes the internal tape structure information to be displayed\n"); fprintf (st, " while the tape image is scanned.\n"); return SCPE_OK; @@ -638,6 +669,7 @@ if (sim_deb && ((uptr->dctrl | ctx->dptr->dctrl) & reason)) Inputs: uptr = pointer to tape unit bc = pointer to returned record length + Outputs: status = operation status @@ -733,21 +765,29 @@ t_tpclnt tpcbc; t_awshdr awshdr; size_t rdcnt; t_mtrlnt buffer [256]; /* local tape buffer */ +t_addr saved_pos; uint32 bufcntr, bufcap; /* buffer counter and capacity */ int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */ t_stat status = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ +*bc = 0; if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ -if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) { /* set the initial tape position; if it fails */ +if ((uptr->tape_eom) && + (uptr->pos >= uptr->tape_eom)) { MT_SET_PNU (uptr); /* then set position not updated */ - status = sim_tape_ioerr (uptr); /* and quit with I/O error status */ + return MTSE_EOM; /* and quit with I/O error status */ } -else switch (f) { /* otherwise the read method depends on the tape format */ +if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) { /* set the initial tape position; if it fails */ + MT_SET_PNU (uptr); /* then set position not updated */ + return sim_tape_ioerr (uptr); /* and quit with I/O error status */ + } + +switch (f) { /* otherwise the read method depends on the tape format */ case MTUF_F_STD: case MTUF_F_E11: @@ -799,6 +839,7 @@ else switch (f) { /* otherwise the read me if (bufcntr == 0) { /* then if this is the initial read */ MT_SET_PNU (uptr); /* then set position not updated */ status = MTSE_EOM; /* and report the end-of-medium and quit */ + uptr->tape_eom = uptr->pos; break; } @@ -844,17 +885,12 @@ else switch (f) { /* otherwise the read me bufcntr = bufcap; /* mark the buffer as invalid to force a read */ - *bc = MTR_GAP; /* reset the marker */ + *bc = (t_mtrlnt)MTR_GAP; /* reset the marker */ runaway_counter -= sizeof_gap / 2; /* and decrement the gap counter */ } else { /* otherwise it's a record marker */ - if (bufcntr < bufcap /* if the position is within the buffer */ - && sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) { /* then seek to the data area; if it fails */ - status = sim_tape_ioerr (uptr); /* then quit with I/O error status */ - break; - } - + saved_pos = uptr->pos; /* Save data position */ sbc = MTR_L (*bc); /* extract the record length */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) /* position to the start */ + (f == MTUF_F_STD ? (sbc + 1) & ~1 : sbc); /* of the record */ @@ -865,8 +901,7 @@ else switch (f) { /* otherwise the read me if (runaway_counter <= 0) /* if a tape runaway occurred */ status = MTSE_RUNAWAY; /* then report it */ - if (status == MTSE_OK) { /* Validate the reverse record size */ - t_addr saved_pos = (t_addr)sim_ftell(uptr->fileref); + if (status == MTSE_OK) { /* Validate the reverse record size for data records */ t_mtrlnt rev_lnt; if (sim_fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET)){ /* then seek to the end of record size; if it fails */ @@ -883,21 +918,20 @@ else switch (f) { /* otherwise the read me status = sim_tape_ioerr (uptr); /* report the error and quit */ break; } - if (sim_fseek (uptr->fileref, saved_pos, SEEK_SET)){ /* then seek back to the beginning of the data; if it fails */ - status = sim_tape_ioerr (uptr); /* then quit with I/O error status */ - break; - } if (rev_lnt != *bc) { /* size mismatch? */ status = MTSE_INVRL; uptr->pos -= (sizeof (t_mtrlnt) + *bc + sizeof (t_mtrlnt)); MT_SET_PNU (uptr); /* pos not upd */ + break; } + if (sim_fseek (uptr->fileref, saved_pos, SEEK_SET)) /* then seek back to the beginning of the data; if it fails */ + status = sim_tape_ioerr (uptr); /* then quit with I/O error status */ } break; /* otherwise the operation succeeded */ case MTUF_F_TPC: (void)sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ + *bc = (t_mtrlnt)tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); /* pos not upd */ @@ -911,7 +945,7 @@ else switch (f) { /* otherwise the read me status = MTSE_EOM; } else { - uptr->pos = uptr->pos + sizeof (t_tpclnt); /* spc over reclnt */ + uptr->pos += sizeof (t_tpclnt); /* spc over reclnt */ if (tpcbc == TPC_TMK) /* tape mark? */ status = MTSE_TMK; else @@ -955,7 +989,6 @@ else switch (f) { /* otherwise the read me MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */ memset (&awshdr, 0, sizeof (awshdr)); rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref); - *bc = 0; if (ferror (uptr->fileref)) { /* error? */ MT_SET_PNU (uptr); /* pos not upd */ @@ -981,7 +1014,7 @@ else switch (f) { /* otherwise the read me else { /* tape data record */ t_addr saved_pos; - *bc = awshdr.nxtlen; /* save rec lnt */ + *bc = (t_mtrlnt)awshdr.nxtlen; /* save rec lnt */ uptr->pos += awshdr.nxtlen; /* spc over record */ memset (&awshdr, 0, sizeof (t_awslnt)); saved_pos = (t_addr)sim_ftell (uptr->fileref); @@ -999,6 +1032,26 @@ else switch (f) { /* otherwise the read me } break; + case MTUF_F_TAR: + if (uptr->pos < uptr->hwmark) { + if ((uptr->hwmark - uptr->pos) >= uptr->recsize) + *bc = (t_mtrlnt)uptr->recsize; /* TAR record size */ + else + *bc = (t_mtrlnt)(uptr->hwmark - uptr->pos); /* TAR remnant last record */ + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); + uptr->pos += *bc; + MT_CLR_INMRK (uptr); + } + else { + if (MT_TST_INMRK (uptr)) + status = MTSE_EOM; + else { + status = MTSE_TMK; + MT_SET_INMRK (uptr); + } + } + break; + default: status = MTSE_FMT; } @@ -1075,6 +1128,7 @@ int32 runaway_counter, sizeof_gap; /* bytes remaining befor t_stat status = MTSE_OK; MT_CLR_PNU (uptr); /* clear the position-not-updated flag */ +*bc = 0; if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */ return MTSE_UNATT; /* then quit with an error */ @@ -1150,7 +1204,7 @@ else switch (f) { /* otherwise the read me uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2; /* then position forward to resync */ bufcntr = 0; /* mark the buffer as invalid to force a read */ - *bc = MTR_GAP; /* reset the marker */ + *bc = (t_mtrlnt)MTR_GAP; /* reset the marker */ runaway_counter -= sizeof_gap / 2; /* and decrement the gap counter */ } @@ -1178,7 +1232,7 @@ else switch (f) { /* otherwise the read me ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf); /* find prev rec */ (void)sim_fseek (uptr->fileref, ppos, SEEK_SET);/* position */ (void)sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ + *bc = (t_mtrlnt)tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) /* error? */ status = sim_tape_ioerr (uptr); @@ -1194,34 +1248,50 @@ else switch (f) { /* otherwise the read me break; case MTUF_F_P7B: - for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) { - (void)sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET); - (void)sim_fread (&c, sizeof (uint8), 1, uptr->fileref); + if (1) { +#define BUF_SZ 512 + uint8 buf[BUF_SZ]; + t_addr buf_offset; + size_t bytes_in_buf = 0; + size_t read_size; - if (ferror (uptr->fileref)) { /* error? */ - status = sim_tape_ioerr (uptr); - break; - } - else if (feof (uptr->fileref)) { /* eof? */ - status = MTSE_EOM; - break; - } - else { + for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) { + if (bytes_in_buf == 0) { /* Need to Fill Buffer */ + if (uptr->pos < BUF_SZ) { + buf_offset = 0; + read_size = (size_t)uptr->pos; + } + else { + buf_offset = uptr->pos - (sbc - 1 + BUF_SZ); + read_size = BUF_SZ; + } + (void)sim_fseek (uptr->fileref, buf_offset, SEEK_SET); + bytes_in_buf = sim_fread (buf, sizeof (uint8), read_size, uptr->fileref); + if (ferror (uptr->fileref)) { /* error? */ + status = sim_tape_ioerr (uptr); + break; + } + if (feof (uptr->fileref)) { /* eof? */ + status = MTSE_EOM; + break; + } + } + c = buf[--bytes_in_buf]; if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; if (c & P7B_SOR) /* start of record? */ break; } - } - if (status == MTSE_OK) { - uptr->pos = uptr->pos - sbc; /* update position */ - *bc = sbc; /* save rec lnt */ - (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for next read */ - if (all_eof) /* tape mark? */ - status = MTSE_TMK; + if (status == MTSE_OK) { + uptr->pos = uptr->pos - sbc; /* update position */ + *bc = sbc; /* save rec lnt */ + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for next read */ + if (all_eof) /* tape mark? */ + status = MTSE_TMK; + } + break; } - break; case MTUF_F_AWS: *bc = sbc = 0; @@ -1259,7 +1329,7 @@ else switch (f) { /* otherwise the read me if (MT_TST_INMRK (uptr)) /* already in a tapemark? */ awshdr.rectyp = AWS_REC; MT_CLR_INMRK (uptr); /* No longer in a tapemark */ - *bc = (awshdr.rectyp == AWS_REC) ? awshdr.prelen : 0;/* save rec lnt */ + *bc = (t_mtrlnt)((awshdr.rectyp == AWS_REC) ? awshdr.prelen : 0);/* save rec lnt */ sbc = *bc; /* extract the record length */ if ((awshdr.rectyp != AWS_TMK) || (awshdr.prelen == 0)) { @@ -1281,7 +1351,28 @@ else switch (f) { /* otherwise the read me } break; - default: + case MTUF_F_TAR: + if (uptr->pos == uptr->hwmark) { + if (MT_TST_INMRK (uptr)) { + status = MTSE_TMK; + MT_CLR_INMRK (uptr); + } + else { + if (uptr->hwmark % uptr->recsize) + *bc = (t_mtrlnt)(uptr->hwmark % uptr->recsize); + else + *bc = (t_mtrlnt)uptr->recsize; + } + } + else + *bc = (t_mtrlnt)uptr->recsize; + if (*bc) { + uptr->pos -= *bc; + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); + } + break; + + default: status = MTSE_FMT; } @@ -1504,6 +1595,8 @@ switch (f) { /* case on format */ return status; break; } +if (uptr->pos > uptr->tape_eom) + uptr->tape_eom = uptr->pos; /* update EOM as needed */ sim_tape_data_trace(uptr, buf, sbc, "Record Written", (uptr->dctrl | ctx->dptr->dctrl) & MTSE_DBG_DAT, MTSE_DBG_STR); return MTSE_OK; } @@ -1556,6 +1649,8 @@ if ((!replacing_record) || (bc == 0)) { if (!replacing_record) sim_set_fsize (uptr->fileref, uptr->pos + sizeof (awshdr)); } +if (uptr->pos > uptr->tape_eom) + uptr->tape_eom = uptr->pos; /* Update EOM if we're there */ return MTSE_OK; } @@ -1580,6 +1675,8 @@ if (ferror (uptr->fileref)) { /* error? */ } sim_debug_unit (MTSE_DBG_STR, uptr, "wr_lnt: lnt: %d, pos: %" T_ADDR_FMT "u\n", dat, uptr->pos); uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */ +if (uptr->pos > uptr->tape_eom) + uptr->tape_eom = uptr->pos; /* update EOM */ return MTSE_OK; } @@ -2568,7 +2665,10 @@ if (uptr->flags & UNIT_ATT) { sim_debug_unit (ctx->dbit, uptr, "sim_tape_rewind(unit=%d)\n", (int)(uptr-ctx->dptr->units)); } uptr->pos = 0; +if (uptr->flags & UNIT_ATT) + (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); MT_CLR_PNU (uptr); +MT_CLR_INMRK (uptr); /* Not within an AWS or TAR tapemark */ return MTSE_OK; } @@ -2841,7 +2941,7 @@ sprintf(msgbuf, "Error %d", stat); return msgbuf; } -static t_stat sim_tape_scan_tape (UNIT *uptr) +static t_stat sim_tape_validate_tape (UNIT *uptr) { t_addr saved_pos = uptr->pos; uint32 record_in_file = 0; @@ -2849,13 +2949,14 @@ uint32 data_total = 0; uint32 tapemark_total = 0; uint32 record_total = 0; uint32 unique_record_sizes = 0; +uint32 remaining_data = 0; +uint32 *rec_sizes = NULL; t_stat r = SCPE_OK; t_stat r_f; t_stat r_r; t_stat r_s; uint8 *buf_f = NULL; uint8 *buf_r = NULL; -uint32 *rec_sizes = NULL; t_mtrlnt bc_f; t_mtrlnt bc_r; t_mtrlnt bc_s; @@ -2866,10 +2967,10 @@ t_mtrlnt max = MTR_MAXLEN; if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; -buf_f = (uint8 *)malloc (max); +buf_f = (uint8 *)calloc (1, max); if (buf_f == NULL) return SCPE_MEM; -buf_r = (uint8 *)malloc (max); +buf_r = (uint8 *)calloc (1, max); if (buf_r == NULL) { free (buf_f); return SCPE_MEM; @@ -2882,6 +2983,8 @@ if (rec_sizes == NULL) { } r = sim_tape_rewind (uptr); while (r == SCPE_OK) { + if (stop_cpu) /* SIGINT? */ + break; pos_f = uptr->pos; r_f = sim_tape_rdrecf (uptr, buf_f, &bc_f, max); switch (r_f) { @@ -2904,13 +3007,15 @@ while (r == SCPE_OK) { break; } if (bc_f != bc_r) { - sim_printf ("Forward Record Read record lemgtj: %d, Reverse read record length: %d\n", bc_f, bc_r); + sim_printf ("Forward Record Read record length: %d, Reverse read record length: %d\n", bc_f, bc_r); break; } if (0 != memcmp (buf_f, buf_r, bc_f)) { sim_printf ("%d byte record contents differ when read forward amd backwards start from position %" T_ADDR_FMT "u\n", bc_f, pos_f); break; } + memset (buf_f, 0, bc_f); + memset (buf_r, 0, bc_f); if (pos_f != pos_r) { sim_printf ("Unexpected tape file position between forward and reverse record read: (%" T_ADDR_FMT "u, %" T_ADDR_FMT "u\n", pos_f, pos_r); break; @@ -2941,11 +3046,12 @@ while (r == SCPE_OK) { break; } } -if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) || - ((uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) || - (unique_record_sizes > 2 * tapemark_total)) { - uint32 remaining_data = (uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos); - +uptr->tape_eom = uptr->pos; +if ((!stop_cpu) && + ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) || (sim_switches & SWMASK ('L')) || + ((uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) || + (unique_record_sizes > 2 * tapemark_total))) { + remaining_data = (uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->tape_eom); sim_printf ("Tape Image '%s' scanned as %s format.\n", uptr->filename, fmts[MT_GET_FMT (uptr)].name); if (r != MTSE_EOM) sim_printf ("After processing "); @@ -2953,8 +3059,8 @@ if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) || sim_printf ("contains "); sim_printf ("%u bytes of tape data (%u records, %u tapemarks)\n", data_total, record_total, tapemark_total); - if (record_total > 0) { - sim_printf ("Comprising (in record size order):\n"); + if ((record_total > 0) && (sim_switches & SWMASK ('L'))) { + sim_printf ("Comprising %d different sized records (in record size order):\n", unique_record_sizes); for (bc = 0; bc <= max; bc++) { if (rec_sizes[bc]) sim_printf ("%8u %u byte records\n", rec_sizes[bc], (uint32)bc); @@ -2965,8 +3071,8 @@ if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) || if (remaining_data > fmts[MT_GET_FMT (uptr)].eom_remnant) sim_printf ("%u bytes of unexamined data remain in the tape image file\n", remaining_data); } -/* Try again reading backwards */ -if (unique_record_sizes > 2 * tapemark_total) { +if ((!stop_cpu) && + (unique_record_sizes > 2 * tapemark_total)) { sim_printf ("An unreasonable number of record sizes(%u) vs tape marks (%u) have been found\n", unique_record_sizes, tapemark_total); sim_printf ("The tape format (%s) might not be correct for the '%s' tape image\n", fmts[MT_GET_FMT (uptr)].name, uptr->filename); } @@ -2975,6 +3081,7 @@ free (buf_f); free (buf_r); free (rec_sizes); uptr->pos = saved_pos; +(void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); return SCPE_OK; } @@ -3116,6 +3223,45 @@ else { /* otherwise get the den return SCPE_OK; } +/* list supported densities + + translates the mask of supported densities to a string list in the form: + + "(800|1600|6250)" + + this string may be useful to construct a MTAB help string for a + SET DENSITY= command. + +*/ + +t_stat sim_tape_density_supported (char *string, size_t string_size, int32 valid_bits) +{ +uint32 density; +int32 count; + +strlcpy (string, "", string_size); +if ((!valid_bits) || (valid_bits >> BPI_COUNT)) + return SCPE_ARG; +for (density = count = 0; density < BPI_COUNT; density++) { + if (valid_bits & (1 << density)) { + char density_str[20]; + + ++count; + if (count == 1) + strlcat (string, "{", string_size); + else + strlcat (string, "|", string_size); + sprintf (density_str, "%d", bpi[density]); + strlcat (string, density_str, string_size); + } + } +if ((count == 1) && (string_size > 1)) + memmove (string, string + 1, strlen (string)); +else + strlcat (string, "}", string_size); +return SCPE_OK; +} + static DEBTAB tape_debug[] = { {"TRACE", MTSE_DBG_API, "API Trace"}, {"DATA", MTSE_DBG_DAT, "Tape Data"}, @@ -3135,13 +3281,15 @@ static t_bool p7b_parity_inited = FALSE; static uint8 p7b_odd_parity[64]; static uint8 p7b_even_parity[64]; -static t_stat create_tape_files (UNIT *uptr, const char *filename, int files, int records, int max_size) +static t_stat sim_tape_test_create_tape_files (UNIT *uptr, const char *filename, int files, int records, int max_size) { FILE *fSIMH = NULL; FILE *fE11 = NULL; FILE *fTPC = NULL; FILE *fP7B = NULL; FILE *fAWS = NULL; +FILE *fTAR = NULL; +FILE *fTAR2 = NULL; int i, j, k; t_tpclnt tpclnt; t_mtrlnt mtrlnt; @@ -3189,6 +3337,14 @@ sprintf (name, "%s.p7b", filename); fP7B = fopen (name, "wb"); if (fP7B == NULL) goto Done_Files; +sprintf (name, "%s.tar", filename); +fTAR = fopen (name, "wb"); +if (fTAR == NULL) + goto Done_Files; +sprintf (name, "%s.2.tar", filename); +fTAR2 = fopen (name, "wb"); +if (fTAR2 == NULL) + goto Done_Files; sprintf (name, "%s.aws", filename); fAWS = fopen (name, "wb"); if (fAWS == NULL) @@ -3267,6 +3423,24 @@ tpclnt = 0xffff; (void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11); (void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC); (void)sim_fwrite (buf, 1, 1, fP7B); +/* Write an unmatched record delimiter (aka garbage) at + the end of the SIMH, E11 and AWS files */ +mtrlnt = 25; +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fAWS); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fAWS); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fAWS); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, uptr->fileref); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, uptr->fileref); +(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, uptr->fileref); +for (j=0; junits)); -SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1")); +SIM_TEST(sim_tape_test_density_string ()); -SIM_TEST(create_tape_files (dptr->units, "TapeTestFile1", 2, 4, 4096)); +SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1")); + +SIM_TEST(sim_tape_test_create_tape_files (dptr->units, "TapeTestFile1", 2, 5, 4096)); sim_switches = saved_switches; -SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "aws")); +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "tar")); sim_switches = saved_switches; -SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "p7b")); +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1.2", "tar")); sim_switches = saved_switches; -SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "tpc")); +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "aws")); sim_switches = saved_switches; -SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "e11")); +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "p7b")); sim_switches = saved_switches; -SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "simh")); +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "tpc")); -SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1")); +sim_switches = saved_switches; +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "e11")); + +sim_switches = saved_switches; +SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "simh")); + +SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1")); return SCPE_OK; } diff --git a/sim_tape.h b/sim_tape.h index 26abba6..402d224 100644 --- a/sim_tape.h +++ b/sim_tape.h @@ -57,7 +57,7 @@ typedef uint32 t_mtrlnt; /* magtape rec lnt */ #define MTR_MAXLEN 0x00FFFFFF /* max len is 24b */ #define MTR_ERF 0x80000000 /* error flag */ #define MTR_F(x) ((x) & MTR_ERF) /* record error flg */ -#define MTR_L(x) ((x) & ~MTR_ERF) /* record length */ +#define MTR_L(x) ((t_mtrlnt)((x) & ~MTR_ERF)) /* record length */ /* TPC tape format */ @@ -85,6 +85,9 @@ typedef struct { #define AWS_REC 0x00A0 } t_awshdr; +/* TAR tape format */ +#define TAR_DFLT_RECSIZE 10240 /* Default Fixed record size */ + /* Unit flags */ #define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */ @@ -98,6 +101,7 @@ typedef struct { #define MTUF_F_TPC 2 /* TPC format */ #define MTUF_F_P7B 3 /* P7B format */ #define MTUF_F_AWS 4 /* AWS format */ +#define MTUF_F_TAR 5 /* TAR format */ #define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT) #define MTUF_PNU (1u << MTUF_V_PNU) #define MTUF_WLK (1u << MTUF_V_WLK) @@ -109,6 +113,7 @@ typedef struct { #define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT) #define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT) #define MT_F_AWS (MTUF_F_AWS << MTUF_V_FMT) +#define MT_F_TAR (MTUF_F_TAR << MTUF_V_FMT) #define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU #define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU @@ -224,6 +229,7 @@ t_stat sim_tape_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat sim_tape_density_supported (char *string, size_t string_size, int32 valid_bits); t_stat sim_tape_set_asynch (UNIT *uptr, int latency); t_stat sim_tape_clr_asynch (UNIT *uptr); t_stat sim_tape_test (DEVICE *dptr); diff --git a/sim_video.c b/sim_video.c index 9f3ed39..d1475fb 100644 --- a/sim_video.c +++ b/sim_video.c @@ -361,13 +361,12 @@ t_bool vid_key_state[SDL_NUM_SCANCODES]; SDL_Texture *vid_texture; /* video buffer in GPU */ SDL_Renderer *vid_renderer; SDL_Window *vid_window; /* window handle */ +SDL_PixelFormat *vid_format; uint32 vid_windowID; #endif SDL_Thread *vid_thread_handle = NULL; /* event thread handle */ SDL_Cursor *vid_cursor = NULL; /* current cursor */ t_bool vid_cursor_visible = FALSE; /* cursor visibility state */ -uint32 vid_mono_palette[2]; /* Monochrome Color Map */ -SDL_Color vid_colors[256]; KEY_EVENT_QUEUE vid_key_events; /* keyboard events */ MOUSE_EVENT_QUEUE vid_mouse_events; /* mouse events */ DEVICE *vid_dev; @@ -631,6 +630,15 @@ if (SDL_SemTryWait (vid_mouse_events.sem) == 0) { return stat; } +uint32 vid_map_rgb (uint8 r, uint8 g, uint8 b) +{ +#if SDL_MAJOR_VERSION == 1 +return SDL_MapRGB (vid_image->format, r, g, b); +#else +return SDL_MapRGB (vid_format, r, g, b); +#endif +} + void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf) { #if SDL_MAJOR_VERSION == 1 @@ -1604,9 +1612,6 @@ if (!initialized) { sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_thread() - Starting\n"); -vid_mono_palette[0] = sim_end ? 0xFF000000 : 0x000000FF; /* Black */ -vid_mono_palette[1] = 0xFFFFFFFF; /* White */ - memset (&vid_key_state, 0, sizeof(vid_key_state)); #if SDL_MAJOR_VERSION == 1 @@ -1646,6 +1651,8 @@ if (!vid_texture) { return 0; } +vid_format = SDL_AllocFormat (SDL_PIXELFORMAT_ARGB8888); + SDL_StopTextInput (); vid_windowID = SDL_GetWindowID (vid_window); @@ -2317,8 +2324,6 @@ SDL_Delay (vid_beep_duration + 100);/* Wait for sound to finnish */ #else /* !(defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL)) */ /* Non-implemented versions */ -uint32 vid_mono_palette[2]; /* Monochrome Color Map */ - t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags) { return SCPE_NOFNC; @@ -2339,6 +2344,11 @@ t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev) return SCPE_EOF; } +uint32 vid_map_rgb (uint8 r, uint8 g, uint8 b) +{ +return 0; +} + void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf) { return; diff --git a/sim_video.h b/sim_video.h index 210bcd6..47bb8bb 100644 --- a/sim_video.h +++ b/sim_video.h @@ -183,6 +183,7 @@ t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback); t_stat vid_close (void); t_stat vid_poll_kb (SIM_KEY_EVENT *ev); t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev); +uint32 vid_map_rgb (uint8 r, uint8 g, uint8 b); void vid_draw (int32 x, int32 y, int32 w, int32 h, uint32 *buf); void vid_beep (void); void vid_refresh (void); @@ -196,7 +197,6 @@ t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* des t_stat vid_screenshot (const char *filename); extern t_bool vid_active; -extern uint32 vid_mono_palette[2]; void vid_set_cursor_position (int32 x, int32 y); /* cursor position (set by calling code) */ /* A device simulator can optionally set the vid_display_kb_event_process