1
0
mirror of https://github.com/rricharz/Tek4010.git synced 2026-01-13 15:27:31 +00:00
2019-04-13 15:57:35 +02:00

249 lines
6.0 KiB
C
Executable File

/*
* ards.c
*
* ARDS option for tek4010 graphics emulator
*
* Copyright 2019 Lars Brinkhoff
*
* https://github.com/rricharz/Tek4010
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include "main.h"
#include "tube.h"
static long startPaintTime;
// mode handles the current state of the emulator:
//
// mode 0 symbol mode
// mode 1 set point mode
// mode 2 extended vector mode
// mode 3 short vector mode
static int mode;
static int args;
static unsigned char data[4];
static int x0 = -485, y0 = 450, x2, y2;
static void draw_char (cairo_t *cr, cairo_t *cr2, char ch)
{
tube_x0 = (x0 + 540)/2;
tube_y0 = (y0 + 707)/2;
//fprintf (stderr, "[tube: %d,%d]", tube_x0, tube_y0);
tube_drawCharacter(cr, cr2, ch);
x0 += 9;
}
static void draw_vector (cairo_t *cr, cairo_t *cr2)
{
tube_x0 = (x0 + 540)/2;
tube_y0 = (y0 + 707)/2;
tube_x2 = (x2 + 540)/2;
tube_y2 = (y2 + 707)/2;
//fprintf (stderr, "[tube: %d,%d - %d,%d]", tube_x0, tube_y0, tube_x2, tube_y2);
tube_drawVector(cr, cr2);
}
void ards_draw(cairo_t *cr, cairo_t *cr2, int first)
// draw onto the main window using cairo
// cr is used for persistent drawing, cr2 for temporary drawing
{
int ch;
refreshCount++; // to calculate the average refresh rate
if (first) {
first = 0;
int actualWidth;
if (argFull) {
efactor = windowHeight / 780.0;
actualWidth = (int)(efactor * 1024.0);
eoffx = (windowWidth - actualWidth) / 2;
refresh_interval = (int)(30.0 * efactor * efactor);
}
else {
efactor = 1.0;
actualWidth = windowWidth;
eoffx = 0;
refresh_interval = 30;
}
windowWidth = actualWidth;
tube_changeCharacterSize(cr, cr2, 74, 35, (int) (10.0 * efactor));
}
startPaintTime = tube_mSeconds(); // start to measure time for this draw operation
showCursor = 1;
isBrightSpot = 0;
// clear the second surface
tube_clearSecond(cr2);
// clear persistent surface, if necessary
if (tube_doClearPersistent) {
tube_clearPersistent(cr,cr2);
}
tube_setupPainting(cr, cr2, "Monospace");
do {
ch = tube_getInputChar();
if (tube_isInput() == 0) {
}
if (ch == -1) {
return; // no char available, need to allow for updates
}
//fprintf (stderr, "\n[INPUT %03o [%d/%d]]", ch, mode, args);
if (args > 0) {
data[--args] = ch;
}
switch (ch) {
case 007:
mode = 0;
args = 0;
break;
case 010:
mode = 0;
args = 0;
x0 -= hDotsPerChar;
break;
case 012:
mode = 0;
args = 0;
y0 -= vDotsPerChar;
break;
case 014:
mode = 0;
args = 0;
x0 = -485;
y0 = 450;
tube_clearPersistent(cr, cr2);
break;
case 015:
mode = 0;
args = 0;
x0 = -479;
break;
case 034:
mode = 0;
args = 0;
break;
case 035:
//fprintf (stderr, "[POINT]");
mode = 1;
args = 4;
break;
case 036:
//fprintf (stderr, "[E VEC]");
mode = 2;
args = 4;
break;
case 037:
//fprintf (stderr, "[S VEC]");
mode = 3;
args = 2;
break;
default:
if (args == 0) {
switch (mode) {
case 0:
//fprintf (stderr, "[SYMBOL %c @ %d, %d]", ch, x0, y0);
draw_char (cr, cr2, ch);
break;
case 1:
args = 4;
x0 = (data[3] & 076) >> 1;
x0 |= (data[2] & 037) << 5;
if (data[3] & 1)
x0 = -x0;
y0 = (data[1] & 076) >> 1;
y0 |= (data[0] & 037) << 5;
if (data[1] & 1)
y0 = -y0;
//fprintf (stderr, "[POINT @ %d, %d]", x0, y0);
break;
case 2:
args = 4;
x2 = (data[3] & 076) >> 1;
x2 |= (data[2] & 037) << 5;
if (data[3] & 1)
x2 = -x2;
x2 += x0;
y2 = (data[1] & 076) >> 1;
y2 |= (data[0] & 037) << 5;
if (data[1] & 1)
y2 = -y2;
y2 += y0;
//fprintf (stderr, "[E VEC @ %d,%d - %d,%d]", x0, y0, x2, y2);
if (data[2] & 040)
; //fprintf (stderr, "[INVISIBLE]");
else
draw_vector(cr, cr2);
if (data[0] & 040)
; //fprintf (stderr, "[DOTTED]");
x0 = x2;
y0 = y2;
break;
case 3:
args = 2;
x2 = (data[1] & 076) >> 1;
if (data[1] & 1)
x2 = -x2;
x2 += x0;
y2 = (data[0] & 076) >> 1;
if (data[0] & 1)
y2 = -y2;
y2 += y0;
draw_vector(cr, cr2);
//fprintf (stderr, "[S VEC @ %d,%d - %d,%d]", x0, y0, x2, y2);
x0 = x2;
y0 = y2;
break;
}
}
break;
}
}
while (((tube_mSeconds() - startPaintTime) < refresh_interval));
// display cursor
if (showCursor && (tube_isInput() == 0)) tube_doCursor(cr2);
}