BESM6: Implemented punchcard output.

This commit is contained in:
Leo Broukhis 2017-02-06 23:04:40 -08:00
parent 026d082950
commit f46c048bb6
7 changed files with 541 additions and 16 deletions

View file

@ -76,11 +76,7 @@ extern const char *scp_errors[];
GRP_CHAN5_FREE | GRP_CHAN6_FREE |\ GRP_CHAN5_FREE | GRP_CHAN6_FREE |\
GRP_CHAN7_FREE ) GRP_CHAN7_FREE )
/* So far irrelevant as none of the devices -
* punchcard I/O and punchtape output - had been implemented.
*/
#define PRP_WIRED_BITS (PRP_UVVK1_END | PRP_UVVK2_END |\ #define PRP_WIRED_BITS (PRP_UVVK1_END | PRP_UVVK2_END |\
PRP_PCARD1_CHECK | PRP_PCARD2_CHECK |\
PRP_PCARD1_PUNCH | PRP_PCARD2_PUNCH |\ PRP_PCARD1_PUNCH | PRP_PCARD2_PUNCH |\
PRP_PTAPE1_PUNCH | PRP_PTAPE2_PUNCH ) PRP_PTAPE1_PUNCH | PRP_PTAPE2_PUNCH )
@ -285,6 +281,7 @@ DEVICE *sim_devices[] = {
&clock_dev, &clock_dev,
&printer_dev, &printer_dev,
&fs_dev, &fs_dev,
&pi_dev,
&tty_dev, /* терминалы - телетайпы, видеотоны, "Консулы" */ &tty_dev, /* терминалы - телетайпы, видеотоны, "Консулы" */
0 0
}; };
@ -651,12 +648,16 @@ static void cmd_033 ()
/* besm6_debug(">>> гашение АС: %08o", (uint32) ACC & BITS(24));*/ /* besm6_debug(">>> гашение АС: %08o", (uint32) ACC & BITS(24));*/
break; break;
case 0154: case 0155: case 0154: case 0155:
/* TODO: управление выводом на перфокарты */ /*
longjmp (cpu_halt, STOP_UNIMPLEMENTED); * Punchcard output: the two selected bits control the motor
* and the culling mechanism.
*/
pi_control (Aex & 1, (uint32) ACC & 011);
break; break;
case 0160: case 0167: case 0160: case 0161: case 0162: case 0163:
/* TODO: управление электромагнитами пробивки перфокарт */ case 0164: case 0165: case 0166: case 0167:
longjmp (cpu_halt, STOP_UNIMPLEMENTED); /* Punchcard output: activating the punching solenoids, 20 at a time. */
pi_write (Aex & 7, (uint32) ACC & BITS(20));
break; break;
case 0170: case 0171: case 0170: case 0171:
/* TODO: пробивка строки на перфоленте */ /* TODO: пробивка строки на перфоленте */
@ -742,6 +743,11 @@ static void cmd_033 ()
* группами по 8 штук каждые несколько секунд. */ * группами по 8 штук каждые несколько секунд. */
ACC = 0; ACC = 0;
break; break;
case 04160: case 04161: case 04162: case 04163:
case 04164: case 04165: case 04166: case 04167:
/* Punchcard output: reading a punched line for checking, 20 bit at a time */
ACC = pi_read (Aex & 7);
break;
case 04170: case 04171: case 04172: case 04173: case 04170: case 04171: case 04172: case 04173:
/* TODO: считывание контрольного кода /* TODO: считывание контрольного кода
* строки перфоленты */ * строки перфоленты */
@ -764,9 +770,6 @@ static void cmd_033 ()
} else if (04140 <= val && val <= 04157) { } else if (04140 <= val && val <= 04157) {
/* TODO: считывание строки перфокарты */ /* TODO: считывание строки перфокарты */
longjmp (cpu_halt, STOP_UNIMPLEMENTED); longjmp (cpu_halt, STOP_UNIMPLEMENTED);
} else if (04160 <= val && val <= 04167) {
/* TODO: контрольное считывание строки перфокарты */
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
} else { } else {
/* Неиспользуемые адреса */ /* Неиспользуемые адреса */
/* if (sim_deb && cpu_dev.dctrl)*/ /* if (sim_deb && cpu_dev.dctrl)*/

View file

@ -146,6 +146,7 @@ extern DEVICE clock_dev;
extern DEVICE printer_dev; extern DEVICE printer_dev;
extern DEVICE tty_dev; extern DEVICE tty_dev;
extern DEVICE fs_dev; extern DEVICE fs_dev;
extern DEVICE pi_dev;
extern jmp_buf cpu_halt; extern jmp_buf cpu_halt;
/* /*
@ -310,6 +311,12 @@ extern void mmu_setup (void);
extern void mmu_setprotection (int idx, t_value word); extern void mmu_setprotection (int idx, t_value word);
extern void mmu_print_brz (void); extern void mmu_print_brz (void);
/*
* Utility functions
*/
extern void gost_putc(unsigned char, FILE *);
extern int odd_parity(unsigned char);
/* /*
* Выполнение обращения к барабану. * Выполнение обращения к барабану.
*/ */
@ -348,6 +355,13 @@ int vt_is_idle (void);
void fs_control (int num, uint32 cmd); void fs_control (int num, uint32 cmd);
int fs_read (int num); int fs_read (int num);
/*
* Вывод на перфокарты.
*/
void pi_control (int num, uint32 cmd);
void pi_write (int num, uint32 cmd);
int pi_read (int num);
/* /*
* Отладочная выдача. * Отладочная выдача.
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* besm6_punch.c: BESM-6 punchcard/punchtape devices * besm6_punch.c: BESM-6 punchtape devices
* *
* Copyright (c) 2009, Leonid Broukhis * Copyright (c) 2009, Leonid Broukhis
* *
@ -29,7 +29,6 @@
#include "besm6_defs.h" #include "besm6_defs.h"
t_stat fs_event (UNIT *u); t_stat fs_event (UNIT *u);
t_stat uvvk_event (UNIT *u);
UNIT fs_unit [] = { UNIT fs_unit [] = {
{ UDATA (fs_event, UNIT_SEQ+UNIT_ATTABLE, 0) }, { UDATA (fs_event, UNIT_SEQ+UNIT_ATTABLE, 0) },

505
BESM6/besm6_punchcard.c Normal file
View file

@ -0,0 +1,505 @@
/*
* besm6_punchcard.c: BESM-6 punchcard devices
*
* Copyright (c) 2017, Leonid Broukhis
*
* 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
* SERGE VAKULENKO OR LEONID BROUKHIS 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 name of Leonid Broukhis or
* Serge Vakulenko shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from Leonid Broukhis and Serge Vakulenko.
*/
#include "besm6_defs.h"
#if 0
/*
* Punchcard input not yet implemented.
*/
t_stat uvvk_event (UNIT *u); /* punched card reader */
UNIT uvvk_unit [] = {
{ UDATA (uvvk_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
{ UDATA (uvvk_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
};
#endif
t_stat pi_event (UNIT *u); /* punched card writer */
UNIT pi_unit [] = {
{ UDATA (pi_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
{ UDATA (pi_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
};
/*
* Each line has 3 phases:
* - striking: the "PUNCH" interrupt line goes high,
* puncher solenoids can be activated
* - moving: solenoids are turned off, the "PUNCH" interrupt line goes low
* - checking: the "CHECK" interrupt goes high,
* querying of the check brushes can be done.
*/
typedef enum {
PI_STRIKE,
PI_MOVE,
PI_CHECK,
PI_LAST = PI_STRIKE + 3*12 - 1,
PI_PAUSE,
PI_IDLE
} pi_state_t;
typedef struct {
/*
* A 3-card long tract, with 12 lines per card,
* represented as 4 20-bit registers each.
*/
uint32 image[3][12][4];
int cur; /* FIFO position */
int running; /* continue with the next card */
pi_state_t state;
void (*punch_fn)(int, int);
} pi_t;
/*
* There are 2 card punchers */
pi_t PI[2];
#define PI1_READY (1<<15)
#define PI2_READY (1<<13)
#define PI1_START (1<<14)
#define PI2_START (1<<12)
// #define NEGATIVE_RDY
#ifndef NEGATIVE_RDY
# define ENB_RDY2 SET_RDY2
# define DIS_RDY2 CLR_RDY2
# define IS_RDY2 ISSET_RDY2
#else
# define ENB_RDY2 CLR_RDY2
# define DIS_RDY2 SET_RDY2
# define IS_RDY2 ISCLR_RDY2
#endif
#define SET_RDY2(x) do READY2 |= x; while (0)
#define CLR_RDY2(x) do READY2 &= ~(x); while (0)
#define ISSET_RDY2(x) ((READY2 & (x)) != 0)
#define ISCLR_RDY2(x) ((READY2 & (x)) == 0)
/*
* Per one line of a punched card.
*/
#define PI_RATE (20*MSEC)
const uint32 pi_punch_mask[2] = { PRP_PCARD1_PUNCH, PRP_PCARD2_PUNCH };
const uint32 pi_check_mask[2] = { PRP_PCARD1_CHECK, PRP_PCARD2_CHECK };
const uint32 pi_ready_mask[2] = { PI1_READY, PI2_READY };
const uint32 pi_start_mask[2] = { PI1_START, PI2_START };
REG pi_reg[] = {
{ REGDATA ( "READY", READY2, 2, 4, 12, 1, NULL, NULL, 0, 0, 0) },
{ 0 }
};
MTAB pi_mod[] = {
{ 0 }
};
t_stat pi_reset (DEVICE *dptr);
t_stat pi_attach (UNIT *uptr, CONST char *cptr);
t_stat pi_detach (UNIT *uptr);
DEVICE pi_dev = {
"PI", pi_unit, pi_reg, pi_mod,
2, 8, 19, 1, 8, 50,
NULL, NULL, &pi_reset, NULL, &pi_attach, &pi_detach,
NULL, DEV_DISABLE | DEV_DEBUG
};
/*
* Outputs 12 lines of 80 characters plus an empty line.
*/
static void pi_punch_dots(int unit, int card) {
UNIT *u = &pi_unit[unit];
FILE * f = u->fileref;
int l, p, c;
for (l = 0; l < 12; ++l) {
for (p = 0; p < 4; ++p)
for (c = 19; c >= 0; --c)
putc((PI[unit].image[card][l][p] >> c) & 1 ? 'O' : '.', f);
putc('\n', f);
}
putc('\n', f);
}
static void pi_to_bytes(int unit, int card, unsigned char buf[120]) {
int byte = 0;
int cnt = 0;
int l, p, c;
for (l = 0; l < 12; ++l) {
for (p = 0; p < 4; ++p) {
for (c = 19; c >= 0; --c) {
int bit = (PI[unit].image[card][l][p] >> c) & 1 ? 1 : 0;
buf[byte] <<= 1;
buf[byte] |= bit;
if (++cnt == 8) {
cnt = 0;
++byte;
}
}
}
}
}
/*
* Outputs 120 bytes, read linewise.
*/
static void pi_punch_binary(int unit, int card) {
UNIT *u = &pi_unit[unit];
FILE * f = u->fileref;
unsigned char buf[120];
pi_to_bytes(unit, card, buf);
fwrite(buf, 120, 1, f);
}
/*
* Outputs a visual representation of the card
* using 3 lines of 40 Braille patterns, plus an empty line.
*/
static void pi_punch_visual(int unit, int card) {
UNIT *u = &pi_unit[unit];
FILE * f = u->fileref;
// Print 3 lines of 40 Braille characters per line representing a punchcard.
unsigned char bytes[3][40];
int line, col, p, c;
memset(bytes, 0, 120);
for (line = 0; line < 12; ++line) {
for (p = 0; p < 4; ++p)
for (c = 19; c >= 0; --c) {
int bit = (PI[unit].image[card][line][p] >> c) & 1 ? 1 : 0;
int col = p*20 + 19-c;
if (bit) {
/*
* Braille Unicode codepoints are U+2800 plus
* an 8-bit mask of punches according to the map
* 0 3
* 1 4
* 2 5
* 6 7
*/
bytes[line/4][col/2] |=
"\x01\x08\x02\x10\x04\x20\x40\x80"[line%4*2+col%2];
}
}
}
for (line = 0; line < 3; ++line) {
for (col = 0; col < 40; ++col) {
fprintf(f, "\342%c%c",
0240+(bytes[line][col] >> 6),
0200 + (bytes[line][col] & 077));
}
putc('\n', f);
}
putc('\n', f);
}
/*
* Attempts to interpret a card as GOST-10859 with odd parity;
* if fails, dumps visual.
*/
static void pi_punch_gost(int unit, int card) {
UNIT *u = &pi_unit[unit];
FILE * f = u->fileref;
unsigned char buf[120];
int len;
int cur;
int zero_expected = 0;
pi_to_bytes(unit, card, buf);
/*
* Bytes in the buffer must have odd parity, with the exception
* of optional zero bytes at the end of lines and at the end of a card.
* Trailing zeros are trimmed, intermediate zeros become blanks.
* The first character in each line must be valid.
*/
for (len = 120; len && !buf[len-1]; --len);
for (cur = 0; cur < len; ++cur) {
if (cur % 10 == 0) {
/* A new line */
zero_expected = 0;
}
if (zero_expected) {
if (buf[cur])
break;
} else if (!buf[cur]) {
if (cur % 10 == 0) {
/* The first char in a line is zero */
break;
}
zero_expected = 1;
} else if (!odd_parity(buf[cur]) || (buf[cur] & 0177) >= 0140) {
break;
}
}
if (cur != len) {
/* Bad parity or invalid codepoint detected */
pi_punch_visual(unit, card);
} else {
for (cur = 0; cur < len; ++cur) {
if (buf[cur]) {
gost_putc(buf[cur] & 0177, f);
} else {
putc(' ', f);
}
}
putc('\n', f);
}
}
/*
* Dumps the last card in the FIFO and advances the FIFO pointer
* (this is equivalent to advancing the FIFO pointer and dumping
* the "current" card).
*/
static void pi_output (int unit, int cull) {
int card;
PI[unit].cur = card = (PI[unit].cur + 1) % 3;
if (cull) {
besm6_debug("<<< PI-%d: Culling bad card", unit);
} else {
(*PI[unit].punch_fn)(unit, card);
}
pi_unit[unit].pos = ftell(pi_unit[unit].fileref);
memset(PI[unit].image[card], 0, sizeof(PI[unit].image[card]));
}
/*
* Reset routine
*/
t_stat pi_reset (DEVICE *dptr)
{
sim_cancel (&pi_unit[0]);
sim_cancel (&pi_unit[1]);
PI[0].state = PI[1].state = PI_IDLE;
DIS_RDY2(PI1_READY | PI2_READY);
if (pi_unit[0].flags & UNIT_ATT)
ENB_RDY2(PI1_READY|PI1_START);
if (pi_unit[1].flags & UNIT_ATT)
ENB_RDY2(PI2_READY|PI2_START);
return SCPE_OK;
}
/*
* Punching mode switches:
* -b - raw binary, line-wise, 120 bytes per p/c;
* -v - a visual form using Unicode Braille patterns;
* -d - a visual form using dots and Os;
* -g or -u - attempts to interpret the card as GOST/UPP text.
* The default is -v.
*/
t_stat pi_attach (UNIT *u, CONST char *cptr)
{
t_stat s;
int unit = u - pi_unit;
PI[unit].punch_fn = NULL;
while (sim_switches &
(SWMASK('B')|SWMASK('V')|SWMASK('D')|SWMASK('G')|SWMASK('U'))) {
if (PI[unit].punch_fn) {
return SCPE_ARG;
}
if (sim_switches & SWMASK('B')) {
PI[unit].punch_fn = pi_punch_binary;
sim_switches &= ~SWMASK('B');
} else if (sim_switches & SWMASK('V')) {
PI[unit].punch_fn = pi_punch_visual;
sim_switches &= ~SWMASK('V');
} else if (sim_switches & SWMASK('D')) {
PI[unit].punch_fn = pi_punch_dots;
sim_switches &= ~SWMASK('D');
} else if (sim_switches & SWMASK('G')) {
PI[unit].punch_fn = pi_punch_gost;
sim_switches &= ~SWMASK('G');
} else if (sim_switches & SWMASK('U')) {
PI[unit].punch_fn = pi_punch_gost;
sim_switches &= ~SWMASK('U');
}
}
if (PI[unit].punch_fn == NULL) {
PI[unit].punch_fn = pi_punch_visual;
}
s = attach_unit (u, cptr);
if (s != SCPE_OK)
return s;
ENB_RDY2(pi_ready_mask[unit]);
return SCPE_OK;
}
t_stat pi_detach (UNIT *u)
{
int unit = u - pi_unit;
DIS_RDY2(pi_ready_mask[unit]);
return detach_unit (u);
}
void pi_control (int num, uint32 cmd)
{
UNIT *u = &pi_unit[num];
if (pi_dev.dctrl)
besm6_debug("<<<PI-%d cmd %o, state %d", num, cmd, PI[num].state);
cmd &= 011;
if (! IS_RDY2(pi_ready_mask[num])) {
if (pi_dev.dctrl)
besm6_debug("<<< PI-%d not ready", num, cmd);
return;
}
switch (cmd) {
case 000: /* stop */
case 010: /* stop with culling (doesn't make much sense) */
if (PI[num].state == PI_LAST) {
pi_output(num, cmd & 010);
}
sim_cancel (u);
PI[num].state = PI_IDLE;
ENB_RDY2(pi_start_mask[num]);
break;
case 001: /* start without culling */
case 011: /* start with culling */
switch (PI[num].state) {
case PI_IDLE:
sim_activate (u, PI_RATE);
break;
case PI_PAUSE:
/* Switching on during pause ignored */
besm6_debug("<<< PI-%d switching on during pause ignored", num);
break;
case PI_LAST:
PI[num].running = 1;
/* This is the only state when the cull bit is honored */
pi_output(num, cmd & 010);
break;
default:
PI[num].running = 1;
break;
} break;
}
}
t_stat pi_event (UNIT *u)
{
int unit = u - pi_unit;
if (++PI[unit].state > PI_IDLE) {
/* Starting a new card */
PI[unit].state = PI_STRIKE;
}
switch (PI[unit].state) {
case PI_LAST:
/*
* At the last check interrupt,
* the "permission to start" flag is cleared.
*/
DIS_RDY2(pi_start_mask[unit]);
break;
case PI_PAUSE:
/*
* The permission to start is re-enabled.
*/
ENB_RDY2(pi_start_mask[unit]);
PI[unit].state = PI_IDLE;
if (PI[unit].running) {
if (pi_dev.dctrl)
besm6_debug ("<<< PI-%d re-enabled", unit);
sim_activate(u, PI_RATE);
PI[unit].running = 0;
} else {
/*
* The unit is going idle without an explicit "stop" command:
* The last card (the separator) falls into the "good" bin.
*/
pi_output(unit, 0);
}
break;
default:
break;
}
if (pi_dev.dctrl)
besm6_debug ("<<< PI-%d event, state %d", unit, PI[unit].state);
if (PI[unit].state <= PI_LAST) {
switch (PI[unit].state % 3) {
case PI_STRIKE:
/* Punch interrupt */
PRP |= pi_punch_mask[unit];
sim_activate(u, PI_RATE/3);
break;
case PI_MOVE:
/* Punchers off */
PRP &= ~pi_punch_mask[unit];
sim_activate(u, 2*PI_RATE/3);
break;
case PI_CHECK:
/* Check interrupt */
PRP |= pi_check_mask[unit];
sim_activate(u, PI_RATE);
}
}
return SCPE_OK;
}
/*
* Writing to the register punches the current card.
*/
void pi_write (int num, uint32 val)
{
int unit = num >> 2;
int card = PI[unit].cur;
int pos = (num & 3) ^ 3;
int line = PI[unit].state / 3;
if (line > 11 || PI[unit].state % 3 != PI_STRIKE) {
besm6_debug("<<< PI-%d, writing out of turn, useless", num);
return;
}
if (pi_dev.dctrl) {
besm6_debug("Card %d line %d pos %d <- val %05x",
card, line, pos, val);
}
PI[unit].image[card][line][pos] = val;
}
/*
* Reading from the register reads the previous card
* and returns the inverted value.
*/
int pi_read (int num)
{
int unit = num >> 2;
int pos = (num & 3) ^ 3;
int line = PI[unit].state / 3;
int card = (PI[unit].cur + 2) % 3;
if (line > 11 || PI[unit].state % 3 != PI_CHECK) {
/* Reading out of turn */
return 0xFFFFF;
} else {
if (pi_dev.dctrl) {
besm6_debug("Card %d line %d pos %d -> val %05x",
card, line, pos, PI[unit].image[card][line][pos]);
}
return PI[unit].image[card][line][pos] ^ 0xFFFFF;
}
}

View file

@ -220,6 +220,10 @@
RelativePath="..\BESM6\besm6_punch.c" RelativePath="..\BESM6\besm6_punch.c"
> >
</File> </File>
<File
RelativePath="..\BESM6\besm6_punchcard.c"
>
</File>
<File <File
RelativePath="..\BESM6\besm6_sys.c" RelativePath="..\BESM6\besm6_sys.c"
> >

View file

@ -664,7 +664,7 @@ BESM6_LIB = $(LIB_DIR)BESM6-$(ARCH).OLB
BESM6_SOURCE = $(BESM6_DIR)BESM6_CPU.C,$(BESM6_DIR)BESM6_SYS.C,$(BESM6_DIR)BESM6_MMU.C,\ BESM6_SOURCE = $(BESM6_DIR)BESM6_CPU.C,$(BESM6_DIR)BESM6_SYS.C,$(BESM6_DIR)BESM6_MMU.C,\
$(BESM6_DIR)BESM6_ARITH.C,$(BESM6_DIR)BESM6_DISK.C,$(BESM6_DIR)BESM6_DRUM.C,\ $(BESM6_DIR)BESM6_ARITH.C,$(BESM6_DIR)BESM6_DISK.C,$(BESM6_DIR)BESM6_DRUM.C,\
$(BESM6_DIR)BESM6_TTY.C,$(BESM6_DIR)BESM6_PANEL.C,$(BESM6_DIR)BESM6_PRINTER.C,\ $(BESM6_DIR)BESM6_TTY.C,$(BESM6_DIR)BESM6_PANEL.C,$(BESM6_DIR)BESM6_PRINTER.C,\
$(BESM6_DIR)BESM6_PUNCH.C $(BESM6_DIR)BESM6_PUNCHCARD.C,$(BESM6_DIR)BESM6_PUNCH.C
BESM6_OPTIONS = /INCL=($(SIMH_DIR),$(BESM6_DIR))/DEF=($(CC_DEFS),"USE_INT64=1") BESM6_OPTIONS = /INCL=($(SIMH_DIR),$(BESM6_DIR))/DEF=($(CC_DEFS),"USE_INT64=1")
# #

View file

@ -1438,7 +1438,7 @@ BESM6D = BESM6
BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \ BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \
${BESM6D}/besm6_arith.c ${BESM6D}/besm6_disk.c ${BESM6D}/besm6_drum.c \ ${BESM6D}/besm6_arith.c ${BESM6D}/besm6_disk.c ${BESM6D}/besm6_drum.c \
${BESM6D}/besm6_tty.c ${BESM6D}/besm6_panel.c ${BESM6D}/besm6_printer.c \ ${BESM6D}/besm6_tty.c ${BESM6D}/besm6_panel.c ${BESM6D}/besm6_printer.c \
${BESM6D}/besm6_punch.c ${BESM6D}/besm6_punch.c ${BESM6D}/besm6_punchcard.c
ifneq (,$(BESM6_BUILD)) ifneq (,$(BESM6_BUILD))
ifneq (,$(and ${VIDEO_LDFLAGS}, $(or $(and $(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf)), $(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf))))) ifneq (,$(and ${VIDEO_LDFLAGS}, $(or $(and $(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf)), $(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf)))))