1
0
mirror of https://github.com/aap/pdp6.git synced 2026-02-27 09:19:45 +00:00

cleaned up the repo a bit

This commit is contained in:
aap
2019-03-08 20:56:20 +01:00
parent 93420ff2a9
commit ac77ceefea
10 changed files with 943 additions and 66 deletions

View File

@@ -21,13 +21,12 @@ The maintenance manual has flow charts, schematics and explanations:
The code is more or less a transcription of the schematics into C.
This means you will not understand it unless you're familiar with the maintenance manual.
Pulses are represented as functions, when a pulse triggers another pulse
it does so by the `nextpulse` function which adds a pulse to the list of next pulses.
In the main cpu loop the list of current pulses is iterated and each pulse is called,
then (after checking some external signals) the current and next pulse lists are swapped
and the process begins anew.
The timing was not accurately modeled and there is room for improvement.
Due to the inexact timing the hardware connections (through the memory and IO bus)
were not implemented too accurately. This may change in the future.
it does so by the `pulse` function which queues a pulse in a list
of pulses that are to happen, sorted chronologically.
Between pulses that happen at different times
various things are done like checking external pulses and advancing the
simulation state.
The timing is not yet 100% accurate but it's pretty close.
### Building
@@ -36,8 +35,8 @@ Otherwise you need SDL and pthread.
### Running
The cpu (apr), console tty and paper tape/punch are implemented.
There are no other external devices yet.
The cpu (apr), console tty, paper tape and punch,
the data control and DECtape are implemented.
The only things missing from the cpu is the repeat key mechanism.
## Verilog Simulation
@@ -59,17 +58,72 @@ The TTY is connected to UART over GPIO pins 4 (RX) and 5 (TX)
## File tree
* `emu` source for the emulator
* `verilog` source for the verilog simulation
* `art` everything graphical
* `code` some test code for the PDP-6
* `panel6` virtual panel for the FPGA
* `tools` tools like an assembler and linker
* `misc` some misc. and old stuff
* emu the C emulator
* emu/main_panel.c main file for emulator with panel simulation
* emu/main_serial.c main file for emulator with panel over serial line
* emu/emu.c top level emulator code
* emu/cmd.c command line interface
* emu/apr.c Arithmetic Processor 166 emulation
* emu/mem.c core and fast memory emulation
* emu/tty.c Teleprinter 626 emulator
* emu/pt.c Paper tape reader 760 and punch 761 emulation
* emu/dc.c Data Control 136 emulation
* emu/dt.c DECtape 551 and 555 emulation
* emu/netmem.c network protocol for shared memory
* emu/util.c various utility functions
* emu/util.h
* emu/test_*.c test code, not too important anymore
* emu/pdp6.h main header
* emu/args.h argument parsing
* emu/elements.inc panel definition
* emu/cmds.txt command line interface documentation
* emu/init.ini emulator init file
* emu/mem_* core memory backing store
* tools
* tools/dtr2dta.c convert between raw (dtr) and simh (dta) DECtape format
* tools/mkpty.c make a pty and connect to the controlling tty
* tools/mkpty33.c as above but try to pretend an ASR33
* tools/as6.c an assembler, roughly modeled on MACRO
* tools/ld6.c a loader or relocatable files
* tools/pdp6bin.h
* tools/pdp6common.c useful functions for PDP-6 code
* tools/pdp6common.h
* tools/rel.c I have no recollection of this code
* tools/reltest.c old test code to create a REL file
* tools/test.s old test code for the assembler/linker
* tools/test2.s
* tools/ptdump.c print a paper tape file in octal
* tools/dtdump.c print dtr DECtape
* verilog
* verilog/apr.v Arithmetic Processor 166 simulation
* verilog/core161c.v Core memory 161C simulation
* verilog/fast162.v Fast memory 162 simulation
* verilog/modules.v utility modules
* verilog/pdp6.v top level module
* verilog/quartus various files for my terasic board
* verilog/test_dec.v inst decoding test
* verilog/test.v misc tests
* verilog/test1.inc
* verilog/test2.inc
* verilog/test_fp.inc
* code random code for the PDP-6, mostly testing
* code/bootstrap.txt a list of boot loaders
* code/dtboot.s loads the first block from a DECtape
* code/main.s random entry
* code/tty.s tty character IO
* panel stand alone panel with lots of duplicate code
* art image files for the panel
* misc nothing important
## To do
- repeat and maint. switches
- test thoroughly!
- devices (test UT, implement 340)
- timing
- improve timing
- implement 340 display
- do more tests

View File

@@ -199,6 +199,7 @@ wake_dc(void *dev)
}
if(IOB_DATAI){
bus->c12 |= dc->db;
//printf("Sending DB to APR: %012lo\n", dc->db);
dc->db_rq = 0;
set_dbda_move(dc);
}
@@ -218,6 +219,7 @@ wake_dc(void *dev)
DB_CLR;
if(IOB_DATAO_SET){
dc->db |= bus->c12;
//printf("Got DB from APR: %012lo\n", dc->db);
set_dbda_move(dc);
}

View File

@@ -116,6 +116,8 @@ makedx(int argc, char *argv[])
/* Control */
int dtdbg;
enum
{
TapeEndF = 022,
@@ -196,7 +198,18 @@ enum
// TODO: not sure if BM SYNC || DATA SYNC is correct
#define UTE_ACTIVE_ERROR (!UT_ALL && prev.rw_state == RW_ACTIVE && (BM_SYNC || DATA_SYNC))
//#define debug(...) printf(__VA_ARGS__)
static void
dbg(char *fmt, ...)
{
if(dtdbg){
va_list ap;
va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
}
}
//#define debug(...) dbg(__VA_ARGS__)
#define debug(...)
#define PRINT1 \
@@ -262,6 +275,13 @@ char state = 'n';
#define REV (dt->ut_rev && !UT_BM)
/* This is a function for debugging purposes */
static void
setstat(Dt551 *dt, int state)
{
dt->rw_state = state;
}
static void
dt_tp0(Dt551 *dt)
{
@@ -327,7 +347,7 @@ dt_tp2(Dt551 *dt)
dt->ut_go = 0;
dt->ut_tape_end_flag = 1;
/* TODO: is this right? */
dt->rw_state = RW_NULL;
setstat(dt, RW_NULL);
}
/* Block mark timing.
@@ -354,7 +374,7 @@ dt_tp2(Dt551 *dt)
/* Send 6 bit byte to DC every two steps when reading */
if(UT_READ && RW_EVEN)
if(UT_READ && RW_EVEN){
/* except checksums */
if((prev.tdata & 0102) == 0){
int rwb = dt->rwb;
@@ -364,6 +384,7 @@ dt_tp2(Dt551 *dt)
if(UTE_DC_DISCONNECT)
dt->ut_incomp_block = 1; // 3-17
}
}
/* Clear LB before reading the reverse checksum */
if(tdedge & 0100)
@@ -392,12 +413,12 @@ dt_tp2(Dt551 *dt)
if(UT_BM && tbedge & 1 || // 3-6
UT_DATA && tdedge & 0100 || // 3-9
UT_ALL && tbedge & 010) // 3-11
dt->rw_state = RW_ACTIVE;
setstat(dt, RW_ACTIVE);
/* What to do after block */
if(tdedge & 1){
if(RW_DATA_CONT) // 3-10
dt->rw_state = RW_RQ;
setstat(dt, RW_RQ);
if(RW_DATA_STOP) // 3-11
dt->ut_jb_done_flag = 1;
/* test checksum. NB: manual says should be 0
@@ -415,7 +436,7 @@ debug("CHECKSUM ERR\n");
/* Catch wrongly set active state; 3-16 */
if(UTE_ACTIVE_ERROR){
dt->ut_info_error = 1;
dt->rw_state = RW_NULL;
setstat(dt, RW_NULL);
}
/* Catch invalid mark code */
if(UTE_ERROR){
@@ -425,7 +446,7 @@ debug("TRACK ERROR\n");
/* Stop activity once job gets done */
if(!prev.ut_jb_done_flag && dt->ut_jb_done_flag) // 3-8
dt->rw_state = RW_NULL;
setstat(dt, RW_NULL);
}
static void
@@ -519,9 +540,9 @@ debug("ILL op %d %d %d\n", nunits, dt->ut_btm_switch, UT_WRTM);
}
if(UT_WRTM) // 3-14
dt->rw_state = RW_ACTIVE;
setstat(dt, RW_ACTIVE);
else if(!UT_DN) // TODO: is this right?
dt->rw_state = RW_RQ;
setstat(dt, RW_RQ);
}else
/* Don't move during delay.
* TODO: is this right? */
@@ -620,7 +641,7 @@ wake_dt(void *dev)
}
if(bus->devcode == UTC){
if(IOB_STATUS){
printf("UTC STATUS\n");
dbg("UTC STATUS\n");
if(dt->ut_units_select) bus->c12 |= F19;
if(dt->ut_tape_end_enable) bus->c12 |= F20;
if(dt->ut_jb_done_enable) bus->c12 |= F21;
@@ -633,7 +654,7 @@ printf("UTC STATUS\n");
bus->c12 |= dt->ut_pia & 07;
}
if(IOB_CONO_CLEAR){
//printf("UTC CONO CLEAR\n");
dbg("UTC CONO CLEAR\n");
dt->ut_incomp_block = 0;
dt->ut_wren = 0;
dt->time_flag = 0;
@@ -643,10 +664,9 @@ printf("UTC STATUS\n");
dt->ut_jb_done_flag = 0;
// 3-5
dt->rw_state = RW_NULL;
setstat(dt, RW_NULL);
}
if(IOB_CONO_SET){
//printf("UTC CONO SET\n");
dt->ut_pia = bus->c12 & 07;
dt->ut_units = bus->c12>>3 & 07;
dt->ut_fcn = bus->c12>>6 & 07;
@@ -661,11 +681,30 @@ printf("UTC STATUS\n");
// UT CONO SET LONG, 1ms after UT CONO SET
// triggers UT START level until end of delay
dbg("UTC CONO SET %06lo\n", bus->c12 & 0777777);
dbg("SEL/%o GO/%o REV/%o TIME/%o FCN/%o\n", dt->ut_units_select,
dt->ut_go, dt->ut_rev,
dt->ut_time, dt->ut_fcn);
/* update selection, also done after delay */
selectdx(dt);
dt->delay = 0;
if(dt->ut_time){
/* TODO: unsure what to do here.
* The state cleared here usually
* becomes invalid in cases where
* a delay is needed.
* Ideally we simulate those circumstances
* better, but for now clear it here. */
dt->tmk = 0;
dt->rwb = 0;
dt->tbm = 0;
dt->tdata = 0;
dt->utek = 0;
dt->uteck = 0;
switch(dt->ut_time){
case 1: // 20ms
dt->delay = 600;
@@ -683,10 +722,11 @@ printf("UTC STATUS\n");
dt->time_flag = 0;
// now wait
dbg("starting delay %d\n", dt->delay);
}else
if(!UT_DN && // TODO: is this right?
!UT_WRTM) // 3-14
dt->rw_state = RW_RQ;
setstat(dt, RW_RQ);
}
}
recalc_dt_req(dt);
@@ -717,6 +757,7 @@ dtdep(Device *dev, const char *reg, word data)
dt = (Dt551*)dev;
if(strcmp(reg, "btm_wr") == 0) dt->ut_btm_switch = data&1;
else if(strcmp(reg, "dbg") == 0) dtdbg = data&1;
else return 1;
return 0;
}

View File

@@ -34,7 +34,8 @@ attach ptr ../code/test.rim
#attach ptr ../lars_sysgen/sysgen.pt
attach ptp ../code/ptp.out
#attach dx0 ../test/out.dt6
attach dx0 ../test/test.dt6
#attach dx0 ../test/test.dt6
attach dx0 ../test/ddt.dtr
#load -b ../maint/pdp6.part1

408
emu/mem_0
View File

@@ -9,9 +9,10 @@
720040000013
345540000006
602540777777
000000000013
700600014300
254000000006
000020:
000017:
254000037726
710600000060
710740000010
254000000021
@@ -20,7 +21,67 @@
254000000024
000027:
254000000021
032760:
032664:
052260547440
400000000000
052260547463
401000000000
052260547467
402000000000
052260547454
403000000000
052320235340
700300000000
052320234450
700340000000
052717441670
700040000000
052717442250
700140000000
051453454300
700000000000
051453477100
700100000000
052320173300
700240000000
052320216100
700200000000
064145630000
000400000000
064327442000
010000000000
064330034000
010400000000
067364207000
012000000000
061226766000
012400000000
053035301000
013000000000
052733550000
020000000000
070165411000
021000000000
070171331000
021400000000
052733745000
061000000000
052734142000
061400000000
053137621000
060400000000
075334270000
000000036636
075265230000
000000036633
012754626000
032752:
052754626000
000000034000
075010344000
000000036637
075022154000
000000036642
075033764000
000000036645
075045574000
@@ -252,7 +313,7 @@
260040033331
201240000040
254000033430
340000033526
740000033526
200240033333
135240037114
261040033333
@@ -449,11 +510,17 @@
315104033625
000004033634
033640:
254000034135
340000036170
340000033435
340000033435
034000:
740000034043
033642:
740000033435
740000033435
740000033435
740000033435
740000033435
740000033435
033776:
777666032664
000000033776
402000036723
402000036600
356000036630
@@ -679,7 +746,8 @@
201245000133
260040033430
254000034222
000010036572
000310036572
440700034343
034346:
441100034352
331100034352
@@ -1804,26 +1872,24 @@
660240000200
254000036471
777666032664
000000000020
036525:
000000000020
000000000020
000000000024
036534:
777777777777
036545:
002235510000
000000032664
000000032664
036550:
000000000020
000000000020
000000000001
000000037423
000000037423
000000000002
036554:
000000000112
036573:
710600000060
004400036014
036577:
000000036545
000000000105
036572:
000000000326
326100037430
036411000000
036576:
777666032664
600000032732
036601:
254000033430
200261777777
@@ -1834,14 +1900,31 @@
254000033430
205240604040
000000036627
036631:
036630:
000000000001
000000037777
036633:
340000000000
740000000200
000000001177
000000000010
000215000010
777777777777
036713:
036673:
777777777777
036675:
777666032664
777777000010
254000037066
000000000010
740000037604
254000037066
000000000001
400000000031
777777777777
200500037260
036710:
740000037463
000000000002
000000000400
000000036060
000000036134
000000000010
@@ -1849,9 +1932,9 @@
000000036134
000000000010
777777777777
000000000020
000000000001
036726:
340000034010
740000034010
336000036721
254000036733
350000036726
@@ -2011,3 +2094,266 @@
300600036626
360610036603
000040000040
037177:
400000000000
444464000000
444464000000
302000000000
037255:
757367573675
020410204102
020410204102
020410204102
020410204102
041020410204
041020410204
041020410204
041020573674
661020410204
041020410204
041020410204
041020410204
041020410204
041020000000
037376:
777777777777
000000000010
402000037777
700200635550
265300037471
201200037746
403100037176
250104000001
253100037406
201202777777
326200037404
403600000000
211500000001
205040400000
250140000001
205040400000
205240020600
306600000046
254000037735
721200000000
134100037777
326100037430
712340000040
254000037424
712040000002
265300037473
465100000177
342100037400
340100000007
345100037516
271100000135
321100037521
322100037414
603240770000
136100000005
254000037422
303600000055
267600037462
721200000000
321600037451
542200037447
322600037066
254000037402
563000033777
254000034000
201200037176
402000000040
200140037750
306600000064
200220033777
606600000003
251144777777
265640037601
265300037624
316340000004
254000037462
322140037402
322500037751
334300037663
334100037527
334100037432
336000037777
712140000002
712300000020
254000037475
325106000000
201100000012
254000037473
616105000001
344240037502
265300037471
306005740524
254000037402
201705740604
242700777777
135100037752
200056037254
137040037753
265300037745
267100037742
607040004040
135600000005
326600037706
342100037437
200540037754
205400777750
340400037574
336010037176
332010037177
604000000015
542400037536
316150037176
312050037177
253400037524
321400037541
323500037470
201400000055
332010037177
254000037470
336000000012
403040000003
202150037176
202050037177
201410000001
242400777777
323500037552
412510037254
436510037303
403440000005
602500000004
254000037453
200100037755
201340037747
336002000000
253100037557
202100000004
336002000000
332002000001
253100037562
274200000002
271202000000
202207000000
200340000002
321100037557
200340037756
201200037747
265300037624
255000000007
200204000000
325200037621
334640037524
316200037756
661440400000
265300037624
200340000004
325440037601
325200037442
325600037614
564300000004
270300000004
273320033777
540200000006
241340000001
265300037624
270344000000
253200037614
254015000000
321500037402
265300037624
624500037447
367240037647
354000000011
137040000013
134100000013
306100000037
254000037466
661112777777
302402000000
326100037625
137400000013
322500037626
200140037377
721700000040
254000037640
721340200000
660140002000
477000000002
721203220200
720200004010
721700000006
254000037470
720340001000
254000037647
325112037703
560140037377
720040000001
275051000000
325000037663
322040037667
321040037644
664140002000
340040037400
341040037643
660140010000
344000037645
331000000012
660140000400
721203220300
331000000012
720200003410
201240000200
344100037647
720040000016
312726000000
254000037470
254000037705
720066000000
254000037705
720166000000
254006000000
201100000044
265300037473
302600000053
306600000044
343500037711
306600000047
254020037447
306600000051
211500000005
303600000031
254000037413
242040000003
246000000003
326040037721
303000000007
267200037442
242000000003
202000037377
201440000100
265300037637
340102037177
367240037647
254000037402
541240037176
205100770000
616240037414
254000037502
607240770000
265300037745
201300037736
134100000005
201102000040
254000037473
037750:
000040000041
344500037730
000116037303
010100000002
000500037254
740623000020
254000000001

View File

@@ -1,4 +1,4 @@
all: as6 ld6 ptdump
all: as6 ld6 ptdump dtr2dta dta2dtr
as6: as6.c pdp6common.c
cc -g as6.c pdp6common.c -o as6
@@ -6,3 +6,9 @@ ld6: ld6.c pdp6common.c
cc -g ld6.c pdp6common.c -o ld6
ptdump: ptdump.c pdp6common.c
cc -g ptdump.c pdp6common.c -o ptdump
dtr2dta: dtr2dta.c
cc -o $@ $<
dta2dtr: dtr2dta.c
cc -o $@ $<

427
tools/dtr2dta.c Normal file
View File

@@ -0,0 +1,427 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define nil NULL
typedef unsigned char uchar;
typedef unsigned int uint;
typedef uint64_t word;
enum
{
TapeEndF = 022,
TapeEndR = 055,
BlockSpace = 025,
BlockEndF = 026,
BlockEndR = 045,
DataSync = 032, /* rev guard */
BlockSync = 051, /* guard */
DataEndF = 073, /* pre-final, final, ck, rev lock */
DataEndR = 010, /* lock, rev ck, rev final, rev pre-final */
Data = 070,
NUMBLOCKS = 01102,
// DTSIZE = 922512
// 01102 blocks, 2700 word for start/end each + safe zone
DTSIZE = 987288 + 1000
};
FILE*
mustopen(const char *name, const char *mode)
{
FILE *f;
if(f = fopen(name, mode), f == nil){
fprintf(stderr, "couldn't open file: %s\n", name);
exit(1);
}
return f;
}
/* Read raw tape data (forward) */
void
readf(uchar **dtp, uchar *mark, word *wrd)
{
int i;
uchar l;
uchar m;
word w;
m = 0;
w = 0;
for(i = 0; i < 6; i++){
l = *(*dtp)++;
m = (m << 1) | !!(l&010);
w = (w << 3) | l&7;
}
*mark = m;
*wrd = w;
}
/* Write raw tape data (forwad */
void
writef(uchar **p, int mark, int *ck, int data)
{
int i;
uchar d;
if(ck){
*ck ^= ~data & 077;
*ck ^= ~data>>6 & 077;
*ck ^= ~data>>12 & 077;
}
for(i = 0; i < 6; i++){
if(mark)
d = !!(mark & 040) << 3;
else
d = !!(**p & 010) << 3;
if(data & 01000000)
d |= **p & 07;
else{
d |= (data & 0700000) >> 15;
data = (data << 3) & 0777777;
}
mark <<= 1;
**p = d;
(*p)++;
}
}
#define LDB(p, s, w) ((w)>>(p) & (1<<(s))-1)
#define XLDB(ppss, w) LDB((ppss)>>6 & 077, (ppss)&077, w)
#define MASK(p, s) ((1<<(s))-1 << (p))
#define DPB(b, p, s, w) ((w)&~MASK(p,s) | (b)<<(p) & MASK(p,s))
#define XDPB(b, ppss, w) DPB(b, (ppss)>>6 & 077, (ppss)&077, w)
void
writesimh(FILE *f, word w)
{
uchar c[8];
uint l, r;
r = LDB(0, 18, w);
l = LDB(18, 18, w);
c[0] = LDB(0, 8, l);
c[1] = LDB(8, 8, l);
c[2] = LDB(16, 8, l);
c[3] = LDB(24, 8, l);
c[4] = LDB(0, 8, r);
c[5] = LDB(8, 8, r);
c[6] = LDB(16, 8, r);
c[7] = LDB(24, 8, r);
fwrite(c, 1, 8, f);
}
word
readsimh(FILE *f)
{
uchar c[8];
word w[2];
if(fread(c, 1, 8, f) != 8)
return ~0;
w[0] = c[3]<<24 | c[2]<<16 | c[1]<<8 | c[0];
w[1] = c[7]<<24 | c[6]<<16 | c[5]<<8 | c[4];
return (w[0]<<18 | w[1]) & 0777777777777;
}
char*
tostr(int m)
{
return m == TapeEndF ? "End Zone Fwd" :
m == TapeEndR ? "End Zone Rev" :
m == BlockSpace ? "Block Space" :
m == BlockEndF ? "Block End Fwd" :
m == BlockEndR ? "Block End Rev" :
m == DataSync ? "Data Sync" :
m == BlockSync ? "Block Sync" :
m == DataEndF ? "Data End Fwd" :
m == DataEndR ? "Data End Rev" :
m == Data ? "Data" :
"Unknown";
}
void
rawdump(uchar *dtp)
{
uchar mark;
word w;
uchar *end;
end = dtp + DTSIZE;
while(dtp < end){
readf(&dtp, &mark, &w);
printf("%02o[%-13s] %06o\n", mark, tostr(mark), w);
}
}
#define CHKWORD(exp) \
readf(&dtp, &mark, &w); \
if(mark != exp){ \
fprintf(stderr, "expected %s(%02o) got %s(%02o)\n", \
tostr(exp), exp, tostr(mark), mark); \
return 0; \
} \
int
validate(uchar *dtp)
{
uchar mark;
word w;
int i, j;
CHKWORD(TapeEndR);
CHKWORD(TapeEndR);
for(i = 0; i < NUMBLOCKS; i++){
CHKWORD(BlockSpace);
CHKWORD(BlockEndF);
CHKWORD(DataSync);
CHKWORD(DataEndR);
CHKWORD(DataEndR);
CHKWORD(DataEndR);
CHKWORD(DataEndR);
for(j = 1; j < 127; j++){
CHKWORD(Data);
CHKWORD(Data);
}
CHKWORD(DataEndF);
CHKWORD(DataEndF);
CHKWORD(DataEndF);
CHKWORD(DataEndF);
CHKWORD(BlockSync);
CHKWORD(BlockEndR);
CHKWORD(BlockSpace);
}
CHKWORD(TapeEndF);
CHKWORD(TapeEndF);
return 1;
}
void
dumpdta(uchar *dtp, FILE *f)
{
uchar mark;
word w, w2;
int i, j;
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w);
for(i = 0; i < NUMBLOCKS; i++){
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w2);
w = w << 18 | w2;
// data unused
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w2);
w = w << 18 | w2;
readf(&dtp, &mark, &w);
for(j = 0; j < 128; j++){
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w2);
writesimh(f, w<<18 | w2);
}
readf(&dtp, &mark, &w);
// data unused
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w2);
w = w << 18 | w2;
// reverse block mark
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w2);
w = w << 18 | w2;
}
readf(&dtp, &mark, &w);
readf(&dtp, &mark, &w);
}
void
wrf(FILE *f, int mark, int *ck, int data)
{
uchar buf[6], *p;
p = buf;
writef(&p, mark, ck, data);
fwrite(buf, 1, 6, f);
};
void
dumpdtr(word *wp, word *bmp, word *ibp, FILE *f)
{
word w;
int i, j;
int ck;
wrf(f, TapeEndR, nil, 0);
wrf(f, TapeEndR, nil, 0);
for(i = 0; i < NUMBLOCKS; i++){
w = *bmp++;
wrf(f, BlockSpace, nil, LDB(18, 18, w)); // block mark
wrf(f, BlockEndF, nil, LDB(0, 18, w)); // block mark
w = *ibp++;
wrf(f, DataSync, nil, LDB(18, 18, w));
wrf(f, DataEndR, nil, LDB(0, 18, w));
ck = 0;
wrf(f, DataEndR, &ck, 0007777); // rev check
/* the data */
w = *wp++;
wrf(f, DataEndR, &ck, LDB(18, 18, w));
wrf(f, DataEndR, &ck, LDB(0, 18, w));
for(j = 1; j < 127; j++){
w = *wp++;
wrf(f, Data, &ck, LDB(18, 18, w));
wrf(f, Data, &ck, LDB(0, 18, w));
}
w = *wp++;
wrf(f, DataEndF, &ck, LDB(18, 18, w));
wrf(f, DataEndF, &ck, LDB(0, 18, w));
wrf(f, DataEndF, nil, (ck & 077) << 12 | 07777); // check
w = *ibp++;
wrf(f, DataEndF, nil, LDB(18, 18, w));
wrf(f, BlockSync, nil, LDB(0, 18, w));
w = *bmp++;
wrf(f, BlockEndR, nil, LDB(18, 18, w)); // rev block mark
wrf(f, BlockSpace, nil, LDB(0, 18, w)); // rev block mark
}
wrf(f, TapeEndF, nil, 0);
wrf(f, TapeEndF, nil, 0);
}
uchar*
findstart(uchar *buf)
{
uchar *t;
int i;
word w;
uchar m;
for(i = 0; i < 1000; i++){
t = buf;
readf(&t, &m, &w);
if(m == TapeEndR)
goto found;
buf++;
}
return nil;
found:
while(readf(&buf, &m, &w), m == TapeEndR);
return buf-18;
}
uchar dtbuf[DTSIZE], *dtp;
word blockbuf[NUMBLOCKS*0200];
word bmbuf[NUMBLOCKS*2];
word ibbuf[NUMBLOCKS*2];
/* Fill block mark and interblock word buffers */
void
makefmt(void)
{
int i, j;
word co;
for(i = 0; i < NUMBLOCKS; i++){
/* forward and reverse block number */
bmbuf[i*2] = i;
// last one is 700707070707 really because it can't be written easily
co = 0;
for(j = 0; j < 12; j++)
co |= ((bmbuf[i*2]>>j*3) & 07) << (11-j)*3;
co ^= 0777777777777;
bmbuf[i*2+1] = co;
/* interblock words - used to find block 75 which contains the loader */
/* forward word */
if(i < 075)
ibbuf[i*2] = 0721200220107; // move forward
else if(i == 075)
ibbuf[i*2] = 0577777777777; // nop
else
ibbuf[i*2] = 0721200233107; // move backward
/* reverse word */
// last one is 777077707007 really because it can't be written easily
if(i < 073)
ibbuf[i*2+1] = 0721200223107; // move forward
else
ibbuf[i*2+1] = 0721200230107; // move backward
}
/* Last block isn't written quite correctly. To simulate: */
// ibbuf[01101*2 + 0] = 0077070007000;
// ibbuf[01101*2 + 1] = 0777077707007;
// bmbuf[01101*2 + 1] = 0700707070707;
}
int
readdtr(FILE *f)
{
fread(dtbuf, 1, DTSIZE, f);
fclose(f);
dtp = findstart(dtbuf);
if(dtp == nil){
fprintf(stderr, "no start\n");
return 1;
}
if(!validate(dtp)){
fprintf(stderr, "invalid file format\n");
return 1;
}
return 0;
}
int
readdta(FILE *f)
{
word w;
int n;
n = 0;
while(w = readsimh(f), w != ~0 && n < NUMBLOCKS*0200)
blockbuf[n++] = w;
return n != NUMBLOCKS*0200;
}
int
dtr2dta(void)
{
if(readdtr(stdin))
return 1;
dumpdta(dtp, stdout);
return 0;
}
int
dta2dtr(void)
{
if(readdta(stdin))
return 1;
makefmt();
dumpdtr(blockbuf, bmbuf, ibbuf, stdout);
return 0;
}
int
main(int argc, char *argv[])
{
if(strstr(argv[0], "dtr2dta")) return dtr2dta();
else if(strstr(argv[0], "dta2dtr")) return dta2dtr();
else fprintf(stderr, "Unknown %s\n", argv[0]);
return 0;
}