mirror of
https://github.com/simh/simh.git
synced 2026-02-16 20:52:19 +00:00
Notes For V3.7-0
1. New Features 1.1 3.7-0 1.1.1 SCP - Added SET THROTTLE and SET NOTHROTTLE commands to regulate simulator execution rate and host resource utilization. - Added idle support (based on work by Mark Pizzolato). - Added -e to control error processing in nested DO commands (from Dave Bryan). 1.1.2 HP2100 - Added Double Integer instructions, 1000-F CPU, and Floating Point Processor (from Dave Bryan). - Added 2114 and 2115 CPUs, 12607B and 12578A DMA controllers, and 21xx binary loader protection (from Dave Bryan). 1.1.3 Interdata - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state. 1.1.4 PDP-11 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (WAIT instruction executed). - Added TA11/TU60 cassette support. 1.1.5 PDP-8 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (keyboard poll loop or jump-to-self). - Added TA8E/TU60 cassette support. 1.1.6 PDP-1 - Added support for 16-channel sequence break system. - Added support for PDP-1D extended features and timesharing clock. - Added support for Type 630 data communications subsystem. 1.1.6 PDP-4/7/9/15 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (keyboard poll loop or jump-to-self). 1.1.7 VAX, VAX780 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (more than 200 cycles at IPL's 0, 1, or 3 in kernel mode). 1.1.8 PDP-10 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (operating system dependent). - Added CD20 (CD11) support. 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
committed by
Mark Pizzolato
parent
15919a2dd7
commit
53d02f7fa7
@@ -1,4 +1,4 @@
|
||||
// DMS R2V12 SLET without RPG, for debugging only
|
||||
/* DMS R2V12 SLET without RPG, for debugging only */
|
||||
|
||||
0x0001, 0x7c50, 0x032f, 0x0008,
|
||||
0x0002, 0x11de, 0x05a2, 0x000b,
|
||||
|
||||
@@ -9,15 +9,17 @@
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// 03 ctrl-C => Program stop (not handled here)
|
||||
// 05 ctrl-E => Simulator stop (not handled here)
|
||||
// 08 ctrl-H => Backspace
|
||||
// 0D ctrl-M (Enter) => EOF
|
||||
// 11 ctrl-Q => Interrupt request (not handled here)
|
||||
// 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard)
|
||||
// 15 ctrl-U => Erase Field
|
||||
// 7E ~ => "not"
|
||||
// FF Del => Backspace again
|
||||
/*
|
||||
* 03 ctrl-C => Program stop (not handled here)
|
||||
* 05 ctrl-E => Simulator stop (not handled here)
|
||||
* 08 ctrl-H => Backspace
|
||||
* 0D ctrl-M (Enter) => EOF
|
||||
* 11 ctrl-Q => Interrupt request (not handled here)
|
||||
* 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard)
|
||||
* 15 ctrl-U => Erase Field
|
||||
* 7E ~ => "not"
|
||||
* FF Del => Backspace again
|
||||
*/
|
||||
|
||||
static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,11 @@
|
||||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
|
||||
#ifndef _WIN32
|
||||
int strnicmp (char *a, char *b, int n);
|
||||
int strcmpi (char *a, char *b);
|
||||
int strnicmp (const char *a, const char *b, int n);
|
||||
int strcmpi (const char *a, const char *b);
|
||||
#endif
|
||||
|
||||
// #define GUI_SUPPORT // uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile
|
||||
/* #define GUI_SUPPORT uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Architectural constants */
|
||||
@@ -40,14 +40,13 @@
|
||||
#define INIMEMSIZE (16384) /* 16Kwords */
|
||||
#define MEMSIZE (cpu_unit.capac)
|
||||
|
||||
#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* flag for memory size setting */
|
||||
|
||||
#define ILL_ADR_FLAG 0x40000000 /* an impossible 1130 address */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Global state */
|
||||
|
||||
extern int cgi; // TRUE if we are running as a CGI program
|
||||
extern int cgi; /* TRUE if we are running as a CGI program */
|
||||
extern int cgiwritable; /* TRUE if we can write the disk images back to the image file in CGI mode */
|
||||
extern int sim_gui;
|
||||
|
||||
extern uint16 M[]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */
|
||||
@@ -58,6 +57,7 @@ extern int32 SAR, SBR; /* storage address/buffer registers */
|
||||
extern int32 OP, TAG, CCC; /* instruction decoded pieces */
|
||||
extern int32 CES; /* console entry switches */
|
||||
extern int32 ACC, EXT; /* accumulator and extension */
|
||||
extern int32 ARF; /* arithmetic factor register, a nonaddressable internal CPU register */
|
||||
extern int32 RUNMODE; /* processor run/step mode */
|
||||
extern int32 ipl; /* current interrupt level (-1 = not handling irq) */
|
||||
extern int32 iplpending; /* interrupted IPL's */
|
||||
@@ -71,9 +71,11 @@ extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */
|
||||
extern int32 mem_mask;
|
||||
extern int32 cpu_dsw; /* CPU device status word */
|
||||
extern int32 sim_int_char; /* interrupt character */
|
||||
extern int32 con_dsw; /* has program stop and int run bits */
|
||||
extern t_bool running;
|
||||
extern t_bool power;
|
||||
extern t_bool cgi; /* TRUE if we are running as a CGI program */
|
||||
extern t_bool cgiwritable; /* TRUE if we can write to the disk image file in CGI mode */
|
||||
extern t_stat reason; /* CPU execution loop control */
|
||||
|
||||
#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/
|
||||
@@ -131,15 +133,19 @@ void WriteW (int32 a, int32 d);
|
||||
#define STOP_PHASE_BREAK 7 /* phase load break */
|
||||
#define STOP_CRASH 8 /* program has crashed badly */
|
||||
#define STOP_TIMED_OUT 9 /* simulation time limit exceeded */
|
||||
#define STOP_IMMEDIATE 10 /* simulator stop key pressed (immediate stop) */
|
||||
#define STOP_BREAK 11 /* simulator break key pressed */
|
||||
#define STOP_STEP 12 /* step count expired */
|
||||
#define STOP_OTHER 13 /* other reason, probably error returned by sim_process_event() */
|
||||
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||
|
||||
#define INT_REQ_0 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */
|
||||
#define INT_REQ_1 0x02
|
||||
#define INT_REQ_2 0x04
|
||||
#define INT_REQ_3 0x08
|
||||
#define INT_REQ_4 0x10
|
||||
#define INT_REQ_5 0x20
|
||||
#define INT_REQ_5 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */
|
||||
#define INT_REQ_4 0x02
|
||||
#define INT_REQ_3 0x04
|
||||
#define INT_REQ_2 0x08
|
||||
#define INT_REQ_1 0x10
|
||||
#define INT_REQ_0 0x20
|
||||
|
||||
#define XIO_UNUSED 0x00 /* XIO commands */
|
||||
#define XIO_WRITE 0x01
|
||||
@@ -156,7 +162,7 @@ void WriteW (int32 a, int32 d);
|
||||
|
||||
#define ILSW_0_1442_CARD 0x8000 /* ILSW 0 is not really defined on the 1130 */
|
||||
|
||||
#define ILSW_1_1132_PRINTER 0x8000 // had these backwards!
|
||||
#define ILSW_1_1132_PRINTER 0x8000 /* had these backwards! */
|
||||
#define ILSW_1_SCA 0x4000
|
||||
|
||||
#define ILSW_2_1131_DISK 0x8000
|
||||
@@ -215,13 +221,13 @@ void WriteW (int32 a, int32 d);
|
||||
#define ILSW_4_SAC_BIT_09 0x0040
|
||||
#define ILSW_4_SAC_BIT_10 0x0020
|
||||
#define ILSW_4_SAC_BIT_11 0x0010
|
||||
#define ILSW_4_T2741_TERMINAL 0x0010 /* APL\1130 nonstandard serial interface uses this bit */
|
||||
#define ILSW_4_SAC_BIT_12 0x0008
|
||||
#define ILSW_4_SAC_BIT_13 0x0004
|
||||
#define ILSW_4_SAC_BIT_14 0x0002
|
||||
#define ILSW_4_SAC_BIT_15 0x0001
|
||||
|
||||
#define ILSW_5_INT_RUN 0x8000
|
||||
#define ILSW_5_PROGRAM_STOP 0x8000
|
||||
#define ILSW_5_INT_RUN_PROGRAM_STOP 0x8000 /* this replaces both ILSW_5_INT_RUN and ILSW_5_PROGRAM_STOP */
|
||||
#define ILSW_5_SAC_BIT_01 0x4000
|
||||
#define ILSW_5_SAC_BIT_02 0x2000
|
||||
#define ILSW_5_SAC_BIT_03 0x1000
|
||||
@@ -238,26 +244,27 @@ void WriteW (int32 a, int32 d);
|
||||
#define ILSW_5_SAC_BIT_14 0x0002
|
||||
#define ILSW_5_SAC_BIT_15 0x0001
|
||||
|
||||
//* CPU DSW bits
|
||||
/* CPU DSW bits */
|
||||
|
||||
#define CPU_DSW_PROGRAM_STOP 0x8000
|
||||
#define CPU_DSW_INT_RUN 0x4000
|
||||
|
||||
/* prototypes: xio handlers */
|
||||
|
||||
void xio_1131_console (int32 addr, int32 func, int32 modify); // console keyboard and printer
|
||||
void xio_1142_card (int32 addr, int32 func, int32 modify); // standard card reader/punch
|
||||
void xio_1134_papertape (int32 addr, int32 func, int32 modify); // paper tape reader/punch
|
||||
void xio_disk (int32 addr, int32 func, int32 modify, int drv); // internal CPU disk
|
||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify); // XY plotter
|
||||
void xio_1132_printer (int32 addr, int32 func, int32 modify); // standard line printer
|
||||
void xio_1131_switches (int32 addr, int32 func, int32 modify); // console buttons & switches
|
||||
void xio_1231_optical (int32 addr, int32 func, int32 modify); // optical mark page reader
|
||||
void xio_2501_card (int32 addr, int32 func, int32 modify); // alternate high-speed card reader
|
||||
void xio_1131_synch (int32 addr, int32 func, int32 modify); // synchronous communications adapter
|
||||
void xio_system7 (int32 addr, int32 func, int32 modify); // system/7 interprocessor IO link
|
||||
void xio_1403_printer (int32 addr, int32 func, int32 modify); // alternate high-speed printer
|
||||
void xio_2250_display (int32 addr, int32 func, int32 modify); // vector display processor
|
||||
void xio_1131_console (int32 addr, int32 func, int32 modify); /* console keyboard and printer */
|
||||
void xio_1142_card (int32 addr, int32 func, int32 modify); /* standard card reader/punch */
|
||||
void xio_1134_papertape (int32 addr, int32 func, int32 modify); /* paper tape reader/punch */
|
||||
void xio_disk (int32 addr, int32 func, int32 modify, int drv); /* internal CPU disk */
|
||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify); /* XY plotter */
|
||||
void xio_1132_printer (int32 addr, int32 func, int32 modify); /* standard line printer */
|
||||
void xio_1131_switches (int32 addr, int32 func, int32 modify); /* console buttons & switches */
|
||||
void xio_1231_optical (int32 addr, int32 func, int32 modify); /* optical mark page reader */
|
||||
void xio_2501_card (int32 addr, int32 func, int32 modify); /* alternate high-speed card reader */
|
||||
void xio_sca (int32 addr, int32 func, int32 modify); /* synchronous communications adapter */
|
||||
void xio_system7 (int32 addr, int32 func, int32 modify); /* system/7 interprocessor IO link */
|
||||
void xio_1403_printer (int32 addr, int32 func, int32 modify); /* alternate high-speed printer */
|
||||
void xio_2250_display (int32 addr, int32 func, int32 modify); /* vector display processor */
|
||||
void xio_t2741_terminal (int32 addr, int32 func, int32 modify); /* IO selectric via nonstandard serial interface for APL */
|
||||
void xio_error (char *msg);
|
||||
|
||||
void bail (char *msg);
|
||||
@@ -267,6 +274,8 @@ t_stat cr_rewind (void);
|
||||
t_stat cr_detach (UNIT *uptr);
|
||||
void calc_ints (void); /* recalculate interrupt bitmask */
|
||||
void trace_io (char *fmt, ...); /* debugging printout */
|
||||
void trace_both (char *fmt, ...); /* debugging printout */
|
||||
t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help);
|
||||
void scp_panic (char *msg); /* bail out of simulator */
|
||||
char *upcase(char *str);
|
||||
void break_simulation (t_stat reason); /* let a device halt the simulation */
|
||||
|
||||
@@ -14,6 +14,13 @@ commands may NOT be accurate. This should probably be fixed.
|
||||
* or modifications.
|
||||
*
|
||||
* Revision History
|
||||
* 05-dec-06 Added cgiwritable mode
|
||||
*
|
||||
* 19-Dec-05 We no longer issue an operation complete interrupt if an INITR, INITW
|
||||
* or CONTROL operation is attemped on a drive that is not online. DATA_ERROR
|
||||
* is now only indicated in the DSW when
|
||||
*
|
||||
* 02-Nov-04 Addes -s option to boot to leave switches alone.
|
||||
* 15-jun-03 moved actual read on XIO read to end of time interval,
|
||||
* as the APL boot card required 2 instructions to run between the
|
||||
* time read was initiated and the time the data was read (a jump and a wait)
|
||||
@@ -29,7 +36,7 @@ commands may NOT be accurate. This should probably be fixed.
|
||||
#include "ibm1130_defs.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define TRACE_DMS_IO // define to enable debug of DMS phase IO
|
||||
#define TRACE_DMS_IO /* define to enable debug of DMS phase IO */
|
||||
|
||||
#ifdef TRACE_DMS_IO
|
||||
extern int32 sim_switches;
|
||||
@@ -86,7 +93,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr);
|
||||
static t_stat dsk_detach (UNIT *uptr);
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr);
|
||||
|
||||
static void diskfail (UNIT *uptr, int errflag);
|
||||
static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt);
|
||||
|
||||
/* DSK data structures
|
||||
|
||||
@@ -180,16 +187,17 @@ extern void void_backtrace (int afrom, int ato);
|
||||
void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
{
|
||||
int i, rev, nsteps, newcyl, sec, nwords;
|
||||
uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development
|
||||
uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */
|
||||
char msg[80];
|
||||
UNIT *uptr = dsk_unit+drv;
|
||||
int16 buf[DSK_NUMWD];
|
||||
|
||||
if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { // hmmm, invalid drive */
|
||||
if (func != XIO_SENSE_DEV) { // tried to use it, too
|
||||
// just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads
|
||||
// sprintf(msg, "Op %x on invalid drive number %d", func, drv);
|
||||
// xio_error(msg);
|
||||
if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { /* hmmm, invalid drive */
|
||||
if (func != XIO_SENSE_DEV) { /* tried to use it, too */
|
||||
/* just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads
|
||||
sprintf(msg, "Op %x on invalid drive number %d", func, drv);
|
||||
xio_error(msg);
|
||||
*/
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -199,7 +207,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
switch (func) {
|
||||
case XIO_INITR:
|
||||
if (! IS_ONLINE(uptr)) { /* disk is offline */
|
||||
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -219,11 +227,12 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
sec = modify & 0x07; /* get sector on cylinder */
|
||||
|
||||
if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */
|
||||
// ah. We have a problem. The APL boot card counts on there being time for at least one
|
||||
// more instruction to execute between the XIO read and the time the data starts loading
|
||||
// into core. So, we have to defer the actual read operation a bit. Might as well wait
|
||||
// until it's time to issue the operation complete interrupt. This means saving the
|
||||
// IO information, then performing the actual read in dsk_svc.
|
||||
/* ah. We have a problem. The APL boot card counts on there being time for at least one
|
||||
* more instruction to execute between the XIO read and the time the data starts loading
|
||||
* into core. So, we have to defer the actual read operation a bit. Might as well wait
|
||||
* until it's time to issue the operation complete interrupt. This means saving the
|
||||
* IO information, then performing the actual read in dsk_svc.
|
||||
*/
|
||||
|
||||
newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD;
|
||||
|
||||
@@ -248,12 +257,12 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
|
||||
case XIO_INITW:
|
||||
if (! IS_ONLINE(uptr)) { /* disk is offline */
|
||||
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error */
|
||||
diskfail(uptr, UNIT_HARDERR);
|
||||
if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error until disk is powered off/on */
|
||||
diskfail(uptr, DSK_DSW_DATA_ERROR, UNIT_HARDERR, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -312,7 +321,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
|
||||
case XIO_CONTROL: /* step fwd/rev */
|
||||
if (! IS_ONLINE(uptr)) {
|
||||
diskfail(uptr, UNIT_HARDERR);
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -364,19 +373,24 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
|
||||
/* diskfail - schedule an operation complete that sets the error bit */
|
||||
|
||||
static void diskfail (UNIT *uptr, int errflag)
|
||||
static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt)
|
||||
{
|
||||
int drv = uptr - dsk_unit;
|
||||
|
||||
sim_cancel(uptr); /* cancel any pending ops */
|
||||
SETBIT(uptr->flags, errflag); /* set the error flag */
|
||||
SETBIT(dsk_dsw[drv], dswflag); /* set any specified DSW bits */
|
||||
SETBIT(uptr->flags, unitflag); /* set any specified unit flag bits */
|
||||
uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */
|
||||
sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */
|
||||
|
||||
if (do_interrupt)
|
||||
sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */
|
||||
}
|
||||
|
||||
t_stat dsk_svc (UNIT *uptr)
|
||||
{
|
||||
int drv = uptr - dsk_unit, i, nwords, sec;
|
||||
int16 buf[DSK_NUMWD];
|
||||
uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development
|
||||
uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */
|
||||
int32 iocc_addr;
|
||||
|
||||
if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */
|
||||
@@ -415,16 +429,16 @@ t_stat dsk_svc (UNIT *uptr)
|
||||
dsk_lastio[drv] = IO_READ;
|
||||
uptr->pos = newpos;
|
||||
}
|
||||
fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read
|
||||
fxread(buf, 2, DSK_NUMWD, uptr->fileref); /* read whole sector so we're in position for next read */
|
||||
uptr->pos = newpos + 2*DSK_NUMWD;
|
||||
}
|
||||
|
||||
void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered
|
||||
void_backtrace(iocc_addr, iocc_addr + nwords - 1); /* mark prev instruction as altered */
|
||||
|
||||
trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask,
|
||||
(iocc_addr + nwords - 1) & mem_mask);
|
||||
|
||||
// // this will help debug the monitor by letting me watch phase loading
|
||||
/* this will help debug the monitor by letting me watch phase loading */
|
||||
if (raw_disk_debug)
|
||||
printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask,
|
||||
(iocc_addr + nwords - 1) & mem_mask);
|
||||
@@ -448,7 +462,7 @@ t_stat dsk_svc (UNIT *uptr)
|
||||
|
||||
}
|
||||
|
||||
uptr->FUNC = DSK_FUNC_IDLE; // we're done with this operation
|
||||
uptr->FUNC = DSK_FUNC_IDLE; /* we're done with this operation */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -459,8 +473,8 @@ t_stat dsk_reset (DEVICE *dptr)
|
||||
UNIT *uptr;
|
||||
|
||||
#ifdef TRACE_DMS_IO
|
||||
// add the WHERE command. It finds the phase that was loaded at given address and indicates
|
||||
// the offset in the phase
|
||||
/* add the WHERE command. It finds the phase that was loaded at given address and indicates */
|
||||
/* the offset in the phase */
|
||||
register_cmd("WHERE", &where_cmd, 0, "w{here} address find phase and offset of an address\n");
|
||||
register_cmd("PHDEBUG", &phdebug_cmd, 0, "ph{debug} off|phlo phhi break on phase load\n");
|
||||
register_cmd("FDUMP", &fdump_cmd, 0, NULL);
|
||||
@@ -487,14 +501,14 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr)
|
||||
int drv = uptr - dsk_unit;
|
||||
t_stat rval;
|
||||
|
||||
sim_cancel(uptr); // cancel current IO
|
||||
sim_cancel(uptr); /* cancel current IO */
|
||||
dsk_lastio[drv] = IO_NONE;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) // dismount current disk
|
||||
if (uptr->flags & UNIT_ATT) /* dismount current disk */
|
||||
if ((rval = dsk_detach(uptr)) != SCPE_OK)
|
||||
return rval;
|
||||
|
||||
uptr->CYL = 0; // reset the device
|
||||
uptr->CYL = 0; /* reset the device */
|
||||
uptr->FUNC = DSK_FUNC_IDLE;
|
||||
dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME;
|
||||
|
||||
@@ -502,18 +516,18 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr)
|
||||
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
|
||||
calc_ints();
|
||||
|
||||
if (sim_switches & SWMASK('M')) // if memory mode (e.g. for CGI), buffer the file
|
||||
SETBIT(uptr->flags, UNIT_BUFABLE);
|
||||
if (sim_switches & SWMASK('M')) /* if memory mode (e.g. for CGI), buffer the file */
|
||||
SETBIT(uptr->flags, UNIT_BUFABLE|UNIT_MUSTBUF);
|
||||
|
||||
if (sim_switches & SWMASK('R')) // read lock mode
|
||||
if (sim_switches & SWMASK('R')) /* read lock mode */
|
||||
SETBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_RONLY);
|
||||
|
||||
if (cgi && (sim_switches & SWMASK('M'))) { // if cgi and memory mode,
|
||||
sim_switches |= SWMASK('R'); // have attach_unit open file in readonly mode
|
||||
SETBIT(uptr->flags, UNIT_ROABLE|UNIT_MUSTBUF); // but don't set the UNIT_RONLY flag so DMS can write to the buffered image
|
||||
if (cgi && (sim_switches & SWMASK('M')) && ! cgiwritable) { /* if cgi and memory mode, but writable option not specified */
|
||||
sim_switches |= SWMASK('R'); /* have attach_unit open file in readonly mode */
|
||||
SETBIT(uptr->flags, UNIT_ROABLE); /* but don't set the UNIT_RONLY flag so DMS can write to the buffered image */
|
||||
}
|
||||
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { // mount new disk
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { /* mount new disk */
|
||||
SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY);
|
||||
return rval;
|
||||
}
|
||||
@@ -536,7 +550,7 @@ static t_stat dsk_detach (UNIT *uptr)
|
||||
|
||||
sim_cancel(uptr);
|
||||
|
||||
if ((rval = detach_unit (uptr)) != SCPE_OK)
|
||||
if ((rval = detach_unit(uptr)) != SCPE_OK)
|
||||
return rval;
|
||||
|
||||
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
|
||||
@@ -555,7 +569,7 @@ static t_stat dsk_detach (UNIT *uptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// boot routine - if they type BOOT DSK, load the standard boot card.
|
||||
/* boot routine - if they type BOOT DSK, load the standard boot card. */
|
||||
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr)
|
||||
{
|
||||
@@ -585,7 +599,7 @@ struct tag_slet {
|
||||
int16 nwords;
|
||||
int16 sector;
|
||||
} slet[MAXSLET] = {
|
||||
# include "dmsr2v12slet.h" // without RPG, use this info until overwritten by actual data from disk
|
||||
# include "dmsr2v12slet.h" /* without RPG, use this info until overwritten by actual data from disk */
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
@@ -599,7 +613,7 @@ int nseg = 0;
|
||||
|
||||
static void enable_dms_tracing (int newsetting)
|
||||
{
|
||||
nseg = 0; // clear the segment map
|
||||
nseg = 0; /* clear the segment map */
|
||||
|
||||
if ((newsetting && trace_dms) || ! (newsetting || trace_dms))
|
||||
return;
|
||||
@@ -678,7 +692,7 @@ static t_stat where_cmd (int flag, char *ptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// savesector - save info on a sector just read. THIS IS NOT YET TESTED
|
||||
/* savesector - save info on a sector just read. THIS IS NOT YET TESTED */
|
||||
|
||||
static void addseg (int i)
|
||||
{
|
||||
@@ -713,14 +727,14 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
||||
if (! trace_dms)
|
||||
return;
|
||||
|
||||
addr++; // first word is sector address, so account for that
|
||||
addr++; /* first word is sector address, so account for that */
|
||||
len--;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
if (addr >= (mseg[i].addr+mseg[i].len)) // entirely after this entry
|
||||
if (addr >= (mseg[i].addr+mseg[i].len)) /* entirely after this entry */
|
||||
continue;
|
||||
|
||||
if (mseg[i].addr < addr) { // old one starts before this. split it
|
||||
if (mseg[i].addr < addr) { /* old one starts before this. split it */
|
||||
addseg(i);
|
||||
mseg[i].len = addr-mseg[i].addr;
|
||||
i++;
|
||||
@@ -731,7 +745,7 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
||||
break;
|
||||
}
|
||||
|
||||
addseg(i); // add new segment. Old one ends up after this
|
||||
addseg(i); /* add new segment. Old one ends up after this */
|
||||
|
||||
if (i >= MAXMSEG)
|
||||
return;
|
||||
@@ -742,12 +756,12 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
||||
mseg[i].len = len;
|
||||
mseg[i].name = name;
|
||||
|
||||
i++; // delete any segments completely covered
|
||||
i++; /* delete any segments completely covered */
|
||||
|
||||
while (i < nseg && (mseg[i].addr+mseg[i].len) <= (addr+len))
|
||||
delseg(i);
|
||||
|
||||
if (i < nseg && mseg[i].addr < (addr+len)) { // old one extends past this. Retain the end
|
||||
if (i < nseg && mseg[i].addr < (addr+len)) { /* old one extends past this. Retain the end */
|
||||
mseg[i].len = (mseg[i].addr+mseg[i].len) - (addr+len);
|
||||
mseg[i].addr = addr+len;
|
||||
}
|
||||
@@ -755,19 +769,19 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
||||
|
||||
static void tracesector (int iswrite, int nwords, int addr, int sector)
|
||||
{
|
||||
int i, phid = 0, sletind = -1, offset = 0;
|
||||
int i, phid = 0, offset = 0;
|
||||
char *name = NULL;
|
||||
|
||||
if (nwords < 3 || ! trace_dms)
|
||||
return;
|
||||
|
||||
switch (sector) { // explicitly known sector name
|
||||
switch (sector) { /* explicitly known sector name */
|
||||
case 0: name = "ID/COLD START"; break;
|
||||
case 1: name = "DCOM"; break;
|
||||
case 2: name = "RESIDENT IMAGE"; break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: name = "SLET"; // save just-read or written SLET info
|
||||
case 5: name = "SLET"; /* save just-read or written SLET info */
|
||||
memmove(&slet[(320/4)*(sector-3)], &M[addr+1], nwords*2);
|
||||
break;
|
||||
case 6: name = "RELOAD TABLE"; break;
|
||||
@@ -777,9 +791,9 @@ static void tracesector (int iswrite, int nwords, int addr, int sector)
|
||||
printf("* %04x: %3d /%04x %c %3d.%d ",
|
||||
prev_IAR, nwords, addr, iswrite ? 'W' : 'R', sector/8, sector%8);
|
||||
|
||||
if (name == NULL) { // look up sector in SLET
|
||||
if (name == NULL) { /* look up sector in SLET */
|
||||
for (i = 0; i < MAXSLET; i++) {
|
||||
if (slet[i].phid == 0) // not found
|
||||
if (slet[i].phid == 0) /* not found */
|
||||
goto done;
|
||||
else if (slet[i].sector > sector) {
|
||||
if (--i >= 0) {
|
||||
@@ -792,17 +806,17 @@ static void tracesector (int iswrite, int nwords, int addr, int sector)
|
||||
goto done;
|
||||
}
|
||||
if (slet[i].sector == sector) {
|
||||
phid = slet[i].phid; // we found the starting sector
|
||||
phid = slet[i].phid; /* we found the starting sector */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= MAXSLET) // was not found
|
||||
if (i >= MAXSLET) /* was not found */
|
||||
goto done;
|
||||
|
||||
name = "?";
|
||||
for (i = sizeof(phase)/sizeof(phase[0]); --i >= 0; ) {
|
||||
if (phase[i].phid == phid) { // look up name
|
||||
if (phase[i].phid == phid) { /* look up name */
|
||||
name = phase[i].name;
|
||||
break;
|
||||
}
|
||||
@@ -816,7 +830,7 @@ done:
|
||||
putchar('\n');
|
||||
|
||||
if (phid >= phdebug_lo && phid <= phdebug_hi && offset == 0)
|
||||
break_simulation(STOP_PHASE_BREAK); // break on read of first sector of indicated phases
|
||||
break_simulation(STOP_PHASE_BREAK); /* break on read of first sector of indicated phases */
|
||||
|
||||
if (name != NULL && *name != '?' && ! iswrite)
|
||||
savesector(addr, offset, nwords, phid, name);
|
||||
@@ -824,12 +838,12 @@ done:
|
||||
|
||||
static t_stat fdump_cmd (int flags, char *cptr)
|
||||
{
|
||||
int addr = 0x7a24; // address of next statement;
|
||||
int addr = 0x7a24; /* address of next statement */
|
||||
int sofst = 0x7a26, symaddr;
|
||||
int cword, nwords, stype, has_stnum, strel = 1, laststno = 0;
|
||||
|
||||
addr = M[addr & mem_mask] & mem_mask; // get address of first statement
|
||||
sofst = M[sofst & mem_mask] & mem_mask; // get address of symbol table
|
||||
addr = M[addr & mem_mask] & mem_mask; /* get address of first statement */
|
||||
sofst = M[sofst & mem_mask] & mem_mask ; /* get address of symbol table */
|
||||
|
||||
for (;;) {
|
||||
cword = M[addr];
|
||||
@@ -851,7 +865,7 @@ static t_stat fdump_cmd (int flags, char *cptr)
|
||||
printf(" [%04x %04x %04x]", M[symaddr], M[symaddr+1], M[symaddr+2]);
|
||||
}
|
||||
|
||||
if (stype == 0x5000) { // error record
|
||||
if (stype == 0x5000) { /* error record */
|
||||
printf(" (err %d)", M[addr+1]);
|
||||
}
|
||||
|
||||
@@ -872,4 +886,4 @@ static t_stat fdump_cmd (int flags, char *cptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#endif // TRACE_DMS_IO
|
||||
#endif /* TRACE_DMS_IO */
|
||||
|
||||
@@ -1,60 +1,61 @@
|
||||
// ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source
|
||||
// Bob Flanders
|
||||
// -------------------------------------------------------------------------------------------
|
||||
//
|
||||
// These routines are used by ibm1130_cr.c when the user has indicated
|
||||
// that the input text is formatted with tabs. Input lines are edited
|
||||
// into the appropriate column format. Three edit modes are recognized:
|
||||
//
|
||||
// Assembler mode:
|
||||
// Input lines of the form
|
||||
//
|
||||
// [label]<whitespace>[opcode]<tab>[tag][L]<tab>[argument]
|
||||
//
|
||||
// are rearranged so that the input fields are placed in the appropriate columns
|
||||
//
|
||||
// The label must start on the first character of the line. If there is no label,
|
||||
// the first character(s) before the opcode must be whitespace. Following the opcode, there
|
||||
// MUST be a tab character, followed by the format and tag. Following the format and tag
|
||||
// may be exactly one whitespace character, and then starts the argument.
|
||||
//
|
||||
// Input lines with * in column 1 and blank lines are turned into Assembler comments,
|
||||
// with the * in the Opcode field.
|
||||
//
|
||||
// Assembler directive lines at the beginning of the deck must be preceded by
|
||||
// ! to indicate that they are not comments. For example,
|
||||
//
|
||||
// !*LIST
|
||||
// * This is a comment
|
||||
//
|
||||
// Fortran mode:
|
||||
// Input lines of the form
|
||||
//
|
||||
// [label]<tab>statement
|
||||
//
|
||||
// or
|
||||
//
|
||||
// [label]<tab>Xcontinuation
|
||||
//
|
||||
// where X is a non alphabetic contination character are rearranged in the
|
||||
// appropriate manner:
|
||||
//
|
||||
// 1 2
|
||||
// 12345678901234567890...
|
||||
// ------------------------
|
||||
// label statement
|
||||
// labelXcontinuation
|
||||
//
|
||||
// However, you must take care that you don't end up with statement text after column 72.
|
||||
//
|
||||
// Input lines with * or C in column 1 are left alone (comments and directives)
|
||||
//
|
||||
// (The ! escape is not used before Fortran directives as before Assembler directives)
|
||||
//
|
||||
// Tab mode:
|
||||
// Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide,
|
||||
// as is standard for vi, notepad, etc.
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/*********************************************************************************************
|
||||
* ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source
|
||||
* Bob Flanders
|
||||
* -------------------------------------------------------------------------------------------
|
||||
*
|
||||
* These routines are used by ibm1130_cr.c when the user has indicated
|
||||
* that the input text is formatted with tabs. Input lines are edited
|
||||
* into the appropriate column format. Three edit modes are recognized:
|
||||
*
|
||||
* Assembler mode:
|
||||
* Input lines of the form
|
||||
*
|
||||
* [label]<whitespace>[opcode]<tab>[tag][L]<tab>[argument]
|
||||
*
|
||||
* are rearranged so that the input fields are placed in the appropriate columns
|
||||
*
|
||||
* The label must start on the first character of the line. If there is no label,
|
||||
* the first character(s) before the opcode must be whitespace. Following the opcode, there
|
||||
* MUST be a tab character, followed by the format and tag. Following the format and tag
|
||||
* may be exactly one whitespace character, and then starts the argument.
|
||||
*
|
||||
* Input lines with * in column 1 and blank lines are turned into Assembler comments,
|
||||
* with the * in the Opcode field.
|
||||
*
|
||||
* Assembler directive lines at the beginning of the deck must be preceded by
|
||||
* ! to indicate that they are not comments. For example,
|
||||
*
|
||||
* !*LIST
|
||||
* * This is a comment
|
||||
*
|
||||
* Fortran mode:
|
||||
* Input lines of the form
|
||||
*
|
||||
* [label]<tab>statement
|
||||
*
|
||||
* or
|
||||
*
|
||||
* [label]<tab>Xcontinuation
|
||||
*
|
||||
* where X is a non alphabetic contination character are rearranged in the
|
||||
* appropriate manner:
|
||||
*
|
||||
* 1 2
|
||||
* 12345678901234567890...
|
||||
* ------------------------
|
||||
* label statement
|
||||
* labelXcontinuation
|
||||
*
|
||||
* However, you must take care that you don't end up with statement text after column 72.
|
||||
*
|
||||
* Input lines with * or C in column 1 are left alone (comments and directives)
|
||||
*
|
||||
* (The ! escape is not used before Fortran directives as before Assembler directives)
|
||||
*
|
||||
* Tab mode:
|
||||
* Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide,
|
||||
* as is standard for vi, notepad, etc.
|
||||
*********************************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -63,10 +64,10 @@
|
||||
#include <string.h>
|
||||
#include "ibm1130_fmt.h"
|
||||
|
||||
#define MAXLINE 81 // maximum output line size
|
||||
#define WORKSZ 256 // size for tab work area
|
||||
#define TAGOFFSET 12 // offset for tag field
|
||||
#define FMTOFFSET 11 // offset for format field
|
||||
#define MAXLINE 81 /* maximum output line size */
|
||||
#define WORKSZ 256 /* size for tab work area */
|
||||
#define TAGOFFSET 12 /* offset for tag field */
|
||||
#define FMTOFFSET 11 /* offset for format field */
|
||||
|
||||
#define MIN(a,b) ((a < b) ? a : b)
|
||||
#define AMSG " with Assembler Reformat"
|
||||
@@ -77,227 +78,236 @@
|
||||
#define FFORMAT "%-5.5s %-74.74s"
|
||||
#define FCONTFMT "%-5.5s%-75.75s"
|
||||
|
||||
char gszLabel[6]; // work area for label
|
||||
char gszArg[MAXLINE]; // .. argument
|
||||
char gszOutput[MAXLINE]; // .. output
|
||||
short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};// tab stops for assembler
|
||||
char gszLabel[6]; /* work area for label */
|
||||
char gszArg[MAXLINE]; /* .. argument */
|
||||
char gszOutput[MAXLINE]; /* .. output */
|
||||
short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};/* tab stops for assembler */
|
||||
|
||||
short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};// tab stops for just plain tabs
|
||||
short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};/* tab stops for just plain tabs */
|
||||
|
||||
// ///////////////
|
||||
// helper routines
|
||||
/*
|
||||
* helper routines
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// ExpandTabs: Expand tabs to spaces
|
||||
/*************************************************
|
||||
* ExpandTabs: Expand tabs to spaces
|
||||
*/
|
||||
|
||||
char* ExpandTabs(char* p_szInbuf, // expand tabs .. input buffer
|
||||
char* p_szOutbuf, // .. output buffer
|
||||
short* p_aiTabs) // .. array of tab stops (1 based) -- 0 end of array
|
||||
char* ExpandTabs(char* p_szInbuf, /* expand tabs .. input buffer */
|
||||
char* p_szOutbuf, /* .. output buffer */
|
||||
short* p_aiTabs) /* .. array of tab stops (1 based) -- 0 end of array */
|
||||
{
|
||||
short iI, // input position
|
||||
iO, // output position
|
||||
iT; // next tab stop
|
||||
short iI, /* input position */
|
||||
iO, /* output position */
|
||||
iT; /* next tab stop */
|
||||
|
||||
char cX; // character to test
|
||||
char cX; /* character to test */
|
||||
|
||||
iI = 0; // init input position
|
||||
iO = 0; // init output position
|
||||
iT = 0; // init tab stop
|
||||
iI = 0; /* init input position */
|
||||
iO = 0; /* init output position */
|
||||
iT = 0; /* init tab stop */
|
||||
|
||||
while ((cX = *(p_szInbuf + iI)) != 0) // while there are characters
|
||||
while ((cX = *(p_szInbuf + iI)) != 0) /* while there are characters */
|
||||
{
|
||||
if (cX == '\t') // q. tab character?
|
||||
{ // a. yes ..
|
||||
while ((p_aiTabs[iT] <= iO + 1) // search for next valid stop ..
|
||||
&& (p_aiTabs[iT] != 0)) // .. or end of table
|
||||
iT++; // .. go to next tab
|
||||
if (cX == '\t') /* q. tab character? */
|
||||
{ /* a. yes .. */
|
||||
while ((p_aiTabs[iT] <= iO + 1) /* search for next valid stop .. */
|
||||
&& (p_aiTabs[iT] != 0)) /* .. or end of table */
|
||||
iT++; /* .. go to next tab */
|
||||
|
||||
if (p_aiTabs[iT] != 0) // q. end of tab array?
|
||||
{ // a. no ..
|
||||
while (iO < (p_aiTabs[iT] - 1)) // fill to tab with blanks
|
||||
*(p_szOutbuf + iO++) = ' '; // .. put in a blank
|
||||
if (p_aiTabs[iT] != 0) /* q. end of tab array? */
|
||||
{ /* a. no .. */
|
||||
while (iO < (p_aiTabs[iT] - 1)) /* fill to tab with blanks */
|
||||
*(p_szOutbuf + iO++) = ' '; /* .. put in a blank */
|
||||
|
||||
}
|
||||
else // Otherwise ...
|
||||
*(p_szOutbuf + iO++) = ' '; // .. Translate to blank
|
||||
else /* Otherwise ... */
|
||||
*(p_szOutbuf + iO++) = ' '; /* .. Translate to blank */
|
||||
}
|
||||
else // Otherwise .. not tab
|
||||
*(p_szOutbuf + iO++) = cX; // .. save the input char
|
||||
else /* Otherwise .. not tab */
|
||||
*(p_szOutbuf + iO++) = cX; /* .. save the input char */
|
||||
|
||||
iI++; // next input character
|
||||
iI++; /* next input character */
|
||||
}
|
||||
|
||||
*(p_szOutbuf + iO) = 0; // end the string..
|
||||
return p_szOutbuf; // .. return output area addr
|
||||
*(p_szOutbuf + iO) = 0; /* end the string.. */
|
||||
return p_szOutbuf; /* .. return output area addr */
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// extract next token, modify pointer
|
||||
/*************************************************
|
||||
* extract next token, modify pointer
|
||||
*/
|
||||
|
||||
char* GetToken(char* p_szOut, // output location
|
||||
int p_iLen, // max output length
|
||||
char**p_pszToken) // pointer to input token
|
||||
char* GetToken(char* p_szOut, /* output location */
|
||||
int p_iLen, /* max output length */
|
||||
char**p_pszToken) /* pointer to input token */
|
||||
{
|
||||
int iI; // work integer
|
||||
char* pszX; // work pointer
|
||||
int iI; /* work integer */
|
||||
char* pszX; /* work pointer */
|
||||
|
||||
pszX = *p_pszToken; // get pointer to token
|
||||
pszX = *p_pszToken; /* get pointer to token */
|
||||
|
||||
for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) // while not whitespace & not end
|
||||
iI++; // .. count token length
|
||||
for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) /* while not whitespace & not end */
|
||||
iI++; /* .. count token length */
|
||||
|
||||
memset(p_szOut, 0, p_iLen); // zero out output area
|
||||
memset(p_szOut, 0, p_iLen); /* zero out output area */
|
||||
|
||||
if (iI > 0) // q. any chars?
|
||||
strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); // a. yes.. copy max of p_iLen-1
|
||||
if (iI > 0) /* q. any chars? */
|
||||
strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); /* a. yes.. copy max of p_iLen-1 */
|
||||
|
||||
*p_pszToken += iI; // point beyond token
|
||||
return p_szOut; // .. return token pointer
|
||||
*p_pszToken += iI; /* point beyond token */
|
||||
return p_szOut; /* .. return token pointer */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToAsm - convert tab-formatted text line to 1130 Assembler format
|
||||
/*************************************************
|
||||
* EditToAsm - convert tab-formatted text line to 1130 Assembler format
|
||||
*/
|
||||
|
||||
char *EditToAsm (char* p_pszEdit) // convert line to 1130 assembler
|
||||
char *EditToAsm (char* p_pszEdit) /* convert line to 1130 assembler */
|
||||
{
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char pszWork[WORKSZ]; // work buffer
|
||||
char acTFWrk[2]; // tag/format work area
|
||||
size_t iI; // work integer
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char pszWork[WORKSZ]; /* work buffer */
|
||||
char acTFWrk[2]; /* tag/format work area */
|
||||
size_t iI; /* work integer */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return AMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return AMSG; /* a. yes .. return display message */
|
||||
|
||||
if (*p_pszEdit == '!') // leave lines starting with ! alone
|
||||
if (*p_pszEdit == '!') /* leave lines starting with ! alone */
|
||||
return EditToWhitespace(p_pszEdit+1);
|
||||
|
||||
if (*p_pszEdit == '*') // q. comment line?
|
||||
{ // a. yes..
|
||||
strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); // .. convert any tabs
|
||||
sprintf(gszOutput, ACOMMENTFMT, pszWork); // .. put the comment out there in the opcode column
|
||||
return gszOutput; // .. and return it
|
||||
if (*p_pszEdit == '*') /* q. comment line? */
|
||||
{ /* a. yes.. */
|
||||
strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); /* .. convert any tabs */
|
||||
sprintf(gszOutput, ACOMMENTFMT, pszWork); /* .. put the comment out there in the opcode column */
|
||||
return gszOutput; /* .. and return it */
|
||||
}
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
ExpandTabs(pszLine, pszWork, gaiAsmTabs); // expand the tabs
|
||||
strncpy(pszLine, pszWork, MAXLINE-1); // copy the line back
|
||||
ExpandTabs(pszLine, pszWork, gaiAsmTabs); /* expand the tabs */
|
||||
strncpy(pszLine, pszWork, MAXLINE-1); /* copy the line back */
|
||||
|
||||
for (iI = strlen(pszLine); iI--;) // trim trailing whitespace
|
||||
for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */
|
||||
{
|
||||
if (*(pszLine + iI) <= ' ') // q. space or less?
|
||||
*(pszLine + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(pszLine + iI) <= ' ') /* q. space or less? */
|
||||
*(pszLine + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
if (strlen(pszLine) == 0) // q. blank line?
|
||||
{ // a. yes .. Assembler abhors these so
|
||||
sprintf(gszOutput, ABLANKLINE); // format as comment statement
|
||||
return gszOutput; // .. and return it
|
||||
if (strlen(pszLine) == 0) /* q. blank line? */
|
||||
{ /* a. yes .. Assembler abhors these so */
|
||||
sprintf(gszOutput, ABLANKLINE); /* format as comment statement */
|
||||
return gszOutput; /* .. and return it */
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add code to process a strip switch
|
||||
// comment?
|
||||
/* TODO: Add code to process a strip switch
|
||||
* comment?
|
||||
*/
|
||||
|
||||
if (strlen(pszLine) > (TAGOFFSET + 1)) // q. line long enough?
|
||||
{ // a. yes.. reorder tag/format
|
||||
memcpy(acTFWrk, pszLine + FMTOFFSET, 2); // get tag/format
|
||||
memset((pszLine + FMTOFFSET), ' ', 2); // .. blank 'em out
|
||||
if (strlen(pszLine) > (TAGOFFSET + 1)) /* q. line long enough? */
|
||||
{ /* a. yes.. reorder tag/format */
|
||||
memcpy(acTFWrk, pszLine + FMTOFFSET, 2); /* get tag/format */
|
||||
memset((pszLine + FMTOFFSET), ' ', 2); /* .. blank 'em out */
|
||||
|
||||
for (iI = 0; iI < 2; iI ++)
|
||||
if (isalpha(acTFWrk[iI])) // q. alpha char?
|
||||
*(pszLine + FMTOFFSET) = acTFWrk[iI]; // a. yes .. make it format
|
||||
else if (isdigit(acTFWrk[iI])) // q. digit?
|
||||
*(pszLine + TAGOFFSET) = acTFWrk[iI]; // a. yes .. make it the tag
|
||||
if (isalpha(acTFWrk[iI])) /* q. alpha char? */
|
||||
*(pszLine + FMTOFFSET) = acTFWrk[iI]; /* a. yes .. make it format */
|
||||
else if (isdigit(acTFWrk[iI])) /* q. digit? */
|
||||
*(pszLine + TAGOFFSET) = acTFWrk[iI]; /* a. yes .. make it the tag */
|
||||
}
|
||||
|
||||
sprintf(gszOutput, AFORMAT, pszLine); // format the line
|
||||
sprintf(gszOutput, AFORMAT, pszLine); /* format the line */
|
||||
|
||||
return gszOutput; // return formatted line
|
||||
return gszOutput; /* return formatted line */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToFortran - convert tab-formatted input text line to FORTRAN format
|
||||
// (a la DEC Fortran)
|
||||
/*************************************************
|
||||
* EditToFortran - convert tab-formatted input text line to FORTRAN format
|
||||
* (a la DEC Fortran)
|
||||
*/
|
||||
|
||||
char *EditToFortran(char* p_pszEdit) // convert line to 1130 assembler
|
||||
char *EditToFortran(char* p_pszEdit) /* convert line to 1130 assembler */
|
||||
{
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char* pszWork; // work pointer
|
||||
size_t iI; // work integer
|
||||
int bContinue; // true if continue
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char* pszWork; /* work pointer */
|
||||
size_t iI; /* work integer */
|
||||
int bContinue; /* true if continue */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return FMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return FMSG; /* a. yes .. return display message */
|
||||
|
||||
if (strchr(p_pszEdit, '\t') == NULL) // q. no tab in the line?
|
||||
return p_pszEdit; // a. nope, return line as is, assume it's formatted correctly
|
||||
if (strchr(p_pszEdit, '\t') == NULL) /* q. no tab in the line? */
|
||||
return p_pszEdit; /* a. nope, return line as is, assume it's formatted correctly */
|
||||
|
||||
if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') // q. comment or directive or blank line?
|
||||
{ // a. yes.. don't restructure
|
||||
if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') /* q. comment or directive or blank line? */
|
||||
{ /* a. yes.. don't restructure */
|
||||
return EditToWhitespace(p_pszEdit);
|
||||
}
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
for (iI = strlen(pszLine); iI--;) // trim trailing whitespace
|
||||
for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */
|
||||
{
|
||||
if (*(pszLine + iI) <= ' ') // q. space or less?
|
||||
*(pszLine + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(pszLine + iI) <= ' ') /* q. space or less? */
|
||||
*(pszLine + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
// TODO: Add code to process a strip switch
|
||||
// comment?
|
||||
/*
|
||||
* TODO: Add code to process a strip switch
|
||||
* comment?
|
||||
*/
|
||||
|
||||
pszWork = (char*) pszLine; // set pointer to line
|
||||
GetToken(gszLabel, 6, &pszWork); // get the line, if any.
|
||||
pszWork = (char*) pszLine; /* set pointer to line */
|
||||
GetToken(gszLabel, 6, &pszWork); /* get the line, if any. */
|
||||
|
||||
pszWork++; // skip tab/whitespace
|
||||
pszWork++; /* skip tab/whitespace */
|
||||
|
||||
// continuation...
|
||||
bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) // if first char non-zero digit
|
||||
|| (!isspace(*pszWork) && !isalpha(*pszWork))); // .. or non-alpha non-blank
|
||||
/* continuation... */
|
||||
bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) /* if first char non-zero digit */
|
||||
|| (!isspace(*pszWork) && !isalpha(*pszWork))); /* .. or non-alpha non-blank */
|
||||
|
||||
memset(gszArg, 0, MAXLINE); // .. and arguments
|
||||
memset(gszArg, 0, MAXLINE); /* .. and arguments */
|
||||
|
||||
strncpy(gszArg, pszWork, 75); // copy rest to argument
|
||||
strncpy(gszArg, pszWork, 75); /* copy rest to argument */
|
||||
|
||||
sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, // format the line
|
||||
gszLabel, // .. statement #
|
||||
gszArg); // .. code
|
||||
sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, /* format the line */
|
||||
gszLabel, /* .. statement # */
|
||||
gszArg); /* .. code */
|
||||
|
||||
return gszOutput; // return formatted line
|
||||
return gszOutput; /* return formatted line */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToWhitespace - expand tabs at 8 space intervals.
|
||||
/*************************************************
|
||||
* EditToWhitespace - expand tabs at 8 space intervals.
|
||||
*/
|
||||
|
||||
char* EditToWhitespace(char *p_pszEdit)
|
||||
{
|
||||
int iI; /* work integer */
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char pszWork[WORKSZ]; // work buffer
|
||||
int iI; /* work integer */
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char pszWork[WORKSZ]; /* work buffer */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return AMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return AMSG; /* a. yes .. return display message */
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
ExpandTabs(pszLine, pszWork, gaiPlainTabs); // expand the tabs
|
||||
strncpy(gszOutput, pszWork, MAXLINE-1); // copy the line back
|
||||
ExpandTabs(pszLine, pszWork, gaiPlainTabs); /* expand the tabs */
|
||||
strncpy(gszOutput, pszWork, MAXLINE-1); /* copy the line back */
|
||||
|
||||
for (iI = strlen(gszOutput); iI--;) // look at each character
|
||||
for (iI = strlen(gszOutput); iI--;) /* look at each character */
|
||||
{
|
||||
if (*(gszOutput + iI) <= ' ') // q. space or less?
|
||||
*(gszOutput + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(gszOutput + iI) <= ' ') /* q. space or less? */
|
||||
*(gszOutput + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
|
||||
return gszOutput; /* ... return buffer */
|
||||
return gszOutput; /* ... return buffer */
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
/* ibm1130_asm.h: definition of routines in ibm1130_asm.c
|
||||
*/
|
||||
|
||||
char* EditToAsm(char*); // convert edit format to 1130 assembler format
|
||||
char* EditToFortran(char*); // convert edit format to Fortran format
|
||||
char* EditToWhitespace(char*); // clean white space, tabstops every 8 positions
|
||||
char* EditToAsm(char*); /* convert edit format to 1130 assembler format */
|
||||
char* EditToFortran(char*); /* convert edit format to Fortran format */
|
||||
char* EditToWhitespace(char*); /* clean white space, tabstops every 8 positions */
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
/* ibm1130_gdu.c: IBM 1130 2250 Graphical Display Unit
|
||||
|
||||
(Under construction)
|
||||
// stuff to fix:
|
||||
// "store revert" might be backwards?
|
||||
// alpha keyboard is not implemented
|
||||
// pushbuttons are not implemented
|
||||
// there is something about interrupts being deferred during a subroutine transition?
|
||||
stuff to fix:
|
||||
"store revert" might be backwards?
|
||||
alpha keyboard is not implemented
|
||||
pushbuttons are not implemented
|
||||
there is something about interrupts being deferred during a subroutine transition?
|
||||
|
||||
Based on the SIMH package written by Robert M Supnik
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
* Mail to simh@ibm1130.org
|
||||
*/
|
||||
|
||||
#define BLIT_MODE // normally defined, undefine when debugging generate_image()
|
||||
//#define DEBUG_LIGHTPEN // normally undefined, define to visualize light-pen sensing
|
||||
#define BLIT_MODE /* define for better performance, undefine when debugging generate_image() */
|
||||
/* #define DEBUG_LIGHTPEN */ /* define to debug light-pen sensing */
|
||||
|
||||
#define DEFAULT_GDU_RATE 20 // default frame rate
|
||||
#define DEFAULT_PEN_THRESHOLD 3 // default looseness of light-pen hit
|
||||
#define INDWIDTH 32 // width of an indicator (there are two columns of these)
|
||||
#define INITSIZE 512 // initial window size
|
||||
#define DEFAULT_GDU_RATE 20 /* default frame rate */
|
||||
#define DEFAULT_PEN_THRESHOLD 3 /* default looseness of light-pen hit */
|
||||
#define INDWIDTH 32 /* width of an indicator (there are two columns of these) */
|
||||
#define INITSIZE 512 /* initial window size */
|
||||
|
||||
#define GDU_DSW_ORDER_CONTROLLED_INTERRUPT 0x8000
|
||||
#define GDU_DSW_KEYBOARD_INTERUPT 0x4000
|
||||
@@ -109,7 +109,7 @@ static t_stat gdu_reset (DEVICE *dptr)
|
||||
|
||||
void xio_2250_display (int32 addr, int32 func, int32 modify)
|
||||
{
|
||||
// ignore commands to nonexistent device
|
||||
/* ignore commands if device is nonexistent */
|
||||
}
|
||||
|
||||
t_bool gdu_active (void)
|
||||
@@ -118,7 +118,7 @@ t_bool gdu_active (void)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
#else // GUI_SUPPORT defined
|
||||
#else /* GUI_SUPPORT defined */
|
||||
|
||||
/******* PLATFORM INDEPENDENT CODE ********************************************************/
|
||||
|
||||
@@ -127,7 +127,6 @@ static int xmouse, ymouse, lpen_dist, lpen_dist2; // current mouse pointer, scal
|
||||
static double sfactor; // current scaling factor
|
||||
static t_bool last_abs = TRUE; // last positioning instruction was absolute
|
||||
static t_bool mouse_present = FALSE; // mouse is/is not in the window
|
||||
|
||||
static void clear_interrupts (void);
|
||||
static void set_indicators (int32 new_inds);
|
||||
static void start_regeneration (void);
|
||||
@@ -239,23 +238,27 @@ static void start_regeneration (void)
|
||||
{
|
||||
SETBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
|
||||
if (gdu_unit.flags & UNIT_DISPLAYED) {
|
||||
StartGDUUpdates();
|
||||
}
|
||||
else {
|
||||
if ((gdu_unit.flags & UNIT_DISPLAYED) == 0) {
|
||||
if (! CreateGDUWindow())
|
||||
return;
|
||||
|
||||
SETBIT(gdu_unit.flags, UNIT_DISPLAYED);
|
||||
}
|
||||
|
||||
StartGDUUpdates();
|
||||
}
|
||||
|
||||
static void halt_regeneration (void)
|
||||
{
|
||||
// halt_regeneration gets called at end of every refresh interation, so it should NOT black out the
|
||||
// screen -- this is why it was flickering so badly. The lower level code (called on a timer)
|
||||
// should check to see if GDU_DSW_BUSY is clear, and if it it still zero after several msec,
|
||||
// only then should it black out the screen and call StopGDUUpdates.
|
||||
if (gdu_dsw & GDU_DSW_BUSY) {
|
||||
StopGDUUpdates();
|
||||
// StopGDUUpdates(); // let lower level code discover this during next refresh
|
||||
CLRBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
}
|
||||
EraseGDUScreen();
|
||||
// EraseGDUScreen(); // let cessation of regeneration erase it (eventually)
|
||||
}
|
||||
|
||||
static void notify_window_closed (void)
|
||||
@@ -264,7 +267,9 @@ static void notify_window_closed (void)
|
||||
StopGDUUpdates();
|
||||
CLRBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
}
|
||||
|
||||
CLRBIT(gdu_unit.flags, UNIT_DISPLAYED);
|
||||
|
||||
gdu_reset(&gdu_dev);
|
||||
}
|
||||
|
||||
@@ -671,7 +676,7 @@ static HPEN hRedPen = NULL;
|
||||
#endif
|
||||
static HBRUSH hGrayBrush, hDarkBrush;
|
||||
static HPEN hBlackPen;
|
||||
|
||||
static int halted = 0; // number of time intervals that GDU has been halted w/o a regeneration
|
||||
static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
|
||||
static DWORD WINAPI GDUPump (LPVOID arg);
|
||||
|
||||
@@ -719,11 +724,6 @@ static t_bool CreateGDUWindow (void)
|
||||
{
|
||||
static BOOL did_atexit = FALSE;
|
||||
|
||||
if (hwGDU != NULL) { // window already exists
|
||||
StartGDUUpdates();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
hInstance = GetModuleHandle(NULL);
|
||||
|
||||
if (hGDUPump == INVALID_HANDLE_VALUE)
|
||||
@@ -878,7 +878,7 @@ static void gdu_WM_PAINT (HWND hWnd)
|
||||
|
||||
static void gdu_WM_SIZE (HWND hWnd, UINT state, int cx, int cy)
|
||||
{
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
InvalidateRect(hWnd, NULL, TRUE);
|
||||
}
|
||||
|
||||
// tweak the sizing rectangle during a resize to guarantee a square window
|
||||
@@ -912,6 +912,16 @@ static void gdu_WM_TIMER (HWND hWnd, UINT id)
|
||||
HDC hDC;
|
||||
|
||||
if (running) { // if CPU is running, update picture
|
||||
if ((gdu_dsw & GDU_DSW_BUSY) == 0) { // regeneration is not to occur
|
||||
if (++halted >= 4) { // stop the timer if four timer intervals go by with the display halted
|
||||
EraseGDUScreen(); // screen goes black due to cessation of refreshing
|
||||
StopGDUUpdates(); // might as well kill the timer
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
halted = 0;
|
||||
|
||||
#ifdef BLIT_MODE
|
||||
hDC = GetDC(hWnd); // blit the new image right over the old
|
||||
PaintImage(hDC, FALSE);
|
||||
@@ -964,7 +974,7 @@ static void DrawPoint (int x, int y)
|
||||
static void UpdateGDUIndicators(void)
|
||||
{
|
||||
if (hwGDU != NULL)
|
||||
InvalidateRect(hwGDU, NULL, TRUE);
|
||||
InvalidateRect(hwGDU, NULL, FALSE); // no need to erase the background -- the draw routine fully paints the indicator
|
||||
}
|
||||
|
||||
static void CheckGDUKeyboard (void)
|
||||
@@ -981,6 +991,7 @@ static void StartGDUUpdates (void)
|
||||
msec = (gdu_rate == 0) ? (1000 / DEFAULT_GDU_RATE) : 1000/gdu_rate;
|
||||
idTimer = SetTimer(hwGDU, 1, msec, NULL);
|
||||
}
|
||||
halted = 0;
|
||||
}
|
||||
|
||||
static void StopGDUUpdates (void)
|
||||
@@ -988,6 +999,7 @@ static void StopGDUUpdates (void)
|
||||
if (idTimer != 0) {
|
||||
KillTimer(hwGDU, 1);
|
||||
idTimer = 0;
|
||||
halted = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,8 +1098,6 @@ static DWORD WINAPI GDUPump (LPVOID arg)
|
||||
ShowWindow(hwGDU, SW_SHOWNOACTIVATE); /* display it */
|
||||
UpdateWindow(hwGDU);
|
||||
|
||||
StartGDUUpdates();
|
||||
|
||||
while (GetMessage(&msg, hwGDU, 0, 0)) { /* message pump - this basically loops forevermore */
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to simh@ibm1130.org
|
||||
*
|
||||
* 30-Dec-05 BLK Fixed mask for IAR and SAR register display and added display
|
||||
* of Arithmetic Factor, per Carl Claunch.
|
||||
*
|
||||
* 09-Apr-04 BLK Changed code to use stock windows cursor IDC_HAND if available
|
||||
*
|
||||
* 02-Dec-02 BLK Changed display, added printer and card reader icons
|
||||
@@ -33,9 +36,9 @@
|
||||
#define UPDATE_BY_TIMER
|
||||
|
||||
#ifdef UPDATE_BY_TIMER
|
||||
# define UPDATE_INTERVAL 20 // set to desired number of updates/second
|
||||
# define UPDATE_INTERVAL 20 /* set to desired number of updates/second */
|
||||
#else
|
||||
# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time
|
||||
# define UPDATE_INTERVAL 5000 /* GUI: set to 100000/f where f = desired updates/second of 1130 time */
|
||||
#endif
|
||||
|
||||
#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_cr.c */
|
||||
@@ -46,8 +49,9 @@
|
||||
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */
|
||||
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||
|
||||
// I think I had it wrong; Program Load actually does start the processor after
|
||||
// reading in the card?
|
||||
/* I think I had it wrong; Program Load actually does start the processor after
|
||||
* reading in the card?
|
||||
*/
|
||||
|
||||
#define PROGRAM_LOAD_STARTS_CPU
|
||||
|
||||
@@ -86,7 +90,7 @@ DEVICE console_dev = {
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
// reset for the "console" display device
|
||||
/* reset for the "console" display device */
|
||||
|
||||
extern char *read_line (char *cptr, int size, FILE *stream);
|
||||
extern FILE *sim_log;
|
||||
@@ -117,8 +121,8 @@ extern UNIT prt_unit;
|
||||
t_stat console_reset (DEVICE *dptr)
|
||||
{
|
||||
if (! sim_gui) {
|
||||
SETBIT(console_unit.flags, UNIT_DIS); // disable the GUI
|
||||
CLRBIT(console_unit.flags, UNIT_DISPLAY); // turn the GUI off
|
||||
SETBIT(console_unit.flags, UNIT_DIS); /* disable the GUI */
|
||||
CLRBIT(console_unit.flags, UNIT_DISPLAY); /* turn the GUI off */
|
||||
}
|
||||
|
||||
update_gui(FALSE);
|
||||
@@ -158,19 +162,19 @@ void scp_panic (char *msg)
|
||||
#define IDC_RESET 14
|
||||
#define IDC_PROGRAM_LOAD 15
|
||||
|
||||
#define IDC_TEAR 16 // standard button
|
||||
#define IDC_1442 17 // device images
|
||||
#define IDC_TEAR 16 /* standard button */
|
||||
#define IDC_1442 17 /* device images */
|
||||
#define IDC_1132 18
|
||||
|
||||
#define LAMPTIME 500 // 500 msec delay on updating
|
||||
#define LAMPTIME 500 /* 500 msec delay on updating */
|
||||
#define FLASH_TIMER_ID 1
|
||||
#define UPDATE_TIMER_ID 2
|
||||
|
||||
#define RUNSWITCH_X 689 // center of the run mode switch dial
|
||||
#define RUNSWITCH_X 689 /* center of the run mode switch dial */
|
||||
#define RUNSWITCH_Y 107
|
||||
#define TOGGLES_X 122 // left edge of series of toggle switches
|
||||
#define TOGGLES_X 122 /* left edge of series of toggle switches */
|
||||
|
||||
#define TXTBOX_X 200 // text labels showing attached devices
|
||||
#define TXTBOX_X 200 /* text labels showing attached devices */
|
||||
#define TXTBOX_Y 300
|
||||
#define TXTBOX_WIDTH 195
|
||||
#define TXTBOX_HEIGHT 12
|
||||
@@ -238,19 +242,18 @@ static struct tag_btn {
|
||||
TXTBOX_X+40, TXTBOX_Y+25, 35, 12, "Tear", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 238, 110, 110, "EMPTY_1442", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
// 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
};
|
||||
#define NBUTTONS (sizeof(btn) / sizeof(btn[0]))
|
||||
|
||||
#define STATE_1442_EMPTY 0 // no cards (no file attached)
|
||||
#define STATE_1442_FULL 1 // cards in hopper (file attached at BOF)
|
||||
#define STATE_1442_MIDDLE 2 // cards in hopper and stacker (file attached, neither EOF nor BOF)
|
||||
#define STATE_1442_EOF 3 // cards in stacker (file attached, at EOF)
|
||||
#define STATE_1442_HIDDEN 4 // simulator is attached to physical card reader
|
||||
#define STATE_1442_EMPTY 0 /* no cards (no file attached) */
|
||||
#define STATE_1442_FULL 1 /* cards in hopper (file attached at BOF) */
|
||||
#define STATE_1442_MIDDLE 2 /* cards in hopper and stacker (file attached, neither EOF nor BOF) */
|
||||
#define STATE_1442_EOF 3 /* cards in stacker (file attached, at EOF) */
|
||||
#define STATE_1442_HIDDEN 4 /* simulator is attached to physical card reader */
|
||||
|
||||
#define STATE_1132_EMPTY 0 // no paper hanging out of printer
|
||||
#define STATE_1132_FULL 1 // paper hanging out of printer
|
||||
#define STATE_1132_HIDDEN 2 // printer is attached to physical printer
|
||||
#define STATE_1132_EMPTY 0 /* no paper hanging out of printer */
|
||||
#define STATE_1132_FULL 1 /* paper hanging out of printer */
|
||||
#define STATE_1132_HIDDEN 2 /* printer is attached to physical printer */
|
||||
|
||||
static struct tag_txtbox {
|
||||
int x, y;
|
||||
@@ -309,9 +312,9 @@ static void destroy_console_window (void)
|
||||
int i;
|
||||
|
||||
if (hConsoleWnd != NULL)
|
||||
SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); // cross thread call is OK
|
||||
SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); /* cross thread call is OK */
|
||||
|
||||
if (hPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it
|
||||
if (hPump != INVALID_HANDLE_VALUE) { /* this is not the most graceful way to do it */
|
||||
TerminateThread(hPump, 0);
|
||||
hPump = INVALID_HANDLE_VALUE;
|
||||
PumpID = 0;
|
||||
@@ -338,10 +341,11 @@ static void destroy_console_window (void)
|
||||
NIXOBJECT(btn[i].hbrDark);
|
||||
}
|
||||
|
||||
// if (class_defined) {
|
||||
// UnregisterClass(hInstance, szConsoleClassName);
|
||||
// class_defined = FALSE;
|
||||
// }
|
||||
/* if (class_defined) {
|
||||
UnregisterClass(hInstance, szConsoleClassName);
|
||||
class_defined = FALSE;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
@@ -350,7 +354,7 @@ static void destroy_console_window (void)
|
||||
|
||||
static int shown_iar = 0, shown_sar = 0, shown_sbr = 0, shown_afr = 0, shown_acc = 0, shown_ext = 0;
|
||||
static int shown_op = 0, shown_tag = 0, shown_irq = 0, shown_ccc = 0, shown_cnd = 0, shown_wait = 0;
|
||||
static int shown_ces = 0, shown_runmode = MODE_RUN;
|
||||
static int shown_ces = 0, shown_arf = 0, shown_runmode = MODE_RUN;
|
||||
static int CND;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
@@ -402,7 +406,7 @@ void update_gui (BOOL force)
|
||||
static int32 displayed = 0;
|
||||
RECT xin;
|
||||
|
||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed
|
||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { /* setting has changed */
|
||||
displayed = console_unit.flags & UNIT_DISPLAY;
|
||||
if (displayed)
|
||||
init_console_window();
|
||||
@@ -438,6 +442,8 @@ void update_gui (BOOL force)
|
||||
{shown_iar = IAR; RedrawRegion(hConsoleWnd, 75, 8, 364, 32);} /* lamps: don't bother erasing bkgnd */
|
||||
if (SAR != shown_sar)
|
||||
{shown_sar = SAR; RedrawRegion(hConsoleWnd, 75, 42, 364, 65);}
|
||||
if (ARF != shown_arf)
|
||||
{shown_arf = ARF; RedrawRegion(hConsoleWnd, 75, 114, 364, 136);}
|
||||
if (ACC != shown_acc)
|
||||
{shown_acc = ACC; RedrawRegion(hConsoleWnd, 75, 141, 364, 164);}
|
||||
if (EXT != shown_ext)
|
||||
@@ -465,7 +471,7 @@ void update_gui (BOOL force)
|
||||
|
||||
int_lamps = 0;
|
||||
|
||||
// this loop works with lamp buttons that are calculated on-the-fly only
|
||||
/* this loop works with lamp buttons that are calculated on-the-fly only */
|
||||
for (i = 0; i < NBUTTONS; i++) {
|
||||
if (btn[i].pushable)
|
||||
continue;
|
||||
@@ -475,26 +481,28 @@ void update_gui (BOOL force)
|
||||
state = hFlashTimer || (running && ! wait_state);
|
||||
break;
|
||||
|
||||
// this button is always off
|
||||
// case IDC_PARITY_CHECK:
|
||||
/* this button is always off
|
||||
case IDC_PARITY_CHECK
|
||||
*/
|
||||
|
||||
// these buttons are enabled/disabled directly
|
||||
// case IDC_POWER_ON:
|
||||
// case IDC_FILE_READY:
|
||||
// case IDC_FORMS_CHECK:
|
||||
// case IDC_KEYBOARD_SELECT:
|
||||
// case IDC_DISK_UNLOCK:
|
||||
/* these buttons are enabled/disabled directly
|
||||
case IDC_POWER_ON:
|
||||
case IDC_FILE_READY:
|
||||
case IDC_FORMS_CHECK:
|
||||
case IDC_KEYBOARD_SELECT:
|
||||
case IDC_DISK_UNLOCK:
|
||||
*/
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state != btn[i].state) { // state has changed
|
||||
if (state != btn[i].state) { /* state has changed */
|
||||
EnableWindow(btn[i].hBtn, state);
|
||||
btn[i].state = state;
|
||||
}
|
||||
}
|
||||
|
||||
if (force) { // if force flag is set, update text region
|
||||
if (force) { /* if force flag is set, update text region */
|
||||
SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+2*TXTBOX_HEIGHT);
|
||||
InvalidateRect(hConsoleWnd, &xin, TRUE);
|
||||
}
|
||||
@@ -584,9 +592,9 @@ static int occurs (char *txt, char ch)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
// turns out to get properly colored buttons you have to paint them yourself. Sheesh.
|
||||
// On the plus side, this lets do a better job of aligning the button text than
|
||||
// the button would by itself.
|
||||
* turns out to get properly colored buttons you have to paint them yourself. Sheesh.
|
||||
* On the plus side, this lets do a better job of aligning the button text than
|
||||
* the button would by itself.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
void PaintButton (LPDRAWITEMSTRUCT dis)
|
||||
@@ -616,7 +624,7 @@ void PaintButton (LPDRAWITEMSTRUCT dis)
|
||||
LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top);
|
||||
}
|
||||
else if (down) {
|
||||
// do the three-D thing
|
||||
/* do the three-D thing */
|
||||
hOldPen = SelectObject(dis->hDC, hDkGreyPen);
|
||||
MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL);
|
||||
LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top);
|
||||
@@ -776,7 +784,7 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||
|
||||
hcArrow = LoadCursor(NULL, IDC_ARROW);
|
||||
#ifdef IDC_HAND
|
||||
hcHand = LoadCursor(NULL, IDC_HAND); // use stock object provided by Windows
|
||||
hcHand = LoadCursor(NULL, IDC_HAND); /* use stock object provided by Windows */
|
||||
if (hcHand == NULL)
|
||||
hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYHAND));
|
||||
#else
|
||||
@@ -816,12 +824,13 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||
EnableWindow(btn[i].hBtn, btn[i].state);
|
||||
}
|
||||
|
||||
// This isn't needed anymore, now that we have the big printer icon -- it acts like a button now
|
||||
// i = IDC_TEAR;
|
||||
// btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER,
|
||||
// btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
//
|
||||
// SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
/* This isn't needed anymore, now that we have the big printer icon -- it acts like a button now
|
||||
* i = IDC_TEAR;
|
||||
* btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER,
|
||||
* btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
*
|
||||
* SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
*/
|
||||
|
||||
hbm1442_full = LoadBitmap(hInstance, "FULL_1442");
|
||||
hbm1442_empty = LoadBitmap(hInstance, "EMPTY_1442");
|
||||
@@ -836,7 +845,6 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||
btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
btn[i].state = STATE_1442_EMPTY;
|
||||
|
||||
// wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_full);
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_empty);
|
||||
|
||||
i = IDC_1132;
|
||||
@@ -847,13 +855,6 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1132_empty);
|
||||
|
||||
// for (i = 0; i < NTXTBOXES; i++) {
|
||||
// txtbox[i].hBox = CreateWindow("EDIT", txtbox[i].txt,
|
||||
// WS_CHILD|WS_VISIBLE|ES_LEFT|ES_READONLY,
|
||||
// txtbox[i].x, txtbox[i].y, TXTBOX_WIDTH, TXTBOX_HEIGHT, hConsoleWnd, (HMENU) (i+100), hInstance, NULL);
|
||||
// SendMessage(txtbox[i].hBox, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
// }
|
||||
|
||||
GetWindowRect(hConsoleWnd, &r); /* get window size as created */
|
||||
wx = r.right - r.left + 1;
|
||||
wy = r.bottom - r.top + 1;
|
||||
@@ -991,7 +992,7 @@ void DrawRunmode (HDC hDC, int mode)
|
||||
* than a mouse-region test. Return value TRUE means the cursor is over a hotspot.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual)
|
||||
static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual, BOOL rightclick)
|
||||
{
|
||||
int b, x, r, ang, i;
|
||||
|
||||
@@ -1054,9 +1055,10 @@ static void DrawConsole (HDC hDC, PAINTSTRUCT *ps)
|
||||
|
||||
SetBkMode(hDC, TRANSPARENT); /* overlay letters w/o changing background */
|
||||
|
||||
DrawBits(hDC, 76, 15, shown_iar, 16, 0x3FFF, digits);
|
||||
DrawBits(hDC, 76, 48, shown_sar, 16, 0x3FFF, digits);
|
||||
DrawBits(hDC, 76, 15, shown_iar, 16, mem_mask, digits); /* register holds only 15 bits */
|
||||
DrawBits(hDC, 76, 48, shown_sar, 16, mem_mask, digits); /* but let's display only used bits */
|
||||
DrawBits(hDC, 76, 81, shown_sbr, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 114, shown_arf, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 147, shown_acc, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 180, shown_ext, 16, 0xFFFF, digits);
|
||||
|
||||
@@ -1124,10 +1126,10 @@ static void DrawConsole (HDC hDC, PAINTSTRUCT *ps)
|
||||
|
||||
void flash_run (void)
|
||||
{
|
||||
EnableWindow(btn[IDC_RUN].hBtn, TRUE); // enable the run lamp
|
||||
EnableWindow(btn[IDC_RUN].hBtn, TRUE); /* enable the run lamp */
|
||||
|
||||
if (hFlashTimer != 0)
|
||||
KillTimer(hConsoleWnd, FLASH_TIMER_ID); // (re)schedule lamp update
|
||||
KillTimer(hConsoleWnd, FLASH_TIMER_ID); /* (re)schedule lamp update */
|
||||
|
||||
hFlashTimer = SetTimer(hConsoleWnd, FLASH_TIMER_ID, LAMPTIME, NULL);
|
||||
}
|
||||
@@ -1154,10 +1156,12 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||
reset_all(0);
|
||||
if (running && ! power) { /* turning off */
|
||||
reason = STOP_POWER_OFF;
|
||||
// this prevents message pump from running, which unfortunately locks up
|
||||
// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
// while (running)
|
||||
// Sleep(10); /* wait for execution thread to exit */
|
||||
/* wait for execution thread to exit */
|
||||
/* this prevents message pump from running, which unfortunately locks up
|
||||
* the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
* while (running)
|
||||
* Sleep(10);
|
||||
*/
|
||||
}
|
||||
|
||||
btn[IDC_POWER_ON].state = power;
|
||||
@@ -1175,7 +1179,7 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||
case MODE_INT_RUN:
|
||||
case MODE_RUN:
|
||||
case MODE_SI:
|
||||
stuff_cmd("go");
|
||||
stuff_cmd("cont");
|
||||
break;
|
||||
|
||||
case MODE_DISP: /* display core and advance IAR */
|
||||
@@ -1196,16 +1200,17 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||
case IDC_PROGRAM_STOP:
|
||||
if (running) { /* potential race condition here */
|
||||
GUI_BEGIN_CRITICAL_SECTION
|
||||
SETBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
|
||||
int_req |= INT_REQ_5;
|
||||
SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP);
|
||||
int_req |= INT_REQ_5; /* note: calc_ints() is not needed in this case */
|
||||
int_lamps |= INT_REQ_5;
|
||||
GUI_END_CRITICAL_SECTION
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_LOAD_IAR:
|
||||
if (! running) {
|
||||
IAR = CES & 0x3FFF; /* set IAR from console entry switches */
|
||||
IAR = CES & mem_mask; /* set IAR from console entry switches */
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1214,12 +1219,13 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||
|
||||
case IDC_IMM_STOP:
|
||||
if (running) {
|
||||
reason = STOP_WAIT; /* terminate execution without setting wait_mode */
|
||||
|
||||
// this prevents message pump from running, which unfortunately locks up
|
||||
// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
// while (running)
|
||||
// Sleep(10); /* wait for execution thread to exit */
|
||||
reason = STOP_IMMEDIATE; /* terminate execution without setting wait_mode */
|
||||
/* wait for execution thread to exit */
|
||||
/* this prevents message pump from running, which unfortunately locks up
|
||||
* the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
* while (running)
|
||||
* Sleep(10);
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1290,10 +1296,6 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
||||
SetRect(&rbmp, 0, 0, bmwid, bmht);
|
||||
if (IntersectRect(&xsect, &clip, &rbmp))
|
||||
BitBlt(hDC, xsect.left, xsect.top, xsect.right-xsect.left+1, xsect.bottom-xsect.top+1, hCDC, xsect.left, xsect.top, SRCCOPY);
|
||||
// rbmp.top = rbmp.bottom;
|
||||
// rbmp.bottom += 200;
|
||||
// if (IntersectRect(&xsect, &clip, &rbmp))
|
||||
// FillRect(hDC, &xsect, hbBlack);
|
||||
return TRUE; /* let Paint do this so we know what the update region is (ps.rcPaint) */
|
||||
|
||||
case WM_PAINT:
|
||||
@@ -1318,11 +1320,15 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
||||
case WM_SETCURSOR:
|
||||
GetCursorPos(&p);
|
||||
ScreenToClient(hWnd, &p);
|
||||
SetCursor(HandleClick(hWnd, p.x, p.y, FALSE) ? hcHand : hcArrow);
|
||||
SetCursor(HandleClick(hWnd, p.x, p.y, FALSE, FALSE) ? hcHand : hcArrow);
|
||||
return TRUE;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE);
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, FALSE);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, TRUE);
|
||||
break;
|
||||
|
||||
case WM_CTLCOLORBTN:
|
||||
@@ -1339,7 +1345,7 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
||||
break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
accept_dropped_file((HANDLE) wParam); // console window - dragged file is a script or card deck
|
||||
accept_dropped_file((HANDLE) wParam); /* console window - dragged file is a script or card deck */
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1368,7 +1374,7 @@ void forms_check (int set)
|
||||
EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus);
|
||||
|
||||
if (btn[IDC_FORMS_CHECK].clr != oldcolor)
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1389,7 +1395,7 @@ void print_check (int set)
|
||||
EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus);
|
||||
|
||||
if (btn[IDC_FORMS_CHECK].clr != oldcolor)
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1425,34 +1431,34 @@ static void accept_dropped_file (HANDLE hDrop)
|
||||
POINT pt;
|
||||
HWND hWndDrop;
|
||||
|
||||
nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // get file count,
|
||||
DragQueryFile(hDrop, 0, fname, sizeof(fname)); // get first filename
|
||||
DragQueryPoint(hDrop, &pt); // get location of drop
|
||||
nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); /* get file count, */
|
||||
DragQueryFile(hDrop, 0, fname, sizeof(fname)); /* get first filename */
|
||||
DragQueryPoint(hDrop, &pt); /* get location of drop */
|
||||
DragFinish(hDrop);
|
||||
|
||||
if (nfiles <= 0) // hmm, this seems unlikely to occur, but better check
|
||||
if (nfiles <= 0) /* hmm, this seems unlikely to occur, but better check */
|
||||
return;
|
||||
|
||||
if (running) { // can only accept a drop while processor is stopped
|
||||
if (running) { /* can only accept a drop while processor is stopped */
|
||||
MessageBeep(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hWndDrop = ChildWindowFromPoint(hConsoleWnd, pt)) == btn[IDC_1442].hBtn)
|
||||
cardreader = TRUE; // file was dropped onto 1442 card reader
|
||||
cardreader = TRUE; /* file was dropped onto 1442 card reader */
|
||||
else if (hWndDrop == NULL || hWndDrop == hConsoleWnd)
|
||||
cardreader = FALSE; // file was dropped onto console window, not a button
|
||||
cardreader = FALSE; /* file was dropped onto console window, not a button */
|
||||
else {
|
||||
MessageBeep(0); // file was dropped onto another button
|
||||
MessageBeep(0); /* file was dropped onto another button */
|
||||
return;
|
||||
}
|
||||
|
||||
if (nfiles > 1) { // oops, we wouldn't know what order to read them in
|
||||
if (nfiles > 1) { /* oops, we wouldn't know what order to read them in */
|
||||
MessageBox(hConsoleWnd, "You may only drop one file at a time", "", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// if shift key is down, prepend @ to name (make it a deck file)
|
||||
/* if shift key is down, prepend @ to name (make it a deck file) */
|
||||
deckfile = ((GetKeyState(VK_SHIFT) & 0x8000) && cardreader) ? "@" : "";
|
||||
|
||||
sprintf(cmd, "%s \"%s%s\"", cardreader ? "attach cr" : "do", deckfile, fname);
|
||||
@@ -1466,22 +1472,18 @@ static void tear_printer (void)
|
||||
if ((prt_unit.flags & UNIT_ATT) == 0)
|
||||
return;
|
||||
|
||||
strcpy(filename, prt_unit.filename); // save current attached filename
|
||||
strcpy(filename, prt_unit.filename); /* save current attached filename */
|
||||
|
||||
if (! stuff_and_wait("detach prt", 1000, 0)) // detach it
|
||||
if (! stuff_and_wait("detach prt", 1000, 0)) /* detach it */
|
||||
return;
|
||||
|
||||
sprintf(cmd, "view \"%s\"", filename); // spawn notepad to view it
|
||||
sprintf(cmd, "view \"%s\"", filename); /* spawn notepad to view it */
|
||||
if (! stuff_and_wait(cmd, 3000, 500))
|
||||
return;
|
||||
|
||||
// no, now we have them click the card reader icon twice to unload the deck. more flexible that way
|
||||
// if (! stuff_and_wait("detach cr", 1000, 0)) // detach the card reader so they can edit the deck file
|
||||
// return;
|
||||
remove(filename); /* delete the file */
|
||||
|
||||
remove(filename); // delete the file
|
||||
|
||||
sprintf(cmd, "attach prt \"%s\"", filename); // reattach
|
||||
sprintf(cmd, "attach prt \"%s\"", filename); /* reattach */
|
||||
stuff_cmd(cmd);
|
||||
}
|
||||
|
||||
@@ -1582,24 +1584,25 @@ void stuff_cmd (char *cmd)
|
||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||
}
|
||||
|
||||
// my_yield - process GUI messages. It's not apparent why stuff_and_wait would block,
|
||||
// since it sleeps in the GUI thread while scp runs in the main thread. However,
|
||||
// at the end of every command scp calls update_gui, which can result in messages
|
||||
// being sent to the GUI thread. So, the GUI thread has to process messages while
|
||||
// stuff_and_wait is waiting.
|
||||
|
||||
/* my_yield - process GUI messages. It's not apparent why stuff_and_wait would block,
|
||||
* since it sleeps in the GUI thread while scp runs in the main thread. However,
|
||||
* at the end of every command scp calls update_gui, which can result in messages
|
||||
* being sent to the GUI thread. So, the GUI thread has to process messages while
|
||||
* stuff_and_wait is waiting.
|
||||
*/
|
||||
static void my_yield (void)
|
||||
{
|
||||
MSG msg;
|
||||
// multitask
|
||||
/* multitask */
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
// stuff_and_wait -- stuff a command and wait for the emulator to process the command
|
||||
// and come back to prompt for another
|
||||
/* stuff_and_wait -- stuff a command and wait for the emulator to process the command
|
||||
* and come back to prompt for another
|
||||
*/
|
||||
|
||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
||||
{
|
||||
@@ -1650,5 +1653,5 @@ void remark_cmd (char *remark)
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _WIN32 defined
|
||||
#endif // GUI_SUPPORT defined
|
||||
#endif /* _WIN32 defined */
|
||||
#endif /* GUI_SUPPORT defined */
|
||||
|
||||
634
Ibm1130/ibm1130_plot.c
Normal file
634
Ibm1130/ibm1130_plot.c
Normal file
@@ -0,0 +1,634 @@
|
||||
/* ibm1130_plot.c: IBM 1130 1627 plotter emulation
|
||||
|
||||
Based on the SIMH simulator package written by Robert M Supnik
|
||||
|
||||
Brian Knittel
|
||||
Revision History
|
||||
|
||||
2004.10.22 - Written.
|
||||
2006.1.2 - Rewritten as plotter routine by Carl V Claunch
|
||||
|
||||
* (C) Copyright 2004, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to simh@ibm1130.org
|
||||
*/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
|
||||
#ifndef ENABLE_PLOT_SUPPORT
|
||||
|
||||
DEVICE plot_dev = {
|
||||
"PLOT", NULL, NULL, NULL,
|
||||
0, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL};
|
||||
|
||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify)
|
||||
{
|
||||
/* silently eat any plotter commands */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "gd.h"
|
||||
|
||||
/***************************************************************************************
|
||||
* 1627 model 1 plotter (based on Calcomp 535 which was sold as IBM 1627)
|
||||
*
|
||||
* - 11" wide carriage, addressible in .01" steps
|
||||
* - continous sheet paper up to 120' in length
|
||||
* - sheet moveable in .01" steps, either direction
|
||||
* - switchable pen, in various colors and line widths
|
||||
*
|
||||
* Simulator implementation will create a JPEG image corresponding to a
|
||||
* landscape mode sheet of paper, the width of the carriage at 11".
|
||||
* A diagram of more than 8" of paper travel will span printed pages
|
||||
* in landscape mode.
|
||||
*
|
||||
* When an 'att plot' command is issued a file is created based on the
|
||||
* default or currently set values of paper length, starting
|
||||
* position of the pen in both X and Y axes, pen color and pen width.
|
||||
* Based on the number of logical pages of paper, the command will create
|
||||
* the proper size canvas internally and create the output JPEG file.
|
||||
*
|
||||
* When a 'det plot' command is issued, the plotter image will be converted
|
||||
* into the file that was specified during the attach process. The
|
||||
* image is not viewable until this point, unless an examine plot is
|
||||
* issued which will dump the current state of the paper into the file.
|
||||
*
|
||||
* The 'set plot' command can set pen width, paper length, pen color,
|
||||
* current carriage X and Y coordinates. Paper length can be set
|
||||
* to alter the default of 800 (8"); changes are ignored until
|
||||
* the next 'attach' command. The current carriage x and y positions
|
||||
* can be set at any time and will go into effect immediately, just
|
||||
* as the pen color and pen width can be altered on the fly.
|
||||
*
|
||||
* NOTE: requires gd library and definition of ENABLE_PLOT_SUPPORT in makefile or Visual C configuration
|
||||
* gd is not included in the main simh and ibm1130.org distributions at the present time.
|
||||
***************************************************************************************/
|
||||
|
||||
#define PLOT1627_DSW_OP_COMPLETE 0x8000
|
||||
#define PLOT1627_DSW_BUSY 0x0200
|
||||
#define PLOT1627_DSW_NOT_READY 0x0100
|
||||
|
||||
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
|
||||
#define IS_DEBUG ((plot_unit->flags & UNIT_DEBUG) == UNIT_DEBUG)
|
||||
#define IS_PENDOWN ((plot_unit->flags & UNIT_PEN) == UNIT_PEN)
|
||||
|
||||
static t_stat plot_svc (UNIT *uptr); /* activity routine */
|
||||
static t_stat plot_reset (DEVICE *dptr); /* reset of 1130 */
|
||||
static t_stat plot_attach (UNIT *uptr, char *cptr); /* attach, loads plotter */
|
||||
static t_stat plot_detach (UNIT *uptr); /* detach and save image */
|
||||
static t_stat plot_examine (UNIT *uptr); /* update file with current canvas */
|
||||
static t_stat plot_set_length (UNIT *uptr, int32 val, char * ptr, void *desc); /* set paper length */
|
||||
static t_stat plot_set_pos (UNIT *uptr, int32 val, char * ptr, void *desc); /* reset current X/Y position */
|
||||
static t_stat plot_show_vals(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* print x, y and length */
|
||||
static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* overcome wacky simh behavior */
|
||||
static void update_pen(void); /* will ensure pen action is correct when changes made */
|
||||
static t_stat plot_validate_change (UNIT *uptr, int32 val, char * ptr, void *desc); /* when set command issued */
|
||||
static void process_cmd(void); /* does actual drawing for plotter */
|
||||
|
||||
extern int32 sim_switches; /* switches set on simh command */
|
||||
static int16 plot_dsw = 0; /* device status word */
|
||||
static int16 plot_cmd = 0; /* the command to process */
|
||||
static int32 plot_wait = 1000; /* plotter movement wait */
|
||||
static int32 plot_xpos = 0; /* current X position */
|
||||
static int32 plot_xmax = 799; /* end of paper */
|
||||
static int32 plot_ypos = 0; /* current Y position */
|
||||
static int32 plot_ymax = 1099; /* right edge of carriage */
|
||||
|
||||
#define PEN_DOWN 0x80000000
|
||||
#define PEN_UP 0x00000000
|
||||
static int32 plot_pen = PEN_UP; /* current pen position */
|
||||
|
||||
static int black_pen; /* holds color black */
|
||||
static int blue_pen; /* holds color blue */
|
||||
static int red_pen; /* holds color red */
|
||||
static int green_pen; /* holds color green */
|
||||
static int yellow_pen; /* holds yellow color */
|
||||
static int purple_pen; /* holds color purple */
|
||||
static int ltgrey_pen; /* holds light grey */
|
||||
static int grey_pen; /* holds grey */
|
||||
static int white_background; /* holds white of paper roll */
|
||||
static int plot_pwidth; /* set and display variable */
|
||||
static int plot_pcolor; /* set and display variable */
|
||||
static int need_update = 0; /* flag to force and update_pen() */
|
||||
static gdImagePtr image; /* pointer to our canvas */
|
||||
|
||||
#define UNIT_V_COLOR (UNIT_V_UF + 0) /* color of selected pen - 3 bits */
|
||||
#define UNIT_V_WIDTH (UNIT_V_UF + 3) /* width of pen - two bits */
|
||||
#define UNIT_V_NOOP (UNIT_V_UF + 5) /* dummy for set/show commands */
|
||||
#define UNIT_V_DEBUG (UNIT_V_UF + 6) /* for -d switch on attach command */
|
||||
#define UNIT_V_PEN (UNIT_V_UF + 7) /* track pen state */
|
||||
|
||||
#define UNIT_WIDTH (3u << UNIT_V_WIDTH) /* two bits */
|
||||
#define UNIT_COLOR (7u << UNIT_V_COLOR) /* three bits */
|
||||
#define UNIT_NOOP (1u << UNIT_V_NOOP) /* dummy for set/show */
|
||||
#define UNIT_DEBUG (1u << UNIT_V_DEBUG) /* shows debug mode on */
|
||||
#define UNIT_PEN (1u << UNIT_V_PEN) /* the pen state bit */
|
||||
|
||||
#define PEN_BLACK (0u << UNIT_V_COLOR)
|
||||
#define PEN_RED (1u << UNIT_V_COLOR)
|
||||
#define PEN_BLUE (2u << UNIT_V_COLOR)
|
||||
#define PEN_GREEN (3u << UNIT_V_COLOR)
|
||||
#define PEN_YELLOW (4u << UNIT_V_COLOR)
|
||||
#define PEN_PURPLE (5u << UNIT_V_COLOR)
|
||||
#define PEN_LTGREY (6u << UNIT_V_COLOR)
|
||||
#define PEN_GREY (7u << UNIT_V_COLOR)
|
||||
|
||||
#define SET_COLOR(op) {plot_unit[0].flags &= ~UNIT_COLOR; plot_unit[0].flags |= (op);}
|
||||
#define GET_COLOR (plot_unit[0].flags & UNIT_COLOR)
|
||||
|
||||
#define BLACK 0,0,0
|
||||
#define BLUE 0,0,255
|
||||
#define RED 255,0,0
|
||||
#define GREEN 0,255,0
|
||||
#define YELLOW 200,200,0
|
||||
#define PURPLE 150,0,150
|
||||
#define LTGREY 200,200,200
|
||||
#define GREY 120,120,120
|
||||
#define WHITE 255,255,255
|
||||
|
||||
#define PEN_SINGLE (0u << UNIT_V_WIDTH)
|
||||
#define PEN_DOUBLE (1u << UNIT_V_WIDTH)
|
||||
#define PEN_TRIPLE (2u << UNIT_V_WIDTH)
|
||||
#define PEN_QUAD (3u << UNIT_V_WIDTH)
|
||||
|
||||
#define GET_WIDTH() (plot_unit[0].flags & UNIT_WIDTH)
|
||||
#define SET_WIDTH(cd) {plot_unit[0].flags &= ~UNIT_WIDTH; un.flags |= (cd);}
|
||||
|
||||
UNIT plot_unit[] = {
|
||||
{ UDATA (&plot_svc, UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
REG plot_reg[] = {
|
||||
{ HRDATA (DSW, plot_dsw, 16) }, /* device status word */
|
||||
{ DRDATA (WTIME, plot_wait, 24), PV_LEFT }, /* plotter movement wait */
|
||||
{ DRDATA (Xpos, plot_xpos, 32), PV_LEFT }, /* Current X Position*/
|
||||
{ DRDATA (Ypos, plot_ypos, 32), PV_LEFT }, /* Current Y Position*/
|
||||
{ FLDATA (PenDown, plot_pen, 0)}, /* Current pen position - 1 = down */
|
||||
{ DRDATA (PaperSize, plot_xmax, 32), PV_LEFT }, /* Length of paper in inches */
|
||||
{ NULL } };
|
||||
|
||||
MTAB plot_mod[] = {
|
||||
{ UNIT_COLOR, PEN_BLACK, "black", "BLACK", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_RED, "red", "RED", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_BLUE, "blue", "BLUE", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_GREEN, "green", "GREEN", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_YELLOW, "yellow", "YELLOW", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_PURPLE, "purple", "PURPLE", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_LTGREY, "ltgrey", "LTGREY", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_GREY, "grey", "GREY", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_SINGLE, "1.0", "1.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_DOUBLE, "2.0", "2.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_TRIPLE, "3.0", "3.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_QUAD, "4.0", "4.0", &plot_validate_change},
|
||||
{ UNIT_PEN, UNIT_PEN, "pendown", "PENDOWN", &plot_validate_change},
|
||||
{ UNIT_PEN, 0, "penup", "PENUP", &plot_validate_change},
|
||||
/* below is dummy entry to trigger the show routine and print extended values */
|
||||
{ UNIT_NOOP, 0, "", NULL, NULL, &plot_show_vals},
|
||||
/* extended entries must allow parm for both unit and dev, but
|
||||
* then they will print the value twice for a 'show plot' command
|
||||
* therefore they are set to not display unless explicity requested
|
||||
* and the special dummy NOOP entry will cause the print of these values */
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VUN | MTAB_VDV | MTAB_NMO, 2,
|
||||
"length", "LENGTH", &plot_set_length, &plot_show_nl, &plot_reg[5]},
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 0,
|
||||
"Xpos", "XPOS", &plot_set_pos, &plot_show_nl, &plot_reg[2]},
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 1,
|
||||
"Ypos", "YPOS", &plot_set_pos, &plot_show_nl, &plot_reg[3]},
|
||||
{ 0 } };
|
||||
|
||||
DEVICE plot_dev = {
|
||||
"PLOT", plot_unit, plot_reg, plot_mod,
|
||||
1, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, plot_reset,
|
||||
NULL, plot_attach, plot_detach};
|
||||
|
||||
/* xio_1627_plotter - XIO command interpreter for the 1627 plotter model 1 */
|
||||
|
||||
void xio_1627_plotter (iocc_addr, iocc_func, iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
|
||||
if (! IS_ONLINE(plot_unit) ) {
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* set not ready */
|
||||
if (IS_DEBUG) printf("Plotter has no paper, ignored\n");
|
||||
return; /* and ignore */
|
||||
}
|
||||
|
||||
switch (iocc_func) {
|
||||
case XIO_READ: /* read XIO */
|
||||
xio_error("Read XIO not supported by 1627 plotter");
|
||||
break;
|
||||
|
||||
case XIO_WRITE: /* write: do one plotter operation */
|
||||
if ((plot_dsw & PLOT1627_DSW_NOT_READY)) {
|
||||
if (IS_DEBUG) printf("Wrote to non-ready Plotter\n");
|
||||
break;
|
||||
}
|
||||
plot_cmd = (uint16) ( M[iocc_addr & mem_mask] >> 10 ); /* pick up command */
|
||||
process_cmd(); /* interpret command */
|
||||
sim_activate(plot_unit, plot_wait); /* schedule interrupt */
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_BUSY); /* mark it busy */
|
||||
break;
|
||||
|
||||
case XIO_SENSE_DEV: /* sense device status */
|
||||
ACC = plot_dsw; /* get current status */
|
||||
if (iocc_mod & 0x01) { /* reset interrupts */
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE);
|
||||
CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
|
||||
}
|
||||
break;
|
||||
|
||||
case XIO_CONTROL: /* control XIO */
|
||||
xio_error("Control XIO not supported by 1627 plotter");
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(msg, "Invalid 1627 Plotter XIO function %x", iocc_func);
|
||||
xio_error(msg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// plot_svc - 1627 plotter operation complete
|
||||
|
||||
static t_stat plot_svc (UNIT *uptr)
|
||||
{
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_BUSY); /* clear reader busy flag */
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE); /* indicate read complete */
|
||||
|
||||
SETBIT(ILSW[3], ILSW_3_1627_PLOTTER); /* initiate interrupt */
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_reset - reset emulated plotter */
|
||||
|
||||
static t_stat plot_reset (DEVICE *dptr)
|
||||
{
|
||||
char * buf;
|
||||
int32 size;
|
||||
|
||||
sim_cancel(plot_unit);
|
||||
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_BUSY | PLOT1627_DSW_OP_COMPLETE);
|
||||
|
||||
if (IS_DEBUG) printf("reset routine for Plotter\n");
|
||||
|
||||
CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* plot_attach - attach file to simulated plotter */
|
||||
|
||||
static t_stat plot_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat result;
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_DEBUG);
|
||||
if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG);
|
||||
|
||||
/* get the output file by using regular attach routine */
|
||||
result = attach_unit(uptr, cptr);
|
||||
|
||||
if (result != SCPE_OK) {
|
||||
if (IS_DEBUG) printf("problem attaching file\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* assume failure */
|
||||
|
||||
/* set up our canvas at the desired size */
|
||||
image = gdImageCreate(plot_ymax+1,plot_xmax+1); /* create our canvas */
|
||||
if (image == NULL) {
|
||||
if (IS_DEBUG) printf("problem creating image canvas\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
/* set up the basic colors after image created */
|
||||
white_background = gdImageColorAllocate(image,WHITE); /* white is background */
|
||||
black_pen = gdImageColorAllocate(image,BLACK); /* load up black color */
|
||||
blue_pen = gdImageColorAllocate(image,BLUE); /* load up blue color */
|
||||
red_pen = gdImageColorAllocate(image,RED); /* load up red color */
|
||||
green_pen = gdImageColorAllocate(image,GREEN); /* load up green color */
|
||||
yellow_pen = gdImageColorAllocate(image,YELLOW); /* load up yellow color */
|
||||
purple_pen = gdImageColorAllocate(image,PURPLE); /* load up purple color */
|
||||
ltgrey_pen = gdImageColorAllocate(image,LTGREY); /* load up light grey color */
|
||||
grey_pen = gdImageColorAllocate(image,GREY); /* load up grey color */
|
||||
|
||||
if ( (white_background == -1) || (black_pen == -1) ||
|
||||
(red_pen == -1) || (blue_pen == -1) || (green_pen == -1) ||
|
||||
(purple_pen == -1) || (ltgrey_pen == -1) || (grey_pen == -1) ) {
|
||||
if (IS_DEBUG) printf("problem allocating pen colors\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* we're in business */
|
||||
|
||||
update_pen(); /* routine to ensure pen is okay */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* pen updating routine, called at attach and whenever we reset the values */
|
||||
|
||||
void update_pen (void)
|
||||
{
|
||||
int color;
|
||||
int width;
|
||||
|
||||
if (!IS_ONLINE(plot_unit)) return; /* only do this if attached */
|
||||
|
||||
/* pick up latest color as active pen */
|
||||
color = GET_COLOR;
|
||||
switch (color) {
|
||||
case PEN_BLACK:
|
||||
plot_pcolor = black_pen;
|
||||
break;
|
||||
|
||||
case PEN_RED:
|
||||
plot_pcolor = red_pen;
|
||||
break;
|
||||
|
||||
case PEN_BLUE:
|
||||
plot_pcolor = blue_pen;
|
||||
break;
|
||||
|
||||
case PEN_GREEN:
|
||||
plot_pcolor = green_pen;
|
||||
break;
|
||||
|
||||
case PEN_YELLOW:
|
||||
plot_pcolor = yellow_pen;
|
||||
break;
|
||||
|
||||
case PEN_PURPLE:
|
||||
plot_pcolor = purple_pen;
|
||||
break;
|
||||
|
||||
case PEN_LTGREY:
|
||||
plot_pcolor = ltgrey_pen;
|
||||
break;
|
||||
|
||||
case PEN_GREY:
|
||||
plot_pcolor = grey_pen;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid pen color state\n");
|
||||
plot_pcolor = black_pen;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set up anti-aliasing for the line */
|
||||
gdImageSetAntiAliased(image, plot_pcolor);
|
||||
|
||||
/* pick up latest width for pen */
|
||||
width = GET_WIDTH();
|
||||
switch (width) {
|
||||
case PEN_SINGLE:
|
||||
plot_pwidth = 1;
|
||||
gdImageSetThickness(image, 1);
|
||||
break;
|
||||
|
||||
case PEN_TRIPLE:
|
||||
plot_pwidth = 3;
|
||||
gdImageSetThickness(image, 3);
|
||||
break;
|
||||
|
||||
case PEN_DOUBLE:
|
||||
plot_pwidth = 2;
|
||||
gdImageSetThickness(image, 2);
|
||||
break;
|
||||
|
||||
case PEN_QUAD:
|
||||
plot_pwidth = 4;
|
||||
gdImageSetThickness(image, 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid pen width\n");
|
||||
plot_pwidth = 1;
|
||||
gdImageSetThickness(image, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* now ensure the pen state is accurate */
|
||||
plot_pen = IS_PENDOWN ? PEN_DOWN : PEN_UP;
|
||||
return;
|
||||
}
|
||||
|
||||
/* plot_detach - detach file from simulated plotter */
|
||||
static t_stat plot_detach (UNIT *uptr)
|
||||
{
|
||||
char * buf;
|
||||
int32 size;
|
||||
FILE * fp;
|
||||
int32 result;
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY);
|
||||
|
||||
/* copy images to files, close files, set device to detached, free gd memory */
|
||||
|
||||
buf = gdImageGifPtr(image,&size);
|
||||
if (! buf) {
|
||||
if (IS_DEBUG) printf("failure creating GIF in-memory\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
fp = uptr->fileref; /* get file attached to unit */
|
||||
|
||||
if (! fseek(fp,0,SEEK_SET)) { /* first we reset to begin of file */
|
||||
if (IS_DEBUG) printf("wrote out GIF to file\n");
|
||||
result = fwrite(buf,1,size,fp); /* write out our image to the file */
|
||||
}
|
||||
|
||||
gdFree(buf); /* free up the memory of GIF format */
|
||||
gdImageDestroy(image); /* free up the canvas memory */
|
||||
|
||||
if (result != size) { /* some problem writing it */
|
||||
if (IS_DEBUG) printf("error in write of image file\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
return detach_unit(uptr); /* have simh close the file */
|
||||
}
|
||||
|
||||
/* process_cmd - implement the drawing actions of the plotter */
|
||||
|
||||
static void process_cmd (void)
|
||||
{
|
||||
int32 oldx, oldy;
|
||||
|
||||
/* first see if we set any changes to pen or position, do an update */
|
||||
if (need_update) {
|
||||
update_pen();
|
||||
need_update = 0;
|
||||
}
|
||||
|
||||
/* will move pen one step or flip pen up or down */
|
||||
oldx = plot_xpos;
|
||||
oldy = plot_ypos;
|
||||
|
||||
switch (plot_cmd) {
|
||||
case 1: /* raise pen command */
|
||||
plot_pen = PEN_UP;
|
||||
plot_unit->flags = plot_unit->flags & (~UNIT_PEN);
|
||||
return;
|
||||
break;
|
||||
|
||||
case 2: /* +Y command */
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 4: /* -Y command */
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 8: /* -X command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
break;
|
||||
|
||||
case 10: /* -X +Y command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 12: /* -X -Y command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 16: /* +X command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
break;
|
||||
|
||||
case 18: /* +X +Y command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 20: /* +X -Y pen command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 32: /* lower pen command */
|
||||
plot_pen = PEN_DOWN;
|
||||
plot_unit->flags = plot_unit->flags | UNIT_PEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid plotter command\n");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check to see if carriage has moved off any edge */
|
||||
if ((plot_xpos > (plot_xmax+1)) || (plot_ypos > (plot_ymax+1)) ||
|
||||
(plot_xpos < 0) || (plot_ypos < 0)) {
|
||||
/* if so, ignore as 1627 has no way of signalling error */
|
||||
if (IS_DEBUG) printf(
|
||||
"attempted to move carriage off paper edge %d %d for command %d\n",
|
||||
plot_xpos,plot_ypos,plot_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* only draw a line if the pen was down during the movement command */
|
||||
if (plot_pen) {
|
||||
gdImageLine(image, plot_ymax-plot_ypos, plot_xmax-plot_xpos, plot_ymax-oldy, plot_xmax-oldx, gdAntiAliased);
|
||||
/* semantics are 0,0 point is lower right */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* plot_set_length - validate and store the length of the paper */
|
||||
|
||||
static t_stat plot_set_length (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
char *cptr;
|
||||
int32 val;
|
||||
|
||||
#define LONGEST_ROLL 1440000 /* longest is 120', 14400", 1,440,000 .01"s */
|
||||
|
||||
val = strtotv (ptr, &cptr, (uint32) 10); /* sim routine to get value */
|
||||
if ((val < 1) | (val >= LONGEST_ROLL)) { /* check valid range */
|
||||
if (IS_DEBUG) printf("setting paper more than 120' or less than 1 inch\n");
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* origin zero drawing, reduce by 1 but show command will fudge by adding it back */
|
||||
*((int32 *)((REG *) desc)->loc) = val - 1;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_set_pos - validate and store the new position of the carriage */
|
||||
|
||||
static t_stat plot_set_pos (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
char *cptr;
|
||||
int32 val;
|
||||
int32 max;
|
||||
|
||||
max = (set == 1) ? plot_ymax : plot_xmax;
|
||||
val = strtotv (ptr, &cptr, (uint32) 10);
|
||||
if ((val < 0) | (val > max)) {
|
||||
if (IS_DEBUG) printf("error moving carriage off paper edge\n");
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
*((int32 *)((REG *) desc)->loc) = val;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* routine to display the paper length and carriage position
|
||||
* cannot use regular simh routine because it prints values twice,
|
||||
* once for device and once for unit
|
||||
*/
|
||||
|
||||
static t_stat plot_show_vals (FILE *fp, UNIT *uptr, int32 val, void *descrip)
|
||||
{
|
||||
fprintf(fp, "length=%d, Xpos=%d, Ypos=%d",plot_xmax+1, plot_xpos,plot_ypos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* routine to add a terminating NL character when 'show plot length'
|
||||
* or equivalent for xpos or ypos is issued, as simh will not append for us */
|
||||
|
||||
static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip)
|
||||
{
|
||||
int32 disp;
|
||||
char *label;
|
||||
|
||||
disp = (val == 2) ? plot_xmax + 1 : ((val == 1) ? plot_ypos : plot_xpos);
|
||||
label = (val == 2) ? "length=" : ((val == 1) ? "Ypos=" : "Xpos=");
|
||||
|
||||
fprintf(fp, "%s%d\n", label, disp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_validate_change - force the update_pen routine to be called after user changes pen setting */
|
||||
|
||||
static t_stat plot_validate_change (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
need_update = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_PLOT_SUPPORT */
|
||||
@@ -5,6 +5,17 @@
|
||||
Brian Knittel
|
||||
Revision History
|
||||
|
||||
2006.12.06 - Moved CGI stuff out of this routine into cgi1130 main() module.
|
||||
|
||||
2006.07.06 - Made 1403 printer 132 columns wide, was 120 previously
|
||||
|
||||
2006.01.03 - Fixed bug in prt_attach, found and fixed by Carl Claunch. Detach followed
|
||||
by reattach of 1403-mode printer left device permanently not-ready.
|
||||
|
||||
2004.11.08 - HACK for demo mode: in physical (-p) mode, multiple consecutive formfeeds are suppressed.
|
||||
This lets us do a formfeed at the end of a job to kick the last page out
|
||||
without getting another blank page at the beginning of the next job.
|
||||
|
||||
2003.12.02 - Added -p option for physical line printer output (flushes
|
||||
output buffer after each line). When using a physical printer on
|
||||
Windows, be sure to set printer to "send output directly to printer"
|
||||
@@ -36,6 +47,7 @@
|
||||
*/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
#include <stdlib.h> /* needed for atexit, for cgi mode */
|
||||
|
||||
/***************************************************************************************
|
||||
* 1132 PRINTER
|
||||
@@ -87,6 +99,8 @@ static int32 prt_fwait = 100; /* fast wait, for 1403 operations */
|
||||
static int32 prt_twait = 50; /* transfer wait, for 1403 operations */
|
||||
#define SKIPTARGET (uptr->u4) /* target for skip operation */
|
||||
|
||||
static t_bool formfed = FALSE; /* last line printed was a formfeed */
|
||||
|
||||
#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */
|
||||
#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */
|
||||
#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */
|
||||
@@ -145,12 +159,13 @@ DEVICE prt_dev = {
|
||||
NULL, NULL, &prt_reset,
|
||||
NULL, prt_attach, prt_detach};
|
||||
|
||||
#define PRT_COLUMNS 120
|
||||
#define PRT_ROWLEN 120
|
||||
#define MAX_OVPRINT 20
|
||||
#define MAX_COLUMNS 120
|
||||
#define MAX_OVPRINT 20
|
||||
#define PRT1132_COLUMNS 120
|
||||
#define PRT1403_COLUMNS 120 /* the 1130's version of the 1403 printed in 120 columns only (see Functional Characteristics) */
|
||||
|
||||
static char prtbuf[PRT_ROWLEN*MAX_OVPRINT];
|
||||
static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp;
|
||||
static char prtbuf[MAX_COLUMNS*MAX_OVPRINT];
|
||||
static int nprint[MAX_COLUMNS], ncol[MAX_OVPRINT], maxnp;
|
||||
static int prt_nchar, prt_row; /* current printwheel position, current page row */
|
||||
static int prt_nnl; /* number of queued newlines */
|
||||
|
||||
@@ -178,18 +193,18 @@ static struct tag_ccpunches { /* list of rows and punches on tape */
|
||||
int row, channels;
|
||||
}
|
||||
ccpunches[] = {
|
||||
2, CC_CHANNEL_1, // channel 1 = top of form
|
||||
62, CC_CHANNEL_12 // channel 12 = bottom of form
|
||||
2, CC_CHANNEL_1, /* channel 1 = top of form */
|
||||
62, CC_CHANNEL_12 /* channel 12 = bottom of form */
|
||||
},
|
||||
cccgi[] = {
|
||||
2, CC_CHANNEL_1 // channel 1 = top of form; no bottom of form
|
||||
2, CC_CHANNEL_1 /* channel 1 = top of form; no bottom of form */
|
||||
};
|
||||
|
||||
#include "ibm1130_prtwheel.h"
|
||||
|
||||
extern int32 sim_switches;
|
||||
|
||||
// cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read
|
||||
/* cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read */
|
||||
|
||||
static int cc_format_1132 (int bits)
|
||||
{
|
||||
@@ -200,7 +215,7 @@ static int cc_format_1132 (int bits)
|
||||
|
||||
#define cc_format_1403(bits) (bits)
|
||||
|
||||
// reset_prt_line - clear the print line following paper advancement
|
||||
/* reset_prt_line - clear the print line following paper advancement */
|
||||
|
||||
static void reset_prt_line (void)
|
||||
{
|
||||
@@ -209,116 +224,116 @@ static void reset_prt_line (void)
|
||||
maxnp = 0;
|
||||
}
|
||||
|
||||
// save_1132_prt_line - fire hammers for character 'ch'
|
||||
/* save_1132_prt_line - fire hammers for character 'ch' */
|
||||
|
||||
static t_bool save_1132_prt_line (int ch)
|
||||
{
|
||||
int i, r, addr = 32;
|
||||
int32 mask = 0, wd = 0;
|
||||
|
||||
for (i = 0; i < PRT_COLUMNS; i++) {
|
||||
if (mask == 0) { // fetch next word from memory
|
||||
for (i = 0; i < PRT1132_COLUMNS; i++) {
|
||||
if (mask == 0) { /* fetch next word from memory */
|
||||
mask = 0x8000;
|
||||
wd = M[addr++];
|
||||
}
|
||||
|
||||
if (wd & mask) { // hammer is to fire in this column
|
||||
if (wd & mask) { /* hammer is to fire in this column */
|
||||
if ((r = nprint[i]) < MAX_OVPRINT) {
|
||||
if (ncol[r] <= i) { // we haven't moved this far yet
|
||||
if (ncol[r] == 0) // first char in this row?
|
||||
memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row
|
||||
ncol[r] = i+1; // remember new row length
|
||||
if (ncol[r] <= i) { /* we haven't moved this far yet */
|
||||
if (ncol[r] == 0) /* first char in this row? */
|
||||
memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1132_COLUMNS); /* blank out the new row */
|
||||
ncol[r] = i+1; /* remember new row length */
|
||||
}
|
||||
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
|
||||
prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */
|
||||
|
||||
nprint[i]++; // remember max overprintings for this column
|
||||
nprint[i]++; /* remember max overprintings for this column */
|
||||
maxnp = MAX(maxnp, nprint[i]);
|
||||
}
|
||||
}
|
||||
|
||||
mask >>= 1; // prepare to examine next bit
|
||||
mask >>= 1; /* prepare to examine next bit */
|
||||
}
|
||||
|
||||
return wd & 1; // return TRUE if the last word has lsb set, which means all bits had been set
|
||||
return wd & 1; /* return TRUE if the last word has lsb set, which means all bits had been set */
|
||||
}
|
||||
|
||||
// write_line - write collected line to output file. No need to trim spaces as the hammers
|
||||
// are never fired for them, so ncol[r] is the last printed position on each line.
|
||||
/* write_line - write collected line to output file. No need to trim spaces as the hammers
|
||||
* are never fired for them, so ncol[r] is the last printed position on each line.
|
||||
*/
|
||||
|
||||
static void newpage (FILE *fd)
|
||||
static void newpage (FILE *fd, t_bool physical_printer)
|
||||
{
|
||||
if (cgi)
|
||||
fputs("<HR>\n", fd);
|
||||
else
|
||||
putc('\f', fd); // formfeed
|
||||
else if (! formfed) {
|
||||
putc('\f', fd);
|
||||
if (physical_printer) {
|
||||
fflush(fd); /* send the ff out to the printer immediately */
|
||||
formfed = TRUE; /* hack: inhibit consecutive ff's */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_prt_line (FILE *fd, int spacemode, t_bool phys_flush)
|
||||
static void flush_prt_line (FILE *fd, int spacemode, t_bool physical_printer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (! (spacemode || maxnp)) // nothing to do
|
||||
if (! (spacemode || maxnp)) /* nothing to do */
|
||||
return;
|
||||
|
||||
prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line
|
||||
prt_row = (prt_row+1) % PRT_PAGELENGTH; /* NEXT line */
|
||||
|
||||
if (spacemode && ! maxnp) { // spacing only
|
||||
if (spacemode && ! maxnp) { /* spacing only */
|
||||
if (prt_row == 0 && prt_nnl) {
|
||||
#ifdef _WIN32
|
||||
if (! cgi)
|
||||
putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
putc('\r', fd); /* DOS/Windows: end with cr/lf */
|
||||
#endif
|
||||
putc('\n', fd); // otherwise end with lf
|
||||
if (spacemode & UNIT_SKIPPING) // add formfeed if we crossed page boundary while skipping
|
||||
newpage(fd);
|
||||
putc('\n', fd); /* otherwise end with lf */
|
||||
if (spacemode & UNIT_SKIPPING) /* add formfeed if we crossed page boundary while skipping */
|
||||
newpage(fd, physical_printer);
|
||||
|
||||
prt_nnl = 0;
|
||||
}
|
||||
else
|
||||
else {
|
||||
prt_nnl++;
|
||||
formfed = FALSE;
|
||||
}
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
prt_unit->pos++; /* note something written */
|
||||
return;
|
||||
}
|
||||
|
||||
if (prt_nnl) { // there are queued newlines
|
||||
// if we spaced to top of form, don't emit formfeed. We'd only ever emit the formfeed if we skipped via control tape channels
|
||||
// if (prt_row == 0 && prt_nnl) { // we spaced to top of form
|
||||
//#ifdef _WIN32
|
||||
// if (! cgi)
|
||||
// putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
//#endif
|
||||
// putc('\n', fd); // otherwise end with lf
|
||||
// newpage(fd);
|
||||
// prt_nnl = 0;
|
||||
// }
|
||||
// else {
|
||||
while (prt_nnl > 0) { // spit out queued newlines
|
||||
if (prt_nnl) { /* there are queued newlines */
|
||||
while (prt_nnl > 0) { /* spit out queued newlines */
|
||||
#ifdef _WIN32
|
||||
if (! cgi)
|
||||
putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
if (! cgi)
|
||||
putc('\r', fd); /* DOS/Windows: end with cr/lf */
|
||||
#endif
|
||||
putc('\n', fd); // otherwise end with lf
|
||||
prt_nnl--;
|
||||
}
|
||||
// }
|
||||
putc('\n', fd); /* otherwise end with lf */
|
||||
prt_nnl--;
|
||||
}
|
||||
}
|
||||
|
||||
for (r = 0; r < maxnp; r++) {
|
||||
if (r > 0)
|
||||
putc('\r', fd); // carriage return between overprinted lines
|
||||
fxwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd);
|
||||
putc('\r', fd); /* carriage return between overprinted lines */
|
||||
|
||||
fxwrite(&prtbuf[r*MAX_COLUMNS], 1, ncol[r], fd);
|
||||
}
|
||||
|
||||
reset_prt_line();
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
prt_nnl++; // queue a newline
|
||||
prt_unit->pos++; /* note something written */
|
||||
prt_nnl++; /* queue a newline */
|
||||
|
||||
if (phys_flush) // if physical printer, send buffered output to device
|
||||
if (physical_printer) /* if physical printer, send buffered output to device */
|
||||
fflush(fd);
|
||||
|
||||
formfed = FALSE; /* note that something is now on the page */
|
||||
}
|
||||
|
||||
// 1132 printer commands
|
||||
/* 1132 printer commands */
|
||||
|
||||
#define PRT_CMD_START_PRINTER 0x0080
|
||||
#define PRT_CMD_STOP_PRINTER 0x0040
|
||||
@@ -347,7 +362,7 @@ void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
|
||||
|
||||
switch (func) {
|
||||
case XIO_READ:
|
||||
M[iocc_addr & mem_mask] = (uint16) (codewheel1132[prt_nchar].ebcdic << 8);
|
||||
M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8;
|
||||
|
||||
if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */
|
||||
prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132;
|
||||
@@ -364,31 +379,31 @@ void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
|
||||
case XIO_CONTROL:
|
||||
if (modify & PRT_CMD_START_PRINTER) {
|
||||
SETBIT(uptr->flags, UNIT_PRINTING);
|
||||
// mytrace(1, "printing");
|
||||
/* mytrace(1, "printing"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_STOP_PRINTER) {
|
||||
CLRBIT(uptr->flags, UNIT_PRINTING);
|
||||
// mytrace(0, "printing");
|
||||
/* mytrace(0, "printing"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_START_CARRIAGE) {
|
||||
SETBIT(uptr->flags, UNIT_SKIPPING);
|
||||
// mytrace(1, "skipping");
|
||||
/* mytrace(1, "skipping"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_STOP_CARRIAGE) {
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING);
|
||||
// mytrace(0, "skipping");
|
||||
/* mytrace(0, "skipping"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_SPACE) {
|
||||
SETBIT(uptr->flags, UNIT_SPACING);
|
||||
// mytrace(1, "space");
|
||||
/* mytrace(1, "space"); */
|
||||
}
|
||||
|
||||
sim_cancel(uptr);
|
||||
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { // busy bits = doing something
|
||||
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { /* busy bits = doing something */
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY);
|
||||
sim_activate(uptr, prt_cwait);
|
||||
}
|
||||
@@ -419,14 +434,14 @@ static t_stat prt_svc (UNIT *uptr)
|
||||
return IS_1403(uptr) ? prt1403_svc(uptr) : prt1132_svc(uptr);
|
||||
}
|
||||
|
||||
// prt1132_svc - emulated timeout for 1132 operation
|
||||
/* prt1132_svc - emulated timeout for 1132 operation */
|
||||
|
||||
static t_stat prt1132_svc (UNIT *uptr)
|
||||
{
|
||||
if (PRT_DSW & PRT1132_DSW_NOT_READY) { // cancel operation if printer went offline
|
||||
if (PRT_DSW & PRT1132_DSW_NOT_READY) { /* cancel operation if printer went offline */
|
||||
SETBIT(uptr->flags, UNIT_FORMCHECK);
|
||||
SET_ACTION(uptr, 0);
|
||||
forms_check(TRUE); // and turn on forms check lamp
|
||||
forms_check(TRUE); /* and turn on forms check lamp */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -436,7 +451,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE);
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */
|
||||
calc_ints();
|
||||
}
|
||||
|
||||
@@ -445,7 +460,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]));
|
||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch
|
||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); /* slew directly to a cc tape punch */
|
||||
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SKIP_RESPONSE);
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||
@@ -453,21 +468,21 @@ static t_stat prt1132_svc (UNIT *uptr)
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_PRINTING) {
|
||||
if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line
|
||||
SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time
|
||||
if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { /* save previous printed line */
|
||||
SETBIT(uptr->flags, UNIT_DATACHECK); /* buffer wasn't set in time */
|
||||
SET_ACTION(uptr, 0);
|
||||
print_check(TRUE); // and turn on forms check lamp
|
||||
print_check(TRUE); /* and turn on forms check lamp */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; // advance print drum
|
||||
prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; /* advance print drum */
|
||||
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE); // issue interrupt to tell printer to set buffer
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER); // we'll save the printed stuff just before next emitter response (later than on real 1130)
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE); /* issue interrupt to tell printer to set buffer */
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER); /* we'll save the printed stuff just before next emitter response (later than on real 1130) */
|
||||
calc_ints();
|
||||
}
|
||||
|
||||
if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { // still doing something
|
||||
if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { /* still doing something */
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY);
|
||||
sim_activate(uptr, prt_cwait);
|
||||
}
|
||||
@@ -483,18 +498,18 @@ void save_1403_prt_line (int32 addr)
|
||||
unsigned char ebcdic;
|
||||
int32 wd;
|
||||
|
||||
for (i = 0; i < PRT_COLUMNS; i++) {
|
||||
if (even) { // fetch next word from memory
|
||||
for (i = 0; i < PRT1403_COLUMNS; i++) {
|
||||
if (even) { /* fetch next word from memory */
|
||||
wd = M[addr++];
|
||||
ebcdic = (unsigned char) ((wd >> 8) & 0x7F);
|
||||
even = FALSE;
|
||||
}
|
||||
else {
|
||||
ebcdic = (unsigned char) (wd & 0x7F); // use low byte of previously fetched word
|
||||
ebcdic = (unsigned char) (wd & 0x7F); /* use low byte of previously fetched word */
|
||||
even = TRUE;
|
||||
}
|
||||
|
||||
ch = ' '; // translate ebcdic to ascii. Don't bother checking for parity errors
|
||||
ch = ' '; /* translate ebcdic to ascii. Don't bother checking for parity errors */
|
||||
for (j = 0; j < WHEELCHARS_1403; j++) {
|
||||
if (codewheel1403[j].ebcdic == ebcdic) {
|
||||
ch = codewheel1403[j].ascii;
|
||||
@@ -504,14 +519,14 @@ void save_1403_prt_line (int32 addr)
|
||||
|
||||
if (ch > ' ') {
|
||||
if ((r = nprint[i]) < MAX_OVPRINT) {
|
||||
if (ncol[r] <= i) { // we haven't moved this far yet
|
||||
if (ncol[r] == 0) // first char in this row?
|
||||
memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row
|
||||
ncol[r] = i+1; // remember new row length
|
||||
if (ncol[r] <= i) { /* we haven't moved this far yet */
|
||||
if (ncol[r] == 0) /* first char in this row? */
|
||||
memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1403_COLUMNS); /* blank out the new row */
|
||||
ncol[r] = i+1; /* remember new row length */
|
||||
}
|
||||
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
|
||||
prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */
|
||||
|
||||
nprint[i]++; // remember max overprintings for this column
|
||||
nprint[i]++; /* remember max overprintings for this column */
|
||||
maxnp = MAX(maxnp, nprint[i]);
|
||||
}
|
||||
}
|
||||
@@ -568,15 +583,15 @@ void xio_1403_printer (int32 iocc_addr, int32 func, int32 modify)
|
||||
|
||||
static t_stat prt1403_svc(UNIT *uptr)
|
||||
{
|
||||
if (PRT_DSW & PRT1403_DSW_NOT_READY) { // cancel operation if printer went offline
|
||||
if (PRT_DSW & PRT1403_DSW_NOT_READY) { /* cancel operation if printer went offline */
|
||||
SET_ACTION(uptr, 0);
|
||||
forms_check(TRUE); // and turn on forms check lamp
|
||||
forms_check(TRUE); /* and turn on forms check lamp */
|
||||
}
|
||||
else if (uptr->flags & UNIT_TRANSFERRING) { // end of transfer
|
||||
else if (uptr->flags & UNIT_TRANSFERRING) { /* end of transfer */
|
||||
CLRBIT(uptr->flags, UNIT_TRANSFERRING);
|
||||
SETBIT(uptr->flags, UNIT_PRINTING); // schedule "print complete"
|
||||
SETBIT(uptr->flags, UNIT_PRINTING); /* schedule "print complete" */
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); // issue transfer complete interrupt
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); /* issue transfer complete interrupt */
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER);
|
||||
}
|
||||
else if (uptr->flags & UNIT_PRINTING) {
|
||||
@@ -584,14 +599,14 @@ static t_stat prt1403_svc(UNIT *uptr)
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_PRINT_COMPLETE);
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER); // issue print complete interrupt
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER); /* issue print complete interrupt */
|
||||
}
|
||||
else if (uptr->flags & UNIT_SKIPPING) {
|
||||
do { // find line with exact match of tape punches
|
||||
do { /* find line with exact match of tape punches */
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
} while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch
|
||||
} while (cctape[prt_row] != SKIPTARGET); /* slew directly to requested cc tape punch */
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING); /* done with this */
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE);
|
||||
@@ -600,7 +615,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
||||
else if (uptr->flags & UNIT_SPACING) {
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr));
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE);
|
||||
@@ -610,7 +625,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
||||
if (uptr->flags & (UNIT_PRINTING|UNIT_SKIPPING|UNIT_SPACING|UNIT_TRANSFERRING))
|
||||
sim_activate(uptr, prt_fwait);
|
||||
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); // set the two CC bits in the DSW
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); /* set the two CC bits in the DSW */
|
||||
if (cctape[prt_row] & CC_CHANNEL_9)
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CH9);
|
||||
if (cctape[prt_row] & CC_CHANNEL_12)
|
||||
@@ -646,16 +661,17 @@ static t_stat prt_reset (DEVICE *dptr)
|
||||
UNIT *uptr = &prt_unit[0];
|
||||
int i;
|
||||
|
||||
// add a DELETE filename command so we can be sure to have clean listings
|
||||
/* add a DELETE filename command so we can be sure to have clean listings */
|
||||
register_cmd("DELETE", &delete_cmd, 0, "del{ete} filename remove file\n");
|
||||
|
||||
sim_cancel(uptr);
|
||||
|
||||
memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image
|
||||
memset(cctape, 0, sizeof(cctape)); /* copy punch list into carriage control tape image */
|
||||
|
||||
if (cgi)
|
||||
if (cgi) {
|
||||
for (i = 0; i < (sizeof(cccgi)/sizeof(cccgi[0])); i++)
|
||||
cctape[cccgi[i].row-1] |= cccgi[i].channels;
|
||||
}
|
||||
else
|
||||
for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++)
|
||||
cctape[ccpunches[i].row-1] |= ccpunches[i].channels;
|
||||
@@ -697,6 +713,7 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
||||
t_stat rval;
|
||||
/* assume failure */
|
||||
SETBIT(PRT_DSW, IS_1132(uptr) ? PRT1132_DSW_NOT_READY : PRT1403_DSW_NOT_READY);
|
||||
formfed = FALSE;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) {
|
||||
if ((rval = prt_detach(uptr)) != SCPE_OK) {
|
||||
@@ -745,7 +762,7 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
||||
reset_prt_line();
|
||||
|
||||
if (IS_1132(uptr)) {
|
||||
PRT_DSW = (uint16) ((PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]));
|
||||
PRT_DSW = (PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]);
|
||||
|
||||
if (IS_ONLINE(uptr))
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY);
|
||||
@@ -758,10 +775,11 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CH12);
|
||||
|
||||
if (IS_ONLINE(uptr))
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY);
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_NOT_READY); /* fixed by Carl Claunch */
|
||||
}
|
||||
|
||||
forms_check(FALSE);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -769,7 +787,8 @@ static t_stat prt_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat rval;
|
||||
|
||||
flush_prt_line(uptr->fileref, TRUE, TRUE);
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
flush_prt_line(uptr->fileref, TRUE, TRUE);
|
||||
|
||||
if (uptr->fileref == stdout) {
|
||||
CLRBIT(uptr->flags, UNIT_ATT);
|
||||
@@ -797,3 +816,4 @@ static t_stat prt_detach (UNIT *uptr)
|
||||
forms_check(FALSE);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ DEVICE ptp_dev = {
|
||||
|
||||
/* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */
|
||||
|
||||
void xio_1134_papertape (int iocc_addr, int iocc_func, int iocc_mod)
|
||||
void xio_1134_papertape (int32 iocc_addr, int32 iocc_func, int32 iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
|
||||
@@ -118,7 +118,7 @@ void xio_1134_papertape (int iocc_addr, int iocc_func, int iocc_mod)
|
||||
}
|
||||
}
|
||||
|
||||
// ptr_svc - emulated timeout - 1134 read operation complete
|
||||
/* ptr_svc - emulated timeout - 1134 read operation complete */
|
||||
|
||||
static t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ static t_stat ptr_svc (UNIT *uptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// ptp_svc - emulated timeout -- 1055 punch operation complete
|
||||
/* ptp_svc - emulated timeout -- 1055 punch operation complete */
|
||||
|
||||
static t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
@@ -245,37 +245,37 @@ static t_stat ptr_boot (int unitno, DEVICE *dptr)
|
||||
}
|
||||
|
||||
if (leader) {
|
||||
if ((ch & 0x7F) == 0x7F) // ignore leading rubouts or "delete" characters
|
||||
if ((ch & 0x7F) == 0x7F) /* ignore leading rubouts or "delete" characters */
|
||||
continue;
|
||||
|
||||
leader = FALSE; // after first nonrubout, any punch in channel 5 terminates load
|
||||
leader = FALSE; /* after first nonrubout, any punch in channel 5 terminates load */
|
||||
}
|
||||
|
||||
// this is untested -- not sure of actual byte ordering
|
||||
/* this is untested -- not sure of actual byte ordering */
|
||||
|
||||
val = (val << 4) | (ch & 0x0F); // get next nybble
|
||||
val = (val << 4) | (ch & 0x0F); /* get next nybble */
|
||||
|
||||
if (++nch == 4) { // if we now have four nybbles, store the word
|
||||
if (++nch == 4) { /* if we now have four nybbles, store the word */
|
||||
M[addr & mem_mask] = (uint16) val;
|
||||
|
||||
addr++; // prepare for next word
|
||||
addr++; /* prepare for next word */
|
||||
nch = 0;
|
||||
val = 0;
|
||||
}
|
||||
|
||||
if (ch & 0x10) { // channel 5 punch terminates load
|
||||
if (ch & 0x10) { /* channel 5 punch terminates load */
|
||||
start = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! start) // if we didn't get a valid load, report EOF error
|
||||
if (! start) /* if we didn't get a valid load, report EOF error */
|
||||
return SCPE_EOF;
|
||||
|
||||
if ((rval = reset_all(0)) != SCPE_OK) // force a reset
|
||||
if ((rval = reset_all(0)) != SCPE_OK) /* force a reset */
|
||||
return rval;
|
||||
|
||||
IAR = 0; // start running at address 0
|
||||
IAR = 0; /* start running at address 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
1164
Ibm1130/ibm1130_sca.c
Normal file
1164
Ibm1130/ibm1130_sca.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -91,16 +91,13 @@
|
||||
|
||||
static void badio (char *dev)
|
||||
{
|
||||
// the real 1130 just ignores attempts to use uninstalled devices. They get tested
|
||||
// at times, so it's best to just be quiet about this
|
||||
// printf("%s I/O is not yet supported", dev);
|
||||
/* the real 1130 just ignores attempts to use uninstalled devices. They get tested
|
||||
* at times, so it's best to just be quiet about this
|
||||
* printf("%s I/O is not yet supported", dev);
|
||||
*/
|
||||
}
|
||||
|
||||
// void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");}
|
||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");}
|
||||
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");}
|
||||
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");}
|
||||
void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");}
|
||||
void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");}
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
@@ -120,7 +117,7 @@ extern int cgi;
|
||||
|
||||
static int32 tti_dsw = 0; /* device status words */
|
||||
static int32 tto_dsw = 0;
|
||||
static int32 con_dsw = 0;
|
||||
int32 con_dsw = 0;
|
||||
|
||||
static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */
|
||||
static unsigned char conin_map[256]; /* input mapping */
|
||||
@@ -211,9 +208,10 @@ DEVICE tti_dev = {
|
||||
tto_reg TTO register list
|
||||
*/
|
||||
|
||||
// 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced
|
||||
// this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE
|
||||
// to the console and the associated WAIT.
|
||||
/* 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced
|
||||
* this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE
|
||||
* to the console and the associated WAIT.
|
||||
*/
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), 200 };
|
||||
|
||||
@@ -279,7 +277,7 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
||||
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
|
||||
tto_unit.buf = emit_conout_character(ch); /* output character and save write status */
|
||||
|
||||
// fprintf(stderr, "[CONOUT] %02x\n", ch);
|
||||
/* fprintf(stderr, "[CONOUT] %02x\n", ch); */
|
||||
|
||||
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
|
||||
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
|
||||
@@ -300,10 +298,10 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
||||
xio_error(msg);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
}
|
||||
|
||||
// emit_conout_character - write character with 1130 console code 'ch'
|
||||
/* emit_conout_character - write character with 1130 console code 'ch' */
|
||||
|
||||
t_stat emit_conout_character (int ch)
|
||||
{
|
||||
@@ -342,12 +340,12 @@ t_stat emit_conout_character (int ch)
|
||||
return map_conout_character(ch);
|
||||
}
|
||||
|
||||
static void Beep (void) // notify user keyboard was locked or key was bad
|
||||
static void Beep (void) /* notify user keyboard was locked or key was bad */
|
||||
{
|
||||
sim_putchar(7);
|
||||
}
|
||||
|
||||
// tti_svc - keyboard polling (never stops)
|
||||
/* tti_svc - keyboard polling (never stops) */
|
||||
|
||||
static t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
@@ -386,7 +384,7 @@ static t_stat tti_svc (UNIT *uptr)
|
||||
|
||||
if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */
|
||||
SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP);
|
||||
calc_ints();
|
||||
|
||||
#ifdef DEBUG_CONSOLE
|
||||
@@ -417,16 +415,13 @@ static t_stat tti_svc (UNIT *uptr)
|
||||
printf("[%04x]", tti_unit.buf & 0xFFFF);
|
||||
#endif
|
||||
|
||||
// CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (unselect keyboard) */
|
||||
// keyboard_selected(FALSE);
|
||||
|
||||
SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */
|
||||
|
||||
SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */
|
||||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -450,14 +445,14 @@ static t_stat tti_reset (DEVICE *dptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// basic_attach - fix quotes in filename, then call standard unit attach routine
|
||||
/* basic_attach - fix quotes in filename, then call standard unit attach routine */
|
||||
|
||||
t_stat basic_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */
|
||||
}
|
||||
|
||||
// quotefix - strip off quotes around filename, if present
|
||||
/* quotefix - strip off quotes around filename, if present */
|
||||
|
||||
char * quotefix (char * cptr)
|
||||
{
|
||||
@@ -492,7 +487,7 @@ static t_stat tto_svc (UNIT *uptr)
|
||||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
|
||||
return (t_stat) tto_unit.buf; /* return status saved during output conversion */
|
||||
}
|
||||
@@ -648,7 +643,7 @@ static struct { /* default output mapping for APLPLUS font */
|
||||
|
||||
#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0]))
|
||||
|
||||
static OS_MAP default_os_map[] = // overstrike mapping for APLPLUS font
|
||||
static OS_MAP default_os_map[] = /* overstrike mapping for APLPLUS font */
|
||||
{
|
||||
'\x8a', 2, "\x5e\x7e",
|
||||
'\x8b', 2, "\x9f\x7e",
|
||||
@@ -717,12 +712,12 @@ static void strsort (int n, unsigned char *s)
|
||||
unsigned char temp;
|
||||
int i, big;
|
||||
|
||||
while (--n > 0) { // repeatedly
|
||||
big = 0; // find largest value of s[0]...s[n]
|
||||
while (--n > 0) { /* repeatedly */
|
||||
big = 0; /* find largest value of s[0]...s[n] */
|
||||
for (i = 1; i <= n; i++)
|
||||
if (s[i] > s[big]) big = i;
|
||||
|
||||
temp = s[n]; // put largest value at end of array
|
||||
temp = s[n]; /* put largest value at end of array */
|
||||
s[n] = s[big];
|
||||
s[big] = temp;
|
||||
}
|
||||
@@ -730,10 +725,10 @@ static void strsort (int n, unsigned char *s)
|
||||
|
||||
/* file format:
|
||||
|
||||
[font XXX] // font named XXX
|
||||
OUT // failure character
|
||||
OUT IN // single character mapping
|
||||
OUT IN IN ... // overstrike mapping
|
||||
[font XXX] font named XXX
|
||||
OUT failure character
|
||||
OUT IN single character mapping
|
||||
OUT IN IN ... overstrike mapping
|
||||
|
||||
*/
|
||||
|
||||
@@ -742,35 +737,35 @@ static void set_conout_mapping (int32 flags)
|
||||
curcol = 0;
|
||||
maxcol = 0;
|
||||
|
||||
// set the default mappings. We may later override them with settings from an ini file
|
||||
/* set the default mappings. We may later override them with settings from an ini file */
|
||||
|
||||
set_default_mapping(flags);
|
||||
}
|
||||
|
||||
// finish_conout_mapping - sort the finalized overstrike mapping
|
||||
/* finish_conout_mapping - sort the finalized overstrike mapping */
|
||||
|
||||
static void finish_conout_mapping (int32 flags)
|
||||
{
|
||||
int i, n, big;
|
||||
OS_MAP temp;
|
||||
|
||||
for (i = 0; i < n_os_mappings; i++) // sort the inlist strings individually
|
||||
for (i = 0; i < n_os_mappings; i++) /* sort the inlist strings individually */
|
||||
strsort(os_map[i].nin, os_map[i].inlist);
|
||||
|
||||
for (n = n_os_mappings; --n > 0; ) { // then sort the os_map array itself with insertion sort
|
||||
big = 0; // find largest value of s[0]...s[n]
|
||||
for (n = n_os_mappings; --n > 0; ) { /* then sort the os_map array itself with insertion sort */
|
||||
big = 0; /* find largest value of s[0]...s[n] */
|
||||
for (i = 1; i <= n; i++)
|
||||
if (os_map_comp(os_map+i, os_map+big) > 0) big = i;
|
||||
|
||||
if (big != n) {
|
||||
temp = os_map[n]; // put largest value at end of array
|
||||
temp = os_map[n]; /* put largest value at end of array */
|
||||
os_map[n] = os_map[big];
|
||||
os_map[big] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate_conout_mapping - called when set command gets a new value
|
||||
/* validate_conout_mapping - called when set command gets a new value */
|
||||
|
||||
static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc)
|
||||
{
|
||||
@@ -793,7 +788,7 @@ static void reset_mapping (void)
|
||||
conin_map[i] = (unsigned char) i; /* default conin_map is identity map */
|
||||
}
|
||||
|
||||
// set_default_mapping - create standard font and overstrike map
|
||||
/* set_default_mapping - create standard font and overstrike map */
|
||||
|
||||
static void set_default_mapping (int32 flags)
|
||||
{
|
||||
@@ -824,10 +819,10 @@ static void set_default_mapping (int32 flags)
|
||||
break;
|
||||
}
|
||||
|
||||
finish_conout_mapping(flags); // sort conout mapping if necessary
|
||||
finish_conout_mapping(flags); /* sort conout mapping if necessary */
|
||||
}
|
||||
|
||||
// sim_putstr - write a string to the console
|
||||
/* sim_putstr - write a string to the console */
|
||||
|
||||
t_stat sim_putstr (char *s)
|
||||
{
|
||||
@@ -843,7 +838,7 @@ t_stat sim_putstr (char *s)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// map_conout_character - translate and write a single character
|
||||
/* map_conout_character - translate and write a single character */
|
||||
|
||||
static t_stat map_conout_character (int ch)
|
||||
{
|
||||
@@ -857,54 +852,54 @@ static t_stat map_conout_character (int ch)
|
||||
return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr((char *) red_ribbon) : SCPE_OK;
|
||||
|
||||
if ((ch = conout_map[ch & 0xFF]) == 0)
|
||||
ch = '?'; // unknown character? print ?
|
||||
ch = '?'; /* unknown character? print ? */
|
||||
|
||||
if (ch == '\n') { // newline: reset overstrike buffer
|
||||
if (ch == '\n') { /* newline: reset overstrike buffer */
|
||||
curcol = 0;
|
||||
maxcol = -1;
|
||||
}
|
||||
else if (ch == '\r') { // carriage return: rewind to column 0
|
||||
else if (ch == '\r') { /* carriage return: rewind to column 0 */
|
||||
curcol = 0;
|
||||
maxcol = -1; // assume it advances paper too
|
||||
maxcol = -1; /* assume it advances paper too */
|
||||
}
|
||||
else if (ch == '\b') { // backspace: back up one character
|
||||
else if (ch == '\b') { /* backspace: back up one character */
|
||||
if (curcol > 0)
|
||||
curcol--;
|
||||
}
|
||||
else if (n_os_mappings && ch != (unsigned char) IGNR_) {
|
||||
if (curcol >= MAX_OUTPUT_COLUMNS)
|
||||
map_conout_character('\x81'); // precede with automatic carriage return/line feed, I guess
|
||||
map_conout_character('\x81'); /* precede with automatic carriage return/line feed, I guess */
|
||||
|
||||
if (curcol > maxcol) { // first time in this column, no overstrike possible yet
|
||||
if (curcol > maxcol) { /* first time in this column, no overstrike possible yet */
|
||||
os_buf[curcol].nin = 0;
|
||||
maxcol = curcol;
|
||||
}
|
||||
|
||||
if (ch != ' ' && ch != 0) { // (if it's not a blank or unknown)
|
||||
if (ch != ' ' && ch != 0) { /* (if it's not a blank or unknown) */
|
||||
os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch;
|
||||
strsort(++os_buf[curcol].nin, os_buf[curcol].inlist);
|
||||
}
|
||||
|
||||
if (os_buf[curcol].nin == 0) // if nothing but blanks seen,
|
||||
ch = ' '; // output is a blank
|
||||
else if (os_buf[curcol].nin == 1) { // if only one printing character seen, display it
|
||||
if (os_buf[curcol].nin == 0) /* if nothing but blanks seen, */
|
||||
ch = ' '; /* output is a blank */
|
||||
else if (os_buf[curcol].nin == 1) { /* if only one printing character seen, display it */
|
||||
ch = os_buf[curcol].inlist[0];
|
||||
}
|
||||
else { // otherwise look up mapping
|
||||
else { /* otherwise look up mapping */
|
||||
ch = '?';
|
||||
|
||||
for (i = 0; i < n_os_mappings; i++) {
|
||||
cmp = os_map_comp(&os_buf[curcol], &os_map[i]);
|
||||
if (cmp == 0) { // a hit
|
||||
if (cmp == 0) { /* a hit */
|
||||
ch = os_map[i].ch;
|
||||
break;
|
||||
}
|
||||
else if (cmp < 0) // not found
|
||||
else if (cmp < 0) /* not found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (curcol < MAX_OUTPUT_COLUMNS) // this should now never happen, as we automatically return
|
||||
if (curcol < MAX_OUTPUT_COLUMNS) /* this should now never happen, as we automatically return */
|
||||
curcol++;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
Based on PDP-11 simulator written by Robert M Supnik
|
||||
|
||||
Revision History
|
||||
0.27 2005Mar08 - Added sca device
|
||||
0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator
|
||||
0.25 2002Apr18 - Fixed some card reader problems. It starts the reader
|
||||
properly if you attach a deck while it's waiting to a read.
|
||||
@@ -27,9 +28,9 @@
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev;
|
||||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
|
||||
extern DEVICE gdu_dev, console_dev;
|
||||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev, t2741_dev;
|
||||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev, sca_dev;
|
||||
extern DEVICE gdu_dev, console_dev, plot_dev;
|
||||
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
@@ -61,8 +62,11 @@ DEVICE *sim_devices[] = {
|
||||
&prt_dev, /* 1132 printer */
|
||||
&ptr_dev, /* 1134 paper tape reader */
|
||||
&ptp_dev, /* 1055 paper tape punch */
|
||||
&sca_dev, /* Synchronous communications adapter option */
|
||||
&console_dev, /* console display (windows GUI) */
|
||||
&gdu_dev, /* 2250 display */
|
||||
&t2741_dev, /* nonstandard serial interface used by APL\1130 */
|
||||
&plot_dev, /* plotter device, in ibm1130_plot.c */
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -76,7 +80,11 @@ const char *sim_stop_messages[] = {
|
||||
"!BREAK in card deck file",
|
||||
"Phase load break",
|
||||
"Program has run amok",
|
||||
"Run time limit exceeded"
|
||||
"Run time limit exceeded",
|
||||
"Immediate Stop key requested",
|
||||
"Simulator break key pressed",
|
||||
"Simulator step count expired",
|
||||
"Simulator IO error",
|
||||
};
|
||||
|
||||
/* Loader. IPL is normally performed by card reader (boot command). This function
|
||||
@@ -106,13 +114,13 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
||||
int iaddr = -1, runaddr = -1, val, nwords;
|
||||
|
||||
while (fgets(line, sizeof(line), fileref) != NULL) {
|
||||
for (c = line; *c && *c <= ' '; c++) // find first nonblank
|
||||
for (c = line; *c && *c <= ' '; c++) /* find first nonblank */
|
||||
;
|
||||
|
||||
if (*c == '\0' || *c == '#' || *c == '/' || *c == ';')
|
||||
continue; // empty line or comment
|
||||
continue; /* empty line or comment */
|
||||
|
||||
if (*c == '@') { // set load address
|
||||
if (*c == '@') { /* set load address */
|
||||
if (sscanf(c+1, "%x", &iaddr) != 1)
|
||||
return SCPE_FMT;
|
||||
}
|
||||
@@ -124,7 +132,7 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
||||
if (sscanf(c+1, "%x", &val) != 1)
|
||||
return SCPE_FMT;
|
||||
|
||||
CES = val & 0xFFFF; // preload console entry switches
|
||||
CES = val & 0xFFFF; /*preload console entry switches */
|
||||
}
|
||||
else if (*c == 'z' || *c == 'Z') {
|
||||
if (sscanf(c+1, "%x", &nwords) != 1)
|
||||
@@ -145,11 +153,11 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
||||
if (iaddr == -1)
|
||||
return SCPE_FMT;
|
||||
|
||||
WriteW(iaddr, val); // store data
|
||||
WriteW(iaddr, val); /*store data */
|
||||
iaddr++;
|
||||
}
|
||||
else
|
||||
return SCPE_FMT; // unexpected data
|
||||
return SCPE_FMT; /*unexpected data */
|
||||
}
|
||||
|
||||
if (runaddr != -1)
|
||||
@@ -166,14 +174,14 @@ t_stat my_save (FILE *fileref, char *cptr, char *fnam)
|
||||
fprintf(fileref, "@0000\r\n");
|
||||
for (iaddr = 0; iaddr < nwords; iaddr++) {
|
||||
val = ReadW(iaddr);
|
||||
if (val == 0) // queue up zeroes
|
||||
if (val == 0) /*queue up zeroes */
|
||||
nzeroes++;
|
||||
else {
|
||||
if (nzeroes >= 4) { // spit out a Z directive
|
||||
if (nzeroes >= 4) { /*spit out a Z directive */
|
||||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||||
nzeroes = 0;
|
||||
}
|
||||
else { // write queued zeroes literally
|
||||
else { /*write queued zeroes literally */
|
||||
while (nzeroes > 0) {
|
||||
fprintf(fileref, " 0000\r\n");
|
||||
nzeroes--;
|
||||
@@ -182,7 +190,7 @@ t_stat my_save (FILE *fileref, char *cptr, char *fnam)
|
||||
fprintf(fileref, " %04x\r\n", val);
|
||||
}
|
||||
}
|
||||
if (nzeroes >= 4) { // emit any queued zeroes
|
||||
if (nzeroes >= 4) { /*emit any queued zeroes */
|
||||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||||
nzeroes = 0;
|
||||
}
|
||||
@@ -241,7 +249,7 @@ static char *opcode[] = {
|
||||
"AND ", "OR ", "EOR ", "?1F ",
|
||||
};
|
||||
|
||||
static char relative[] = { // true if short mode displacements are IAR relative
|
||||
static char relative[] = { /*true if short mode displacements are IAR relative */
|
||||
FALSE, TRUE, FALSE, FALSE,
|
||||
FALSE, TRUE, FALSE, FALSE,
|
||||
TRUE, FALSE, FALSE, FALSE,
|
||||
@@ -287,10 +295,11 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
|
||||
// if (sw & SWMASK ('A')) { /* ASCII? not useful */
|
||||
// fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
// return SCPE_OK;
|
||||
// }
|
||||
/* if (sw & SWMASK ('A')) { // ASCII? not useful
|
||||
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */
|
||||
sw |= SWMASK('E');
|
||||
@@ -349,7 +358,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||||
DSPLC &= 0x003F;
|
||||
eaddr = DSPLC;
|
||||
}
|
||||
else if ((OP == 0x08 && F)|| OP == 0x09) { // BSI L and BSC any
|
||||
else if ((OP == 0x08 && F)|| OP == 0x09) { /* BSI L and BSC any */
|
||||
if (OP == 0x09 && (IR & 0x40))
|
||||
mnem = "BOSC";
|
||||
|
||||
@@ -368,7 +377,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||||
fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst);
|
||||
return SCPE_OK;
|
||||
}
|
||||
else if (OP == 0x0e && TAG == 0) { // MDX with no tag => MDM or jump
|
||||
else if (OP == 0x0e && TAG == 0) { /* MDX with no tag => MDM or jump */
|
||||
if (F) {
|
||||
fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC);
|
||||
return -1;
|
||||
@@ -446,47 +455,47 @@ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
int strnicmp (char *a, char *b, int n)
|
||||
int strnicmp (const char *a, const char *b, int n)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if (--n < 0) // still equal after n characters? quit now
|
||||
if (--n < 0) /* still equal after n characters? quit now */
|
||||
return 0;
|
||||
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
if ((ca = *a) == 0) /* get character, stop on null terminator */
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
if ((ca -= cb) != 0) /* if different, return comparison */
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
int strcmpi (char *a, char *b)
|
||||
int strcmpi (const char *a, const char *b)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
if ((ca = *a) == 0) /* get character, stop on null terminator */
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
if ((ca -= cb) != 0) /* if different, return comparison */
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
|
||||
388
Ibm1130/ibm1130_t2741.c
Normal file
388
Ibm1130/ibm1130_t2741.c
Normal file
@@ -0,0 +1,388 @@
|
||||
/***************************************************************************************
|
||||
* Nonstandard serial attachment for remote 2741 terminal (IO selectric) used by APL\1130
|
||||
* This implementation may be incomplete and/or incorrect
|
||||
***************************************************************************************/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define DEBUG_T2741
|
||||
|
||||
static TMLN t2741_ldsc = { 0 }; /* line descr for telnet attachment */
|
||||
static TMXR t2741_tmxr = { 1, 0, 0, &t2741_ldsc }; /* line mux for telnet attachment */
|
||||
|
||||
#define T2741_DSW_TRANSMIT_NOT_READY 0x4000
|
||||
#define T2741_DSW_READ_RESPONSE 0x1000
|
||||
#define T2741_DSW_READ_OVERRUN 0x0800
|
||||
#define T2741_DSW_ATTENTION 0x0010
|
||||
|
||||
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
|
||||
|
||||
#define UNIT_V_PHYSICAL_TERM (UNIT_V_UF + 0) /* indicates not telnet but attachment to real terminal */
|
||||
#define UNIT_V_UPCASE (UNIT_V_UF + 1) /* indicates upshift performed */
|
||||
#define UNIT_V_SENDING (UNIT_V_UF + 2) /* indicates not telnet but attachment to real terminal */
|
||||
#define UNIT_V_RECEIVING (UNIT_V_UF + 3) /* indicates not telnet but attachment to real terminal */
|
||||
|
||||
#define UNIT_PHYSICAL_TERM (1u << UNIT_V_PHYSICAL_TERM)
|
||||
#define UNIT_UPCASE (1u << UNIT_V_UPCASE)
|
||||
#define UNIT_SENDING (1u << UNIT_V_SENDING)
|
||||
#define UNIT_RECEIVING (1u << UNIT_V_RECEIVING)
|
||||
|
||||
#define CODE_SHIFTUP 0x1C00
|
||||
#define CODE_SHIFTDOWN 0x7C00
|
||||
#define CODE_CIRCLEC 0x1F00
|
||||
#define CODE_CIRCLED 0x1600
|
||||
#define CODE_RETURN 0x5B00
|
||||
#define CODE_LINEFEED 0x3B00
|
||||
#define CODE_ATTENTION 0x0001 /* pseudocode, never really returned as a received character */
|
||||
#define CODE_UNKNOWN 0x0000
|
||||
|
||||
static t_stat t2741_svc (UNIT *uptr);
|
||||
static t_stat t2741_reset (DEVICE *dptr);
|
||||
static t_stat t2741_attach (UNIT *uptr, char *cptr);
|
||||
static t_stat t2741_detach (UNIT *uptr);
|
||||
static uint16 ascii_to_t2741 (int ascii);
|
||||
static char * t2741_to_ascii (uint16 code);
|
||||
static void set_transmit_notready (void);
|
||||
|
||||
static uint16 t2741_dsw = T2741_DSW_TRANSMIT_NOT_READY; /* device status word */
|
||||
static uint32 t2741_swait = 200; /* character send wait */
|
||||
static uint32 t2741_rwait = 2000; /* character receive wait */
|
||||
static uint16 t2741_char = 0; /* last character received */
|
||||
static int overrun = FALSE;
|
||||
static uint32 t2741_socket = 1130;
|
||||
|
||||
UNIT t2741_unit[1] = {
|
||||
{ UDATA (&t2741_svc, UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
REG t2741_reg[] = {
|
||||
{ HRDATA (DSW, t2741_dsw, 16) }, /* device status word */
|
||||
{ DRDATA (RTIME, t2741_rwait, 24), PV_LEFT }, /* character receive wait */
|
||||
{ DRDATA (STIME, t2741_swait, 24), PV_LEFT }, /* character send wait */
|
||||
{ DRDATA (SOCKET, t2741_socket,16), PV_LEFT }, /* socket number */
|
||||
{ HRDATA (LASTCHAR, t2741_char, 16), PV_LEFT }, /* last character read */
|
||||
{ NULL } };
|
||||
|
||||
DEVICE t2741_dev = {
|
||||
"T2741", t2741_unit, t2741_reg, NULL,
|
||||
1, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, t2741_reset,
|
||||
NULL, t2741_attach, t2741_detach};
|
||||
|
||||
/* xio_t2741_terminal - XIO command interpreter for the terminal adapter */
|
||||
|
||||
void xio_t2741_terminal (int32 iocc_addr, int32 iocc_func, int32 iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
uint16 code;
|
||||
|
||||
switch (iocc_func) {
|
||||
case XIO_READ: /* read: return last character read */
|
||||
code = t2741_char & 0xFF00;
|
||||
M[iocc_addr & mem_mask] = code;
|
||||
overrun = FALSE;
|
||||
#ifdef DEBUG_T2741
|
||||
/* trace_both("T2741 %04x READ %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code)); */
|
||||
#endif
|
||||
break;
|
||||
|
||||
case XIO_WRITE: /* write: initiate character send */
|
||||
code = M[iocc_addr & mem_mask] & 0xFF00;
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 %04x SEND %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code));
|
||||
#endif
|
||||
SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
SETBIT(t2741_unit->flags, UNIT_SENDING);
|
||||
|
||||
if (code == CODE_SHIFTUP)
|
||||
SETBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
else if (code == CODE_SHIFTDOWN)
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
sim_activate(t2741_unit, t2741_swait); /* schedule interrupt */
|
||||
break;
|
||||
|
||||
case XIO_SENSE_DEV: /* sense device status */
|
||||
ACC = t2741_dsw;
|
||||
#ifdef DEBUG_T2741
|
||||
/* trace_both("T2741 %04x SENS %04x%s", prev_IAR, t2741_dsw, (iocc_mod & 0x01) ? " reset" : ""); */
|
||||
#endif
|
||||
if (iocc_mod & 0x01) { /* reset interrupts */
|
||||
CLRBIT(t2741_dsw, T2741_DSW_READ_RESPONSE);
|
||||
CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL);
|
||||
}
|
||||
break;
|
||||
|
||||
case XIO_CONTROL: /* control: do something to interface */
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 %04x CTRL %04x", prev_IAR, iocc_mod &0xFF);
|
||||
#endif
|
||||
SETBIT(t2741_unit->flags, UNIT_RECEIVING); /* set mode to receive mode */
|
||||
if (IS_ONLINE(t2741_unit) && (t2741_char != 0 || ! feof(t2741_unit->fileref))) {
|
||||
sim_activate(t2741_unit, t2741_rwait);
|
||||
t2741_char = (CODE_CIRCLED >> 8); /* first character received after turnaround is circled */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(msg, "Invalid T2741 XIO function %x", iocc_func);
|
||||
xio_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_transmit_notready (void)
|
||||
{
|
||||
if (IS_ONLINE(t2741_unit) && ! (t2741_unit->flags & UNIT_SENDING))
|
||||
CLRBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
else
|
||||
SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
}
|
||||
|
||||
static t_stat t2741_svc (UNIT *uptr)
|
||||
{
|
||||
int ch = EOF;
|
||||
uint16 code;
|
||||
|
||||
if (uptr->flags & UNIT_SENDING) { /* xmit: no interrupt, as far as I know. just clr busy bit */
|
||||
CLRBIT(uptr->flags, UNIT_SENDING);
|
||||
set_transmit_notready();
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_RECEIVING) { /* rcv: fire interrupt */
|
||||
t2741_char <<= 8;
|
||||
|
||||
if (t2741_char == 0) { /* there is no 2nd character from previous ascii input */
|
||||
if ((ch = getc(t2741_unit->fileref)) == EOF)
|
||||
t2741_char = 0;
|
||||
else {
|
||||
if (ch == '\r') { /* if we get CR, jump to LF */
|
||||
if ((ch = getc(t2741_unit->fileref)) != '\n') {
|
||||
ungetc(ch, t2741_unit->fileref);
|
||||
ch = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == '\027') {
|
||||
t2741_char = CODE_LINEFEED; /* attention key sends line feed character */
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 ---- ATTENTION");
|
||||
#endif
|
||||
SETBIT(t2741_dsw, T2741_DSW_ATTENTION); /* no character returned ? */
|
||||
}
|
||||
else {
|
||||
t2741_char = ascii_to_t2741(ch); /* translate to 2741 code(s) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code = t2741_char & 0xFF00;
|
||||
|
||||
if (t2741_char != 0) {
|
||||
if (overrun) /* previous character was not picked up! */
|
||||
SETBIT(t2741_dsw, T2741_DSW_READ_OVERRUN);
|
||||
|
||||
SETBIT(t2741_dsw, T2741_DSW_READ_RESPONSE);
|
||||
SETBIT(ILSW[4], ILSW_4_T2741_TERMINAL); /* issue interrupt */
|
||||
calc_ints();
|
||||
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 ---- RCVD %02x '%s' RDRESP%s%s", code >> 8, t2741_to_ascii(code),
|
||||
(t2741_dsw & T2741_DSW_READ_OVERRUN) ? "|OVERRUN" : "",
|
||||
(t2741_dsw & T2741_DSW_ATTENTION) ? "|ATTENTION" : "");
|
||||
#endif
|
||||
|
||||
overrun = TRUE; /* arm overrun flag */
|
||||
}
|
||||
|
||||
if (t2741_char == CODE_CIRCLEC) /* end of line (CIRCLEC after RETURN) auto downshifts */
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
if (t2741_char == 0 || code == CODE_CIRCLEC)
|
||||
CLRBIT(uptr->flags, UNIT_RECEIVING); /* on enter or EOF, stop typing */
|
||||
else
|
||||
sim_activate(t2741_unit, t2741_rwait); /* schedule next character to arrive */
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat t2741_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ((rval = attach_unit(uptr, cptr)) == SCPE_OK) { /* use standard attach */
|
||||
t2741_char = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
if ((t2741_unit->flags & UNIT_RECEIVING) && ! feof(t2741_unit->fileref))
|
||||
sim_activate(t2741_unit, t2741_rwait); /* schedule interrupt */
|
||||
}
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static t_stat t2741_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat rval;
|
||||
|
||||
if (t2741_unit->flags & UNIT_RECEIVING) /* if receive was pending, cancel interrupt */
|
||||
sim_cancel(t2741_unit);
|
||||
|
||||
t2741_char = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
rval = detach_unit(uptr); /* use standard detach */
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static t_stat t2741_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel(t2741_unit);
|
||||
|
||||
CLRBIT(t2741_unit->flags, UNIT_SENDING|UNIT_RECEIVING|UNIT_UPCASE);
|
||||
|
||||
t2741_char = 0;
|
||||
t2741_dsw = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL);
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static struct tag_t2741_map {
|
||||
int code;
|
||||
int lcase, ucase;
|
||||
t_bool shifts;
|
||||
} t2741_map[] = {
|
||||
{0x4F00, 'A', 'a', TRUE},
|
||||
{0x3700, 'B', 'b', TRUE},
|
||||
{0x2F00, 'C', 'c', TRUE},
|
||||
{0x2A00, 'D', 'd', TRUE},
|
||||
{0x2900, 'E', 'e', TRUE},
|
||||
{0x6700, 'F', '_', TRUE},
|
||||
{0x6200, 'G', 'g', TRUE},
|
||||
{0x3200, 'H', 'h', TRUE},
|
||||
{0x4C00, 'I', 'i', TRUE},
|
||||
{0x6100, 'J', 'j', TRUE},
|
||||
{0x2C00, 'K', '\'', TRUE},
|
||||
{0x3100, 'L', 'l', TRUE},
|
||||
{0x4300, 'M', '|', TRUE},
|
||||
{0x2500, 'N', 'n', TRUE},
|
||||
{0x5100, 'O', 'o', TRUE},
|
||||
{0x6800, 'P', '*', TRUE},
|
||||
{0x6D00, 'Q', '?', TRUE},
|
||||
{0x4A00, 'R', 'r', TRUE},
|
||||
{0x5200, 'S', 's', TRUE},
|
||||
{0x2000, 'T', '~', TRUE},
|
||||
{0x2600, 'U', 'u', TRUE},
|
||||
{0x4600, 'V', 'v', TRUE},
|
||||
{0x5700, 'W', 'w', TRUE},
|
||||
{0x2300, 'X', 'x', TRUE},
|
||||
{0x7300, 'Y', 'y', TRUE},
|
||||
{0x1500, 'Z', 'z', TRUE},
|
||||
{0x1300, '0', '&', TRUE},
|
||||
{0x0200, '1', '?', TRUE},
|
||||
{0x0400, '2', '?', TRUE},
|
||||
{0x0700, '3', '<', TRUE},
|
||||
{0x1000, '4', '?', TRUE},
|
||||
{0x0800, '5', '=', TRUE},
|
||||
{0x0D00, '6', '?', TRUE},
|
||||
{0x0B00, '7', '>', TRUE},
|
||||
{0x0E00, '8', '?', TRUE},
|
||||
{0x1600, '9', '|', TRUE},
|
||||
{0x7000, '/', '\\', TRUE},
|
||||
{0x7600, '+', '-', TRUE},
|
||||
{0x6400, '?', '?', TRUE},
|
||||
{0x4000, '<', '>', TRUE},
|
||||
{0x6B00, '[', '(', TRUE},
|
||||
{0x4900, ']', ')', TRUE},
|
||||
{0x6E00, ',', ';', TRUE},
|
||||
{0x4500, '.', ':', TRUE},
|
||||
{0x0100, ' ', 0, FALSE},
|
||||
{0x5B00, '\r', 0, FALSE},
|
||||
{0x3B00, '\n', 0, FALSE},
|
||||
{0x5D00, '\b', 0, FALSE},
|
||||
{0x5E00, '\t', 0, FALSE},
|
||||
{0x0001, '\027', 0, FALSE},
|
||||
};
|
||||
|
||||
static uint16 ascii_to_t2741 (int ascii)
|
||||
{
|
||||
int i;
|
||||
uint16 rval = 0;
|
||||
|
||||
ascii &= 0xFF;
|
||||
|
||||
if (ascii == '\n') /* turn newlines into returns + CIRCLED? */
|
||||
return CODE_RETURN | (CODE_CIRCLEC >> 8);
|
||||
|
||||
for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) {
|
||||
if (t2741_map[i].shifts) {
|
||||
if (t2741_map[i].lcase == ascii) {
|
||||
rval = t2741_map[i].code;
|
||||
if (t2741_unit->flags & UNIT_UPCASE) {
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
rval = CODE_SHIFTDOWN | (rval >> 8);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
if (t2741_map[i].ucase == ascii) {
|
||||
rval = t2741_map[i].code;
|
||||
if (! (t2741_unit->flags & UNIT_UPCASE)) {
|
||||
SETBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
rval = CODE_SHIFTUP | (rval >> 8);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
else if (t2741_map[i].lcase == ascii)
|
||||
return t2741_map[i].code;
|
||||
}
|
||||
|
||||
return CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static char * t2741_to_ascii (uint16 code)
|
||||
{
|
||||
int i;
|
||||
static char string[2] = {'?', '\0'};
|
||||
|
||||
switch (code) {
|
||||
case CODE_SHIFTUP: return "SHIFTUP";
|
||||
case CODE_SHIFTDOWN: return "SHIFTDN";
|
||||
case CODE_CIRCLEC: return "CIRCLEC";
|
||||
case CODE_CIRCLED: return "CIRCLED";
|
||||
}
|
||||
|
||||
for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) {
|
||||
if (t2741_map[i].code == code) {
|
||||
if (t2741_map[i].shifts) {
|
||||
string[0] = (t2741_unit->flags & UNIT_UPCASE) ? t2741_map[i].ucase : t2741_map[i].lcase;
|
||||
return string;
|
||||
}
|
||||
switch (t2741_map[i].lcase) {
|
||||
case ' ': return " ";
|
||||
case '\r': return "RETURN";
|
||||
case '\n': return "LINEFEED";
|
||||
case '\b': return "BS";
|
||||
case '\t': return "IDLE";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
Reference in New Issue
Block a user