simh-testsetgenerator/display/ng.c
2022-10-29 14:15:41 -04:00

361 lines
7.9 KiB
C

/*
* Copyright (c) 2018, 2022 Lars Brinkhoff
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the authors shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization
* from the authors.
*/
#include <string.h>
#include <assert.h>
#include "display.h" /* XY plot interface */
#include "ng.h"
/* Bits in the CSR register, type Dazzle. */
#define TKRUN 004000
#define TKGO 010000
#define TKSTOP 020000
/* Number of displays. */
#define DISPLAYS 8
static void *ng_dptr;
static int ng_dbit;
#if defined(__cplusplus)
extern "C" {
#endif
#define DEVICE void
extern void _sim_debug_device (unsigned int dbits, DEVICE* dptr, const char* fmt, ...);
#define DEBUGF(...) _sim_debug_device (ng_dbit, ng_dptr, ## __VA_ARGS__)
#if defined(__cplusplus)
}
#endif
int ng_type = 0;
int ng_scale = PIX_SCALE;
static uint16 status[DISPLAYS];
static int reloc = 0;
static int console = 0;
static int dpc[DISPLAYS];
static int x[DISPLAYS];
static int y[DISPLAYS];
static unsigned char sync_period = 0;
static unsigned char time_out = 0;
int32
ng_get_csr(void)
{
if (ng_type == TYPE_DAZZLE) {
DEBUGF("[%d] Get CSR: ", 0);
if (status[console] & TKRUN)
DEBUGF("running\n");
else
DEBUGF("stopped\n");
return status[console];
} else if (ng_type == TYPE_LOGO) {
DEBUGF("Get CSR: %06o\n", status[0]);
return status[0];
}
return 0;
}
int32
ng_get_reloc(void)
{
return reloc & 0177777;
}
void
ng_set_csr(uint16 d)
{
if (ng_type == TYPE_DAZZLE) {
console = d & 0377;
if (d & TKGO) {
DEBUGF("[%d] Set CSR: GO\n", console);
if ((status[console] & TKRUN) == 0)
dpc[console] = 2*console;
status[console] = TKRUN | console;
}
if (d & TKSTOP) {
DEBUGF("[%d] Set CSR: STOP\n", console);
status[console] = console;
}
} else if (ng_type == TYPE_LOGO) {
DEBUGF("Set CSR: %06o\n", d);
if ((status[0] & 1) == 0 && (d & 1))
dpc[0] = 2*0;
status[0] = d;
}
}
void
ng_set_reloc(uint16 d)
{
reloc = d;
DEBUGF("Set REL: %06o\n", d);
}
int
ng_init(void *dev, int debug)
{
/* Don't change this number. */
assert (DISPLAYS == 8);
ng_dptr = dev;
ng_dbit = debug;
memset (status, 0, sizeof status);
return display_init(DIS_NG, ng_scale, ng_dptr);
}
static int fetch (int a, uint16 *x)
{
return ng_fetch (a + reloc, x);
}
static int store (int a, uint16 x)
{
return ng_store (a + reloc, x);
}
static void point (void)
{
int x1 = x[console];
int y1 = y[console];
DEBUGF("[%d] POINT %d %d\n", console, x[console], y[console]);
display_point(x1 + 256, y1 + 256, DISPLAY_INT_MAX, 0);
}
void increment (uint16 inst)
{
int n = (inst >> 8) & 7;
int i, mask;
if (n == 0)
n = 8;
DEBUGF("[%d] Increment %d, direction %d, bits %o\n",
console, n, (inst >> 11) & 7, inst & 0377);
mask = 0200;
if (ng_type == TYPE_DAZZLE)
mask = 0200 >> (8 - n);
for (i = 0; i < n; i++, mask >>= 1) {
switch (inst & 034000) {
case 000000:
if (inst & mask)
x[console]++;
y[console]++;
break;
case 004000:
if (inst & mask)
y[console]++;
x[console]++;
break;
case 010000:
if (inst & mask)
y[console]--;
x[console]++;
break;
case 014000:
if (inst & mask)
x[console]++;
y[console]--;
break;
case 020000:
if (inst & mask)
x[console]--;
y[console]--;
break;
case 024000:
if (inst & mask)
y[console]--;
x[console]--;
break;
case 030000:
if (inst & mask)
y[console]++;
x[console]--;
break;
case 034000:
if (inst & mask)
x[console]--;
y[console]++;
break;
}
point ();
}
}
void pushj (uint16 inst)
{
uint16 a;
fetch (16 + 2*console, &a);
store (16 + 2*console, a + 1);
store (2*a, dpc[console]);
DEBUGF("[%d] PUSHJ %06o -> %06o (%06o->%06o)\n",
console, dpc[console], inst << 1, a, a+1);
dpc[console] = inst << 1;
}
void stop (void)
{
DEBUGF("[%d] STOP\n", console);
if (ng_type == TYPE_DAZZLE)
status[console] &= ~TKRUN;
else if (ng_type == TYPE_LOGO)
dpc[0] = 2*0;
}
uint16 pop (void)
{
uint16 a;
fetch (16 + 2*console, &a);
store (16 + 2*console, a - 1);
DEBUGF("[%d] POP (%06o -> %06o)\n", console, a, a - 1);
return a - 1;
}
void popj (void)
{
uint16 a, x;
a = pop ();
fetch (2*a, &x);
DEBUGF("[%d] POPJ %06o -> %06o\n", console, dpc[console], x);
dpc[console] = x;
}
void resetx (void)
{
DEBUGF("[%d] RESET X\n", console);
x[console] = 0;
}
void resety (void)
{
DEBUGF("[%d] RESET Y\n", console);
y[console] = 0;
}
void delta (uint16 inst)
{
int delta = inst & 01777;
if (inst & 01000)
delta |= ~0u << 10;
switch (inst & 014000) {
case 000000:
if (inst & 02000)
resetx ();
if (inst & 01000)
resety ();
if (inst & 00400)
stop ();
if (inst & 00200)
pop ();
if (inst & 00100)
popj ();
return;
case 004000:
y[console] += delta;
break;
case 010000:
x[console] += delta;
break;
case 014000:
x[console] += delta;
y[console] += delta;
break;
}
DEBUGF("[%d] DELTA %d\n", console, delta);
if (inst & 02000) {
point ();
}
}
int
ng_cycle(int us, int slowdown)
{
uint16 inst;
static uint32 usec = 0;
static uint32 msec = 0;
uint32 new_msec;
int running = 0;
int saved;
new_msec = (usec += us) / 1000;
/* if awaiting sync, look for next frame start */
if (sync_period && (msec / sync_period != new_msec / sync_period))
sync_period = 0; /* start next frame */
msec = new_msec;
if (ng_type == TYPE_LOGO) {
DEBUGF("LOGO/STATUS %06o\n", status[0]);
if ((status[0] & 1) == 0)
goto age_ret;
} else if (ng_type != TYPE_DAZZLE)
return 0;
if (sync_period)
goto age_ret;
saved = console;
for (console = 0; console < 1; console++) {
if (ng_type == TYPE_DAZZLE && (status[console] & TKRUN) == 0)
continue;
running = 1;
time_out = fetch(dpc[console], &inst);
DEBUGF("[%d] PC %06o, INSTR %06o\n", console, dpc[console], inst);
dpc[console] += 2;
switch (inst & 0160000) {
case 0040000:
case 0060000:
increment (inst);
break;
case 0100000:
case 0120000:
pushj (inst & 037777);
break;
case 0140000:
delta (inst);
break;
}
}
console = saved;
age_ret:
display_age(us, slowdown);
return running || !display_is_blank();
}