{**********************************************************************} {* APMTEL Database builder *} {* Andrew Ness 1988 CS4 project *} {* Modded version - see mod list below *} {* *} {* Version 1.3 7 Nov 1988 *} {**********************************************************************} %include "APMTEL:ins_pg3.inc" %include "inc:fs.imp" %include "inc:fsutil.imp" %include "inc:util.imp" %conststring (255) database file = "db.dat" %begin %constinteger server station = 16_35, { Filestore D station number magic number = 16, { The magic number of the APMTEL server my port= 21, { The local port used buf size = 520, { Maximum size of the ether packet true = 1, false = 0 %integer server port, n, c, graphics flag, %byte comm %integer page0, %integer pagestore, {100 * bytearray page(0:23,0:39) } %integer i, j, command, param, channel %string (255) filename %predicate pending read(%integer port) %integer bit bit=1< timeout*1000 %or bytes#0 %return bytes %end %integerfn server handshake(%string (255) command, %integer timeout, %bytearrayname response(0:*), %integername len) %integer t ether write(my port,charno(command,1),length(command)) t = cputime %cycle %if pending read(my port) %then %c len = ether read(my port,response(0),BUF SIZE) %and %result=0 %result=-1 %if cputime-t > timeout*1000 !! %result=1 %if testsymbol=' ' %repeat %end %predicate start talking %integer rc %string (255) command %bytearray buffer(0:1023) ether close(my port) {Make sure local port is closed ether open(my port, server station<<8) {Open connection to the SERVER command = tostring(magic number) rc=server handshake(command, 5, buffer, n); !"Hello server" ! !If the number of bytes rxd is 0, then the filestore is not up or is busy.... !so tell the user to try again later ! %if rc#0 %start printline("Server not responding - cache only") printline("Retry by attempting to force a download (menu option 2)") ! ether close(my port) %false %finish ! !Now, if the remote port number is less than 1, then the server is not running !on the filestore ! server port = buffer(0) - '0' %if server port <1 %start printline("Server not running - cache only") printline("Retry by attempting to force a download (menu option 2)") ! ether close(my port) %false %finish printline("Hi - APMTEL SERVER Connected") ether close(my port) ether open(my port, server station << 8 ! server port) rc=server handshake("A".current user, 5, buffer, n) %true %end !----- USER3 Emulation %routine flag comment(%string (255) s) printline(s) %end %routine show screen(%integer junk) %end !----- CUT HERE FROM USER3 ----- %bytefn to upper(%byte c) %if 'a' <= c <= 'z' %thenreturn c-'a'+'A' %elsereturn c %end !Routine to take teletext page/subpage from header and convert to integer. %integerfn txstoi(%integer packet) %constinteger hi=0, lo=1 %integerfn nib(%integer offset,hilo) %integer n n = byteinteger(packet+offset) %if hilo=hi %then n=n>>4 %result=n&15 %end %result = %c (((((nib(5,lo)*10+nib(0,hi))*10+nib(0,lo))*10+nib(1,hi))*10+%c nib(1,lo))*10+nib(2,hi))*10+nib(2,lo) %end %integerfn pg(%integer channel, %integer page) !Takes page specified as an integer channel plus !page number (we hope as a decimal number, 100<=n<=999) and turns it into !a 16-bit integer, top 4 bits channel, bottom 12 page number as BCD. %integer h,t,d h = page//100 page = page - h*100 t = page//10 d = page - t*10 channel = channel & 16_0F %result=((channel<<4+h)<<4+t)<<4+d %end %conststring (255) %array getfail(-1:4) = %c % {-1}"Server <-> Teletext receiver timeout", {0} "OK", {1} "Request cancelled", {2} "Server died while transmitting on ether", {3} "Server failed to transmit page to ether", {4} "Software error" %routine move(%integer bytes, %bytename from, to) !Move BYTES bytes from FROM to TO. Pinched from IE. !If addr(FROM) < addr(TO) do the move from the top down to allow overlap %return %if Bytes = 0 %or From == To %if Addr (To) < Addr (From) %start *Subq.l #1, d0 f loop: *move.b (a0)+, (a1)+ *dbra d0, f loop %else *add.l d0, a0 *add.l d0, a1 *subq.l #1, d0 b loop: *move.b -(a0), -(a1) *dbra d0, b loop %finish %end %ownstring(40) spaces40 = " " %integerfn get subpage from server(%integer param, to, %integername status) %string (255) command %bytearray buffer(0:1023), coda(0:511) %integer rc,rc2,n,i %routine unpack teletext(%bytearrayname buffer, to(0:1023)) %integer row, p, mag,i %bytearray check(0:31) !Note: Rows 26, 28 and 29 are not transmitted. There may be up to 4 !row 27s. I put the first row 27 in row 27 and any others in rows !26 then 28 and 29. !Unused rows have MAG and ROW set to 0. p=0 %for i=0,1,31 %cycle; check(i)=0; %repeat %for i=0,1,23 %cycle ;!Max. of 24 42-byte rows in 1024 chars mag=buffer(p); row=buffer(p+1) %if mag#0 %start %if row=27 %start !Clumsy !does it in received order without dehamming the subrow no. row=26 %if check(27)#0 row=28 %if check(26)#0 row=29 %if check(28)#0 %finish move(40, buffer(p+2), to(row*40)) check(row)=1 %finish p=p+42 %repeat !Fill in empty rows - assumed to contain spaces %for row=1,1,31 %cycle %if check(row)=0 %start move(40, charno(spaces40, 1), to(row*40)) %finish %repeat to(5) = buffer(0) ;!Save the magazine in an unused header byte status = buffer(5)<<8+(buffer(6)&255) %end command = "B".itos(param,-1) rc=server handshake(command, 200, buffer, n) %if rc=0 %start ;!Success %if n=512 %start !Expect the 2nd frame fragment n= get ether (my port,array(addr(buffer(512))), 6) %if n=512 %start !Then the status message n=get ether(my port,coda,512) !Now unpack the frame !!openoutput(1, "Page"); selectoutput(1); unpack teletext(buffer, array(to)) !!%for i=0,1,1023 %cycle; printsymbol(buffer(i)); %repeat !!%for i=0,1,1279 %cycle; printsymbol(byteinteger(to+i)); %repeat !!close output %else !Server died between sending blocks 1 and 2. %result=2 %finish %else %result=3 %finish %else %if rc>0 %start !! rc2=server handshake("E",5,array(to),n) !Note possibility for confusion if the cancel crosses the pages !coming back. Sort this later. %finish %finish %result=rc %end %integerfn mod10(%integer no); %result = no - (no//10)*10; %end %integerfn mod100(%integer no); %result = no - (no//100)*100; %end %constinteger %c erase page = 16_08, {byte 4} newsflash = 16_10, {byte 4} subtitle = 16_20, {byte 4} suppress header = 16_01, {byte 5} update indicator = 16_02, {byte 5} out of sequence = 16_04, {byte 5} inhibit display = 16_08, {byte 5} serial magazine = 16_10 {byte 5} %string (15) %fn statusbits(%integer status) !Returns the frame status bits as a string %byte c4,c5 %string (15) s c4 = status>>8; c5 = status & 16_FF s="" s=s."e" %if c4 & erase page # 0 s=s."n" %if c4 & newsflash # 0 s=s."s" %if c4 & subtitle # 0 s=s."h" %if c5 & suppress header # 0 s=s."u" %if c5 & update indicator # 0 s=s."o" %if c5 & out of sequence # 0 s=s."i" %if c5 & inhibit display # 0 s=s."m" %if c5 & serial magazine # 0 s=s."?" %if c4 & (\(erase page ! newsflash ! subtitle)) # 0 %or %c c5 & (\(suppress header ! update indicator ! out of sequence ! %c inhibit display ! serial magazine)) # 0 s="[".s."]" %unless s="" %result=s %end %integerfn get page from server(%integer page, base, %integername subpages) %integer rc, full pageno, f, firstf, maxsub, i, latestf, to, status firstf=-1; f=0; subpages=-1; maxsub=-1 !Once the subpages have wrapped round, we know we have a complete page !and how big it is. subpages=0 %cycle to = base + f * 1280 rc=get subpage from server(page, to, status) %result=rc %if rc#0 full pageno = txstoi(to) show screen(to) latestf=f; f = mod100(full pageno) ;!the subpage number %if firstf<0 %start;!start point in subpage cycle firstf=f !Page is in subpage-0 slot. Copy the page to the correct place move(1280,byteinteger(to), byteinteger(base+(f-1)*1280)) %if f>1 %finish %if f=0 %start; !Only subpage flag comment(" Page ".itos(full pageno,-1)." ".status bits(status)) subpages=1 %result=0 %elseif f=latestf ;!subpages are looping flag comment("Subpage ".itos(full pageno,-1)." looping") subpages=1 %result=0 %else flag comment("Subpage ".itos(full pageno,-1)." ".status bits(status)." arrived") %finish %if f entry(comm) entry('C'): !Change channel channel = param rc=server handshake(tostring(comm).itos(channel,-1), 60, buffer, n) %return entry('D'): !Quit rc=server handshake(tostring(comm), 1, buffer, n) ether close(my port) %return entry('E'): !Force a page request from server page id = pg(channel, param) rc=get page from server(param, pagestore, subpages) %if rc=0 %start write cached page(page id, pagestore, subpages) %else printline("page request failed ".itos(rc,-1)) %finish %return %end %externalroutinespec create db file(%string(255) name, %integer ind, blks) %integer mag, pag,m create db file("db.dat", 5, 40) %stop %unless start talking pagestore = heapget(100*1280); page0 = heapget(1280) open cache(database file) %for channel = 1,1,4 %cycle act on('C', channel) %for mag = 1, 1, 9 %cycle !Interleave page requests %for pag = 0,1,24 %cycle -> end %if testsymbol='#' m = mag*100+pag act on('E', m) act on('E', m+25) act on('E', m+50) act on('E', m+75) %repeat %repeat %repeat end: close cache act on('D', 0) heapput(pagestore) %endofprogram