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:
92
README.md
92
README.md
@@ -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
|
||||
|
||||
2
emu/dc.c
2
emu/dc.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
69
emu/dt.c
69
emu/dt.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
408
emu/mem_0
@@ -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
|
||||
|
||||
@@ -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
427
tools/dtr2dta.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user