Days of Old: When Men were Men and Nerds Typed in BASIC programs - Page 1
Forum section: electronics / general

author: DrG
author_rank: Super Contributor
timestamp: March 27, 2021, 04:38:24 pm
content: Did some crate digging yesterday and found this.It is a collection of BASIC program listings that folks could type in to show off their home computer. Copyright 1978, but the individual programs are apparently from earlier issues of Creative Computing magazine. As I recall, I picked up two of these "collections" at a used bookstore, probably in the early 1980s.The collection is edited by David Ahl, the publisher of Creative Computing magazine [look him up]. Check out the biographical blurb.Now, I consider myself an 'old timer', but he is definitely my senior chronologically and experientially - in fact, of all those computers listed, I have only laid hands on two (PDP 8,11).Here were all the BASICs that the programs would run on - and what conversion issues you might encounter. It's interesting because it serves as a historical marker of what early home computers were out there at the time - qualified by the location of the intended audience....then, of course, were all the programs. You would type these in (line by line and tiny dot-matrix print) and you had, potentially, something amusing working on your computer! Some of the listings were quite extensive and I imagine were quite an effort (I would only type in a few short ones). Lunar Landing, BlackJack, Craps, and of course, SUPER STAR TREK!Good Times

author: MIS42N
author_rank: Frequent Contributor
timestamp: April 12, 2021, 08:02:39 am
content: Those days! I wrote a planet finder - put in date, time, latitude, longitude and it says where to look. In 4kbyteCode:'' Program to calculate position of planets' ========================================'' The position of the planets are calculated in 3 dimensions, initially' in a coordinate system using the orbit of the earth as the XY plane,' the sun as origin (0,0,0), the mean radius of the orbit of the earth as' 1 unit, the X+ axis passing through the earth's position at the vernal' equinox. Most planet data is made available in this reference system.'' These coordinates are then recalculated with the same origin and X axis' but with the XY plane parallel to the earth's equator. By knowing the' earth's position and the planet's position, the direction of the planet' is given in R.A. (right ascension) and declination.'' Given the latitude and longitude of the observer, it is possible to' recalculate to azimuth and altitude.'' ========================================'' Latitude and Longitude of observer expressed as radians' J = Longitude -- E of Greenwich is +' K = Latitude -- N of equator is +' N = Local time offset in hours [Local - GMT]'10 J = 2.641265: K = -.532325: N = 10!'' P = Pi; FNA - reduce radians to 0 -> 2Pi'20 P = 3.1415926#: DEF FNA (X) = X - INT(X / (P * 2)) * P * 2'' Get date, reduce to number of days in G [1/1/1900 = 1]'100 INPUT "Date D,M,Y"; B, C, D: IF C < 3 THEN C = C + 12: D = D - 1110 C = C + 1: G = B + INT(C * 153 / 5) + INT(D * 1461 / 4) - 63'' Get time, reduce to minutes since midnight in H'120 INPUT "TIME (24HR CLOCK) H,M"; B, C: H = B * 60 + C'130 INPUT "NO. OF PREDICTIONS"; S: IF S = 1 GOTO 150'' TI - Time Interval in minutes'140 INPUT "INTERVAL H,M"; B, C: TI = B * 60 + C'150 INPUT "PLANET NO."; V'' T = time in days and a fraction used to calculate positions etc. The base' date for calculation was midday 31/12/1899 GMT [hence the -.5]' When calculating using the earth's rotation, it is convenient to keep' time as whole days (G) and hours (H) also.' O = Angle between earth's axis and earth's orbit (changes with time)'160 FOR TC = 1 TO S: T = G + H / 1440 - .5 - N / 24: O = .40932 - T * 6.212E-09'' A$ - name of planet' A - mean distance from sun (earth = 1)' E - eccentricity, B - time correction for E' I - angle of planet orbit, C - time correction for I' U - angle from X axis to where orbital plane crosses, D - time correction' W - angle between U and perihelion, F - time correction' L - mean longitude of planet at reference [31/12/1899]' X - whole days + 1 to orbit the sun' Y - radians in excess of one orbit completed in X days' Z - angular velocity radians/day'170 RESTORE: FOR Q = 0 TO 8: READ A$, A, E, B, I, C, U, D, W, F, L, X, Y, Z180 IF Q = 0 THEN GOSUB 600: EX = X: EY = Y: EZ = Z: EL = L: ER = R: GOTO 470190 IF V > 0 AND V <> Q GOTO 470200 GOSUB 600210 C = G - 60: D = INT(C / 1461): C = C - D * 1461: B = INT(C / 365): IF B = 4 THEN B = 3220 C = C - B * 365 + 31: D = D * 4 + B: B = C * 5: C = INT(B / 153): B = INT((B - C * 153) / 5) + 1: C = C + 2230 IF C > 12! THEN C = C - 12: D = D + 1240 PRINT : PRINT : PRINT " DATE TIME": PRINT250 F = B: GOSUB 580: F = C: GOSUB 570: F = D: GOSUB 570260 PRINT " "; : F = INT(H / 60): GOSUB 580: PRINT ":"; : F = H - F * 60: GOSUB 580270 I = FNA((H / 60 - N) * P / 12 + EL - .000099): F = I: PRINT : PRINT280 PRINT "G.M.S.T. "; : GOSUB 530290 I = FNA(I + J): F = I: PRINT "LOCAL S.T. "; : GOSUB 530300 PRINT : PRINT "DATA FOR "; A$: PRINT310 B = X - EX: GOSUB 750: A = ATN((Y - EY) / B): IF B < 0 THEN A = A + P330 PRINT "R.A. "; : F = A: GOSUB 530340 W = (X - EX) ^ 2 + (Y - EY) ^ 2: B = SQR(W): GOSUB 750350 E = ATN((Z - EZ) / B): F = E: PRINT "DECLINATION "; : GOSUB 500360 C = W + (Z - EZ) ^ 2: B = (C + ER ^ 2 - R ^ 2) / (2 * ER * SQR(C)): GOSUB 750380 F = ATN(SQR(1 - B ^ 2) / B): IF B < 0 THEN F = F + P390 PRINT "ELONGATION "; : GOSUB 500400 U = FNA(A - I): F = U: PRINT : PRINT "HOUR ANGLE "; : GOSUB 530410 C = SIN(K) * SIN(E) + COS(K) * COS(E) * COS(U): B = SQR(1 - C ^ 2): GOSUB 750420 F = ATN(C / B): PRINT : PRINT "ALTITUDE "; : GOSUB 500430 B = COS(K) * SIN(E) - SIN(K) * COS(E) * COS(U): C = COS(E) * SIN(U)435 GOSUB 750: F = ATN(C / B): IF B < 0 THEN F = F + P440 F = FNA(F): PRINT "AZIMUTH "; : GOSUB 500450 PRINT : PRINT "PRESS ANY KEY FOR MORE"460 DOLOOP UNTIL LEN(INKEY$) > 0''470 NEXT Q: H = H + TI: B = INT(H / 1440): G = G + B: H = H - B * 1440: NEXT TC: END'500 B = F * 180 / P: F = SGN(B) * INT(ABS(B)): B$ = STR$(F): C = LEN(B$)510 FOR D = 1 TO C: C$ = MID$(B$, D, 1): IF C$ <> " " THEN PRINT C$;520 NEXT D: PRINT CHR$(248); : GOTO 550530 B = F * 12 / P: IF B < 0 THEN B = B + 24540 F = INT(B): GOSUB 580: PRINT "HR";550 B = ABS(B - F) * 60: F = INT(B): GOSUB 580: PRINT "'";560 F = INT((B - F) * 60 + .5): GOSUB 580: PRINT CHR$(34): RETURN570 PRINT "/";580 PRINT MID$(STR$(F + 100), 3, 2); : RETURN''' time adjust E, I, U, W'600 E = E + B * T: I = I + C * T: U = U + D * T: W = W + F * T' Calculate mean position of planet at time T, relative to its perihelion' To avoid rounding errors, we remove most or all the whole orbits of the' sun, by removing from the time component a multiple of the number of days' in which a whole orbit and a bit was completed (X), but generating an' an angle which is the residuals of the orbits (residual is Y). The mean' position at time T relative to perihelion is in M610 B = INT(T / X): C = T - B * X: L = B * Y + C * Z + L: M = FNA(L - U - W): X = M' successively approximate X the difference between M and the actual position620 Y = (M - X + E * SIN(X)) / (1 - E * COS(X)): X = X + Y: IF ABS(Y) > .0000005 GOTO 620'630 B = COS(X / 2): GOSUB 750: F = 2 * ATN((SQR((1 + E) / (1 - E)) * SIN(X / 2)) / B)650 R = A * (1 - E * COS(X)): Y = W + F660 B = R * (COS(U) * COS(Y) - SIN(U) * SIN(Y) * COS(I))670 C = R * (SIN(U) * COS(Y) + COS(U) * SIN(Y) * COS(I))680 D = R * SIN(Y) * SIN(I)690 X = B: Y = C * COS(O) - D * SIN(O): Z = C * SIN(O) + D * COS(O)700 RETURN750 IF B = 0 THEN B = 1E-10760 RETURN800 DATA EARTH,1,.016751,-.114E-8,0,0,0,0,1.766637,.8215E-6,1.740035,366,.0130363,.01720279810 DATA MERCURY,.3870986,.205614,.56E-9 ,.122223,.889E-9,.822915,.5663E-6,.501785,.177E-6,3.109812,88,.00225458,.07142545820 DATA VENUS,.7233316,.006821,-.131E-8,.05923,.481E-9,1.322602,.43E-6,.949185,.2428E-6,5.982413,225,.00851648,.02796311830 DATA MARS,1.523692,.093313,.282E-8,.032294,.323E-9,.851484,.3684E-6,4.981723,.5112E-6,5.126863,687,.6438E-3,.009146767840 DATA JUPITER,5.2028,.048332,.449E-8,.022842,-.272E-8,1.735536,.4823E-6,4.77105,.2171E-6,4.16936,4333,.5989E-3,.00145022850 DATA SATURN,9.538843,.05589,-.945E-8,.04350,-.186E-8,1.968489,.4152E-6,5.9044,.5254E-6,4.666956,10760,.5051E-3,.5839825E-3860 DATA URANUS,19.18195,.0471,0,.013483,.398E-9,1.282478,.2515E-6,1.668002,.5137E-6,4.26205,30686,.1616E-3,.2047626E-3870 DATA NEPTUNE,30.0578,.0085,0,.031052,-.451E-8,2.280806,.525E-6,4.767997,-.2006E-6,1.498626,1,.10439E-3,.1E-3880 DATA PLUTO,39.4387,.2494,0,.29915,0,1.902409,.7053E-6,2.009925,0,1.648242,1,.69454E-4,.7E-4

author: tggzzz
author_rank: Super Contributor
timestamp: April 12, 2021, 08:24:15 am
content: Learning to program in Algol on a Burroughs machinein 1956is quite an achievement.Algol was designed between 1958 and 1960.

author: rfclown
author_rank: Frequent Contributor
timestamp: April 12, 2021, 02:19:26 pm
content: I typed in some of those programs. I was (am still am) fascinated with the Amazing program that printed out a random maze. I never tried to figure out how it worked.

author: AndrewNorman
author_rank: Contributor
timestamp: April 12, 2021, 04:25:11 pm
content: Spent many hours typing programs into my BBC Model B and trying to figure out why it wasn't working.There were the standard programs that calculated biorhythms and the text-based pace invaders.Managed to get a big program to run an RPG game typed in by my friend's mother who was a typist from a pool who was used to typing stuff without understanding what she was typing.Now spend all my days writing code to pay for my evenings playing with electronics

author: Syntax Error
author_rank: Frequent Contributor
timestamp: April 12, 2021, 04:53:34 pm
content: It's no surprise that my user name is Syntax Error as that was the very first thing I managed to output on a home micro. Not hello world, just holding down the enter key and scrolling syntax error off the green screen monitor. How cool was that for a 'micro kid'?Anyway, after learning not to programme but to program, I had a go at writting a BASIC routine for the legendary skill test, The Towers Of Hanoi. I bet some of you guys tried it? Somewhere I might have my source code, all hand written, as a dot matrix printer was a few years away.My father who was an analog EE, remained to be convinced of the merits of computers.

author: themadhippy
author_rank: Super Contributor
timestamp: April 12, 2021, 05:25:57 pm
content: Typing in programs? scanning a listing as a text document,then changing the .txt extension to .bas was much easier.

author: DrG
author_rank: Super Contributor
timestamp: April 12, 2021, 05:30:00 pm
content: Quote from: tggzzz on April 12, 2021, 08:24:15 amWhat is your explanation - a lie, a damn lie, a typo or ? I don't know, but I can read historical articles also and what I see is that ALGOL was "released" in 58https://en.wikipedia.org/wiki/ALGOL_58. It certainly seems possible to me that something that became IAL/ALGOL was running on that machine in 1956. Maybe it is a mistake, I don't know.

author: DrG
author_rank: Super Contributor
timestamp: April 12, 2021, 05:49:59 pm
content: Quote from: rfclown on April 12, 2021, 02:19:26 pmYeah, a lot of us were fascinated by the "maze". In 1991 (I just looked at some file dates), I did learn how to draw mazes...and then I started playing around with how a "mouse" could solve the maze. Solutions (number of moves) were compared to a random move strategy. As I recall, I only worked on a couple of "models". Simple strategies like not repeating the last move...and proximity (if the goal was adjacent - go there because the "rodent" could smell the cheese when that close - even tried variants on 'olfactory' cues). I had generated demos so you could watch it in action.My recollection is that people liked it and liked it too much and it got more "attention" at work than I cared for and so I abruptly dumped it as being silly...and went back to real work. Here is the code for one of them - Turbo-C and an IBM PC as I recall, but no idea if it runs, was 'in progress' or whatever. Somewhere, I had results files for what I tried but I can't find them and I am tired of lookingCode:/*---RM3X3.CMaze solver - model 001randomversion 1.2notes: 1. cat3x3.dat is loaded from the default drive2. cr/lf is added after 40 elements are writtento the output file3. if global pad=0 then only 1 space is added toelements of the output file4. model number and sum moves are written for each run---*/#include <stdio.h>#include <conio.h>#include <dos.h>#include <stdlib.h>#include <time.h>#include "usrlib.h"#define YSIZE 3#define XSIZE 3#define TRUE 1#define FALSE 0/* PROTOTYPES */void gen_m_string(void);/*--copies the maze character array template into dup_string[][]and break the walls--*/void preamble(void);void my_exit(int);void make_move(void);void draw_move(int);void init_screen(void);void init_maze(void);void clr(void);void update_maze(void);void get_command(void);void switch_screen(void);int get_dt(void);void get_odt(void);void draw_screen0(char);void write_data(void);void d_win(char tr,char tc,char br,char bc,char style,char w_atrib,char shadow);unsigned char wait_key(char);/* DOS.H defined structures */struct date d;struct time t;/* GLOBALS *//* the maze data file record structure */typedef struct m3x3{unsigned int number;/* arbitrary or sorted 1-192*/unsigned char ysize;/* YSIZE*/unsigned char xsize;/* XSIZE*//* start and goal boxes are INSIDE the maze*/unsigned char starty;/* start coordinates*/unsigned char startx;/* " "*/unsigned char goaly;/* end coordinates*/unsigned char goalx;/* " "*/unsigned char moves2solve;/* number of moves*//* all coordinate arrays are y,x order*//* architecture */unsigned char structure;/* distance array coordinates */unsigned char distance;/* solution coordinates 0,0 is end */unsigned char map[YSIZE*XSIZE+2];/*--movement solution directions array is moves INCLUDING an out of bounds to the eastthe others are 0-N 1-E 2-S 3-W--*/unsigned char direction[YSIZE*XSIZE+2];unsigned int choices;/* total number of choices*/unsigned char spare;/* makes record size=64*/};struct m3x3 m3;/* maze strings */char mstring={{201,205,205,205,205,205,203,205,205,205,205,205,203,205,205,205,205,205,187,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,211,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32, 32,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,214,0},{204,205,205,205,205,205,206,205,205,205,205,205,206,205,205,205,205,205,185,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{204,205,205,205,205,205,206,205,205,205,205,205,206,205,205,205,205,205,185,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186, 32, 32, 32, 32, 32,186,0},{200,205,205,205,205,205,202,205,205,205,205,205,202,205,205,205,205,205,188,0}};char dup_string;int model=1;/* model # 1=random*/int moves;/* record of moves/maze*/int cmoves=0;/* moves for current maze*/int screen=2;/* 0 saver, 1=list 2=show*/unsigned int pass=1;/* number of sets solved*/unsigned int last_pass=1;int solved;/* delays during screen=2 in @ msec */int speed=2;int vdel={70,50,30,10},/* vertical char movement*/hdel={48,30,18,6},/* horizontal char movement*/im={250,200,150,100},/* inter-maze*/imdel={100,80,60,40};/* inter-move*/int sc0_pos=0;/* screen=0 position index *//* screen character attributes */char iw_green,iw_blue,iw_red,f_iw_blue,default_color,g_blue;char mchar=2;/* the maze character*/char mattrib; /* " attribute */char o_date[]="YYDDDHHMMSS ";/* ordinal date string*/char dt_string[]="00-00-0000 11:11 "; /* current date & time string*/char buffer;/* for general conversion*/int count=0;/* maze counter*/char id=FALSE;/* switch to write id data*/char pad=FALSE; /* switch to pad output data */FILE *fname;/* used for input and output*/int cx,cy,posy,posx; /* coord's for the mouse*/void main(){int x,y;unsigned int max_pass=1000;preamble();if( (fname=fopen("cat3x3.dat","rb") )==NULL)my_exit(1);/* read the maze data into the structure array */for(x=0;x<192;x++)(void)fread(&m3,sizeof(struct m3x3),1,fname);fclose(fname);/* open up the output file */get_odt();sprintf(&o_date,".%03d",model);if( (fname=fopen(o_date,"at") )==NULL)my_exit(8);/* copy the maze template once */for(y=0;y<13;y++)for(x=0;x<20;x++)dup_string=mstring;switch_screen();/* start out as though we switched */while(pass<=max_pass){count=0;for(x=0;x<192;x++)moves=0;/* loop through the entire data file*/while(count<192){init_maze();/* also init's screen*/while(!solved){get_command();make_move();if(cx==3){/* mouse is in the goal*/update_maze();count++;}}}/* write out the data */write_data();pass++;}my_exit(0);}void gen_m_string(){register x,y;for(x=1;x<19;x++){/* only copy the inner walls */dup_string=mstring;dup_string=mstring;}for(y=1;y<12;y++){dup_string=mstring;dup_string=mstring;}/* make the appropriate breaks */if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&2)){dup_string=32;dup_string=32;dup_string=32;}if((m3.structure&4))for(x=2;x<5;x++)dup_string=32;if((m3.structure&4))for(x=2;x<5;x++)dup_string=32;if((m3.structure&4))for(x=8;x<11;x++)dup_string=32;if((m3.structure&4))for(x=8;x<11;x++)dup_string=32;if((m3.structure&4))for(x=14;x<17;x++)dup_string=32;if((m3.structure&4))for(x=14;x<17;x++)dup_string=32;}void preamble(){/*--check out the user--*/if(_osmajor<3){/* from dos.h */puts("\nError: DOS 3.0 or later required\n");exit(1);}get_video();if((videomode!=7)&&(videomode!=2)&&(videomode!=3)){puts("\nError: video mode 2, 3, or 7 required\n");exit(1);}/* set character attributes */if(videomode==7){iw_green=112;iw_blue=7;iw_red=112;f_iw_blue=135;g_blue=7;default_color=7;}else{iw_green=47;iw_blue=31;iw_red=79;f_iw_blue=159;g_blue=18;default_color=31;}mattrib=g_blue;save_curs();curs_off();clr();d_win(28,8,54,15,1,iw_green,129);write_string(30,9,iw_red," MAZE SIMULATION ");write_str(30,11,"3 X 3 MAZE - MODEL 001");write_str(30,14, "[press a key to start]");(void)wait_key(0);write_string(30,14,f_iw_blue," loading maze data ");}void my_exit(int ern){char *emess[]={"OK","Can't open CAT3X3.DAT!","Bad direction choice","Bad direction drawn","Bad screen mode","Bad file read","????","Program aborted by user","Can't open output file","Can't write maze data to output file"};fclose(fname);restore_curs();clrscr();puts("\n");if(ern!=7 && ern!=0){write_str(1,1,"ERROR: ");write_str(7,1,emess);}elsewrite_str(1,1,emess);exit(ern);}void make_move(){/*--from the m3.structure and the globals cy and cxpicks a direction at random and updates cy,cx and cmovescalls draw_move if screen2--*//* the move array where [.]=structure element[.]=the number of possible moves[][0..3]=the directions 1/2/4/8 n/e/s/w */static int move_map={{0,0,0,0,0}, /*  - never */{1,0,0,0,1}, /*  */{2,0,0,0,1}, /*  */{1,2,0,0,2}, /*  */{4,0,0,0,1}, /*  */{1,4,0,0,2}, /*  */{2,4,0,0,2}, /*  */{1,2,4,0,3}, /*  */{8,0,0,0,1}, /*  */{1,8,0,0,2}, /*  */{2,8,0,0,2}, /*  */{1,2,8,0,3}, /*  */{4,8,0,0,2}, /*  */{1,4,8,0,3}, /*  */{2,4,8,0,3}, /*  */{1,2,4,8,4} /*  */};int cell,possible_moves,choice,move;/* choose direction of move *//* these assignments sacrifice speed for clarity */cell=m3.structure;possible_moves=move_map;if(possible_moves==1)move=move_map;else{choice=random(possible_moves);move=move_map;}/* update global positions */cmoves++;switch(move){case 1:cy--;break;case 2:cx++;break;case 4:cy++;break;case 8:cx--;break;default:my_exit(2);break;}if(screen==2)draw_move(move);}void draw_move(int direction){int x;switch(direction){case 1:for(x=0;x<4;x++){write_char(posx,posy,default_color,32,1);delay(vdel);write_char(posx,--posy,mattrib,mchar,1);delay(vdel);}break;case 4:for(x=0;x<4;x++){write_char(posx,posy,default_color,32,1);delay(vdel);write_char(posx,++posy,mattrib,mchar,1);delay(vdel);}break;case 2:for(x=0;x<6;x++){write_char(posx,posy,default_color,32,1);delay(hdel);write_char(++posx,posy,mattrib,mchar,1);delay(hdel);}break;case 8:for(x=0;x<6;x++){write_char(posx,posy,default_color,32,1);delay(hdel);write_char(--posx,posy,mattrib,mchar,1);delay(hdel);}break;default:my_exit(3);break;}sprintf(buffer,"%03d",cmoves);write_str(42,3,buffer);delay(imdel);}void init_screen(){static int pcy={2,6,10,11};/* character position offsets */static int pcx={3,10,16,20};static int startgx=30,startgy=6,line=10;char buffer;int x,y;div_t pp;switch(screen){case 0:draw_screen0(FALSE);break;case 1:if(last_pass!=pass){last_pass=pass;d_win(25,2,55,5,1,iw_green,0);sprintf(buffer,"3 X 3 MODEL %03d (RANDOM)",model);write_str(29,3,buffer);sprintf(buffer,"Pass=%05u",pass);write_str(36,4,buffer);d_win(1,9,80,22,2,iw_blue,0);y=line;for(x=0;x<12;x++){sprintf(buffer,"[%03d-%03d] %4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",x*16+1,x*16+16,moves[(x*16)],moves[(x*16)+1],moves[(x*16)+2],moves[(x*16)+3],moves[(x*16)+4],moves[(x*16)+5],moves[(x*16)+6],moves[(x*16)+7],moves[(x*16)+8],moves[(x*16)+9],moves[(x*16)+10],moves[(x*16)+11],moves[(x*16)+12],moves[(x*16)+13],moves[(x*16)+14],moves[(x*16)+15]);write_string(3,y++,default_color,buffer);}}else{/* just update the display */sprintf(buffer,"%4d",moves[m3.number-1]);pp=div(m3.number-1,16);write_str(13+(pp.rem*4),line+pp.quot,buffer);}break;case 2:/* draw the maze character display */write_block(10,2,60,21,default_color,32);gen_m_string();posx=pcx+startgx;posy=pcy+startgy;for(y=0;y<13;y++)write_str(startgx,startgy+y,dup_string);write_char(posx,posy,iw_green,mchar,1);d_win(24,1,54,4,1,iw_green,0);sprintf(buffer,"3 X 3 MODEL %03d (RANDOM)",model);write_str(28,2,buffer);sprintf(buffer,"Moves=%03d",cmoves);write_str(35,3,buffer);d_win(24,20,54,23,2,iw_red,0);sprintf(buffer,"MAZE # %03d",m3.number);write_str(34,21,buffer);sprintf(buffer,"Optimal Solution in %03d Moves",m3.moves2solve);write_str(25,22,buffer);break;default:my_exit(4);break;}}void switch_screen(){static int pcy={2,6,10,11};/* character position offsets */static int pcx={3,10,16,20};static int startgx=30,startgy=6,line=10;char buffer;int x,y;clr();switch(screen){case 0:draw_screen0(TRUE);break;case 1:d_win(25,2,55,5,1,iw_green,0);sprintf(buffer,"3 X 3 MODEL %03d (RANDOM)",model);write_str(29,3,buffer);sprintf(buffer,"Pass=%05u",pass);write_str(36,4,buffer);d_win(1,9,80,22,2,iw_blue,0);y=line;for(x=0;x<12;x++){sprintf(buffer,"[%03d-%03d] %4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",x*16+1,x*16+16,moves[(x*16)],moves[(x*16)+1],moves[(x*16)+2],moves[(x*16)+3],moves[(x*16)+4],moves[(x*16)+5],moves[(x*16)+6],moves[(x*16)+7],moves[(x*16)+8],moves[(x*16)+9],moves[(x*16)+10],moves[(x*16)+11],moves[(x*16)+12],moves[(x*16)+13],moves[(x*16)+14],moves[(x*16)+15]);write_string(3,y++,default_color,buffer);}break;case 2:/* draw the maze character display */write_block(10,2,60,21,default_color,32);gen_m_string();posx=pcx+startgx;posy=pcy+startgy;for(y=0;y<13;y++)write_str(startgx,startgy+y,dup_string);write_char(posx,posy,iw_green,mchar,1);d_win(24,1,54,4,1,iw_green,0);sprintf(buffer,"3 X 3 MODEL %03d (RANDOM)",model);write_str(28,2,buffer);sprintf(buffer,"Moves=%03d",cmoves);write_str(35,3,buffer);d_win(24,20,54,23,2,iw_red,0);sprintf(buffer,"MAZE # %03d",m3.number);write_str(34,21,buffer);sprintf(buffer,"Optimal Solution in %03d Moves",m3.moves2solve);write_str(25,22,buffer);break;default:my_exit(4);break;}}void clr(){write_block(1,1,80,25,default_color,32);}void init_maze(){/* initializes these variables for every maze */cx=m3.startx;cy=m3.starty;cmoves=0;solved=0;m3.structure|=2;init_screen();randomize(); /* <--- NOTE */}void update_maze(){/* it was solved */solved=1;moves[m3.number-1]=cmoves;switch(screen){case 0:break;case 1:init_screen();break;case 2:delay(im);break;default:break;}}void get_command(){signed char key;if((key=get_key())!=0)switch(key){case 'q':case 'Q':write_string(26,25,f_iw_blue,"Quit? [press 'Y'to confirm]");key=wait_key(0);write_string(26,25,default_color," ");if(key=='y'||key=='Y')my_exit(7);break;case '0':if(screen!=0){screen=0;switch_screen();}break;case '1':if(screen!=1){screen=1;switch_screen();}break;case '2':if(screen!=2){screen=2;switch_screen();}break;case 'p':case 'P':write_string(37,25,f_iw_blue,"PAUSE");(void)wait_key(0);write_string(37,25,default_color," ");break;case -72:if(speed<3)speed++;break;case -80:if(speed>0)speed--;break;default:break;}}int get_dt(){/*--update the current time and date string - if minutes have changedthen update dt_string and return 1 else 0--*/static last_min=61;int changed=0;getdate(&d);/* get system date & time*/gettime(&t);if(t.ti_min!=last_min){sprintf(dt_string,"%02d/%02d/%4d %02d:%02d",d.da_mon,d.da_day,d.da_year,t.ti_hour,t.ti_min);last_min=t.ti_min;changed++;}return(changed);}void get_odt(){/*--make ordinal date string - o_date--*//* cumulative number of days in months (non-leap year) */static int cdim[]={0,0,31,59,90,120,151,181,212,243,273,304,334};unsigned char ly=0; /* default=not leap year */unsigned int ddd;getdate(&d);/* get system date & time*/gettime(&t);ddd=(int)d.da_day+cdim[d.da_mon];/* how many days have gone by? *//* correct for a leap year (good from 1582-present) */if(d.da_year%4==0) /* leap year is evenly divisible by 4 */if(d.da_year%100!=0) /* and not a century year */ly=1;elseif(d.da_year%400==0) /* unless evenly divisible by 400 */ly=1;if ((d.da_mon > 2) && (ly))ddd++;/* make'em */sprintf(o_date,"%02d",d.da_year-1900);sprintf(&o_date,"%03d",ddd);sprintf(&o_date,"%02d",t.ti_hour);sprintf(&o_date,"%02d",t.ti_min);sprintf(&o_date,"%02d",t.ti_sec);}void d_win(char tr,char tc,char br,char bc,char style,char w_atrib,char feature){/*--draw a window....style - 0=no border 1=single 2=doublefeature - bit 1=single 2-part2=double 2-part7=shadowtr=top row tc=top column br=bottom row bc=bottom column--*/register r=32;unsigned int c=1;char border={{32,32,32,32,32,32,10,10},{196,179,218,191,217,192,195,180},{205,186,201,187,188,200,204,185}};/* draw the straight window */write_block(tr,tc,((br-tr)+1),((bc-tc)+1),w_atrib,r);if(style){/* draw the horizontals */write_char(tr+1,tc,w_atrib,border,(br-tr-1));write_char(tr+1,bc,w_atrib,border,(br-tr-1));/* draw the verticals */for(r=tc+1;r<bc;r++){write_char(tr,r,w_atrib,border,c);write_char(br,r,w_atrib,border,c);}/* draw the corners */write_char(tr,tc,w_atrib,border,c);write_char(br,tc,w_atrib,border,c);write_char(br,bc,w_atrib,border,c);write_char(tr,bc,w_atrib,border,c);}if(feature&3){write_char(tr+1,tc+2,w_atrib,border,(br-tr-1));write_char(tr,tc+2,w_atrib,border,c);write_char(br,tc+2,w_atrib,border,c);}if(feature&128){ /* shadow from s_char & s_attrib *//* make an offset horizontal and vertical */for(r=tc+1;r<bc+2;r++)write_char(br+1,r,w_atrib,178,c);write_char(tr+1,bc+1,w_atrib,178,(br-tr));}}void draw_screen0(char update){static int scr0_xy={{41,5},{13,11},{4,4},{51,5},{13,6},{50,4},{27,7},{2,1},{8,12},{53,2},{27,9},{53,14}};char buffer;/* only do the whole refresh every minute or on entry */if((get_dt())||(update)){clr();if((++sc0_pos)==12)sc0_pos=0;d_win(scr0_xy,scr0_xy,(scr0_xy+26),(scr0_xy+10),2,iw_red,2);sprintf(buffer,"MODEL %03d",model);write_str((scr0_xy+9),(scr0_xy+1),buffer);write_str((scr0_xy+6),(scr0_xy+8),dt_string);sprintf(buffer,"PASS=%05u",pass);d_win((scr0_xy+4),(scr0_xy+4),(scr0_xy+22),(scr0_xy+6),2,iw_red,0);write_str((scr0_xy+8),(scr0_xy+5),buffer);write_string((scr0_xy+6),(scr0_xy+5),f_iw_blue,"*");write_string((scr0_xy+19),(scr0_xy+5),f_iw_blue,"*");}else{/* just update the pass */sprintf(buffer,"%05u",pass);write_str((scr0_xy+13),(scr0_xy+5),buffer);}}unsigned char wait_key(char flush){unsigned char key;if(flush)(void)fget_key();while((key=get_key())==0);return(key);}void write_data(){register x;int line_counter=0;unsigned long sum=0;/* will skip the ordinal date id if the global id=1 */if(id){get_odt();if(fprintf(fname,"%s",o_date)==EOF)my_exit(9);}/* write the model number as the first element */if(fprintf(fname,"%d ",model)==EOF)my_exit(9);/* we add cr/lf's and padding depends on form switch */for(x=0;x<192;x++){sum+=moves;if(pad){if(fprintf(fname,"%4d",moves)==EOF)my_exit(9);}else{if(fprintf(fname,"%d ",moves)==EOF)my_exit(9);}if(++line_counter==40){line_counter=0;if(fprintf(fname,"\n")==EOF)my_exit(9);}}if(fprintf(fname,"%lu\n",sum)==EOF)my_exit(9);}

author: tggzzz
author_rank: Super Contributor
timestamp: April 12, 2021, 06:36:11 pm
content: Quote from: DrG on April 12, 2021, 05:30:00 pmHow would I know?Burroughs Algol first appeared in 1962, according tohttps://en.wikipedia.org/wiki/Burroughs_large_systems#ALGOL

author: Tom45
author_rank: Frequent Contributor
timestamp: April 12, 2021, 07:39:49 pm
content: The Burroughs B5000 series of computers were designed with a stack architecture and instructions that were a good match for running compiled ALGOL. The first of the series appeared in the early 60s, not long after the ALGOL 58 and then the ALGOL 60 language specifications.Burroughs ALGOL compiler was released in 1961. In the 60s Burroughs and ALGOL went together. So perhaps his memory conflated starting with a Burroughs computer in the 50s with the later association with ALGOL.

author: DrG
author_rank: Super Contributor
timestamp: April 12, 2021, 08:56:47 pm
content: Quote from: Tom45 on April 12, 2021, 07:39:49 pmI think that there is some problem with that sentence "He learned to program in 1956 on a Burroughs B-200 in Algol and Cal….." He is listed as being born in 1939, which would have made him 17 in 1956. That is young, but not unheard of for undergraduate school, but would Cornell let a freshman use that computer? Also, I am not sure that the B-200 existed in 1956 - have not searched that hard, but it "looks" like that series was making rounds in 1961https://www.smecc.org/burroughs_b-200.htmFurthermore, it is problematic if you assume that the sentence meaning is exactly as structured, in the sense that "he learned to program in Algol in 1956" in contrast to, "He learned to program in 1956 including using Algol and Cal". 1956 may have been a typo for 1965.He (David Ahl) has a Facebook page and I suppose he could simply be asked. I don't do Facebook and am not that interested, although there is something to be said for getting the history correct - on the other hand, I couldn't even type in the long listings and he was doing quite a bit to further the Computer Revolution, so - respect.Edited: His FB page lists him as Class of 1960 from Cornell, so, ordinarily, 1956 would be a reasonable start date.....geez is there nothing that can't sidetrack me from real work?

author: JohnnyMalaria
author_rank: Super Contributor
timestamp: April 12, 2021, 09:07:49 pm
content: Quote from: themadhippy on April 12, 2021, 05:25:57 pmNot with a Sinclair ZX<anything>

author: MIS42N
author_rank: Frequent Contributor
timestamp: April 12, 2021, 11:16:42 pm
content: The Burroughs B-200 introduced 1961http://burroughsinfo.com/historical-timeline.html, the first Algol 1958. David Ahl completes High School 1956http://www.swapmeetdave.com/Ahl/DHAbio.htmso clearly the bio is wrong.My first program was written in 1967 in Algol on an Elliot 803https://en.wikipedia.org/wiki/Elliott_ALGOL. I came across the printout in an archival dig a few weeks back, and now wondering if the paper tape survives somewhere in the archives. It was written as part of a course called "Computer Programming for Engineers", it was such a buzz I dropped the engineering bit and chased programming jobs. In 1968 I became a PIT (programmer in training). I encountered a Burroughs B200? (can't find a reference to it) at Monash University (Melbourne) in 1969, it was their administration computer - 3 tape drives for storage. The campus computer was a B5500, a beast for the time.

author: tggzzz
author_rank: Super Contributor
timestamp: April 12, 2021, 11:43:45 pm
content: Quote from: MIS42N on April 12, 2021, 11:16:42 pmThere's a working 803B at The National Museum of Computing. The staff are happy to whip out the schematics and discuss them with you - that's my idea of agreatmuseumThe oldest working computer in the world is in the next room.Bletchley Park museum is next door, but is best ignored.If you get a chance, go seehttps://www.tnmoc.org/elliott-brothers-computerswhich notesQuote

author: IanB
author_rank: Super Contributor
timestamp: April 13, 2021, 12:05:47 am
content: Quote from: DrG on April 12, 2021, 08:56:47 pmMy personal experience: in olden times universities often had outreach programs with local high schools, where they made computing resources available to high school students for computer science classes.This was sometimes very low tech: students of 14 or 15 years old would write their programs in pencil on coding sheets, which would be taken by courier or mail to the computing center for keying into the system. The students' programs would then be run in batch mode and the output delivered back to the classroom. The students had quite an anxious wait to find out if their program had run successfully, or if the line printer output just said "Syntax error at line 70". A mistake in your program would lead to a wait of several days before you could try again.The less painful form of access was by dial up modem using a teletype machine. It was a rite of passage to write the program that would send a long string of ^G characters to the ASR-33 teletype and fill the room with Ding-Ding-Ding-Ding-Ding sounds!A highlight was a school bus trip to the local computing center where the whole class could sit in a terminal room and program at the same time.I had a lot of fun, for example, using DEC System 10 and PDP-11 machines.

author: DrG
author_rank: Super Contributor
timestamp: April 13, 2021, 12:14:12 am
content: Quote from: IanB on April 13, 2021, 12:05:47 amYes, you have a point there and that "outreach" continues today. Still as I said in the post you quoted and in the one by @MIS42N ,there are some problems with that sentence in that biography. Not saying anything at all to suggest that it was intentional or anything of the like (nor do I think others are). Personally, I admire and respect the man's vision and contribution.

author: rfclown
author_rank: Frequent Contributor
timestamp: April 13, 2021, 12:18:29 am
content: Quote from: JohnnyMalaria on April 12, 2021, 09:07:49 pmNot with "anything" when this book came out. There was a "scanner" for the IBM 370 that I fed programs into during my summer job as a student, but it only read punch cards. For my TRS-80, I typed everything in (then saved on cassette tape).

author: xrunner
author_rank: Super Contributor
timestamp: April 13, 2021, 12:37:31 am
content: Oh yea! I had a Radio Shack Trash-80 before I went to the university. I typed in those games from some magazine I got every month (don't remember the name now). They NEVER worked right it seemed (too many GOTOs LOL), and you had to debug the damn things every time. But I'll tell you what - that learning helped in ways I will never regret!

author: DrG
author_rank: Super Contributor
timestamp: April 13, 2021, 12:40:35 am
content: Quote from: rfclown on April 13, 2021, 12:18:29 amCoincidentally, I have a Data Dubber for TRS-80 cassette tapes on my bench as I type. I want to test it out by looking at the before and after wave forms - which, for me, will be a good chance to use an o-scope (Owon HDS1022M-N). As you may remember the TRS-80 cassette system was, at times, frustratingly crappy. Maybe I will have some graphics to post.

author: JohnnyMalaria
author_rank: Super Contributor
timestamp: April 13, 2021, 01:46:58 am
content: Quote from: DrG on April 13, 2021, 12:40:35 amI wonder if it was as crappy as my ZX-80. My B&W TV would interfere so I had to turn off the TV and, thanks to the copious emissions from the ZX-80, listen to an AM radio to hear the tape transfer. When it went silent(ish), either it was complete or the RAM pack had moved a femtometer and crashed...

author: DrG
author_rank: Super Contributor
timestamp: April 14, 2021, 07:36:45 pm
content: Quote from: JohnnyMalaria on April 13, 2021, 01:46:58 amI don't know. I did have a ZX-81 for a short time and gave it to someone, not sure if I ever made a tape - I couldn't get past the blinking (didn't the Z80 do the vid as well?). I see that you can get them pretty cheaply on $bay (not sure if you can get working ones that cheap though).https://www.ebay.com/itm/Sinclair-ZX81-personal-computer-with-power-cord-untested-as-is/303937622095?hash=item46c418104f:g:3xgAAOSwGQVgYMe6

author: rsjsouza
author_rank: Super Contributor
timestamp: April 14, 2021, 07:58:10 pm
content: I remember those days, typing some simple programs on the display computers at the local Sears or at a friend's house. Most ZX81 clones.One thing I recall were the numerous syntax errors on these listings. The editors started collating the program listings printed directly from the computer instead of re-typing them. This reduced the number of typos severely.

author: bson
author_rank: Unknown
timestamp: April 14, 2021, 11:35:58 pm
content: I had only programmed calculators before, but learned elementary programming from that Ahl book by typing in the programs and then understanding how they work from the listings and by experimenting... Must have been in 79. This was on a Z80 computer, and the next step was hand assembling Z80 programs into hex and poking them into memory - and running and trying to figure out why they didn't work. (Usually producing a hard hang or reset.) Nothing like it to make one pay attention to detail.

author: rfclown
author_rank: Frequent Contributor
timestamp: April 15, 2021, 01:49:47 am
content: Quote from: bson on April 14, 2021, 11:35:58 pmSame for me. The first thing I programmed was a large programmable caluculator that my high school had which was hooked to a pen plotter. You could save the programs on a magnetic card. I was going to take a computer class the next year, but my family moved from Illinois to Alabama, and the school had no computer stuff. My dad got me a TRS-80 (Z80), and I learned BASIC and hand assembled and poked into memory (reset switch got a lot of action). The only two programs I bought for my TRS-80 was a tiny PASCAL, and finally an assembler. This was in 79. Then it was off to college, and the TRS-80 didn't get as much use since I then had PDPs to play with, except to prank friends. I hooked the cassette on/off relay to the phone line to pulse dial. Then I'd program it to dial a friend's number after a long delay, and keep dialing every few minutes. The delay gave me time to go over to my friend's appartment to hang out.

author: MIS42N
author_rank: Frequent Contributor
timestamp: April 15, 2021, 10:50:23 pm
content: Quote from: IanB on April 13, 2021, 12:05:47 amNot just students with the slow turnaround. My first programming job, the computer was busy all day with production work and all development was run by the night shift. So we had one shot per day to get a program working. It was normal to have 10 or more programs on the go at the same time. The day would start by looking at the night's output. Fix syntax errors first, they were the most obvious. Then look at all the test runs, fix the logic errors. If there was time after that, continue writing the next program.Some of the programs were epic. One I wrote was 7000 punch cards, 3-1/2 card boxes and took several minutes just to read in. This was in the days of batch processing. The program took input from another program that supposedly validated user input - valid dates in date columns, reasonable values in numeric columns etc. The program took this input and validated it against numerous random access files, did some processing and passed it on to the program that updated files.One night, a card was missing from the deck (unexplained). This resulted in the library definitions of two files to not be copied in, so the compiler flagged errors. Since almost every line of the program dealt with one or other of the files, the resulting error list was HUGE. We put the printout in the back of a utility, weighed the end down with a rock and drove until it was all laid out on the road. it was quarter of a mile long.What was interesting, that program occupied less than 64kbytes memory. IIRC it had multiple overlays (a precursor of virtual memory that was explicitly programmed) and every time it was changed it was necessary to shuffle things so it still fitted into the available memory.It took many programmers most of a year to get that suite of programs into operation. When it was finished, it cut production costs so much it saved the cost of development in less than a year.Memories, sweet memories. I still do programming for 'fun'. The current project is about 4000 lines and if it takes more than 5 seconds to compile I'm wondering what else was happening to slow it down. The good old day weren't that good.

author: Kleinstein
author_rank: Super Contributor
timestamp: April 16, 2021, 06:23:26 am
content: Typing in a Basic program from a journal was an odd way. I did it, but not very often, and not much basic. I remember that there was a short program for the C64 to also type in binary files with some check-sums.It's nearly 20 years I last wrote a Basic program (some simple data-logging). It brings back memory.Modern compilers tend to be relatively slow - this is in part from C and related languages with the program split over many files, plenty of libraries and #defines, but also with more optimization. With respect to compiler speed the Borland turbo pascal and related are really nice.There is also a positive side if the turn around cycle is a bid slower - it forces to take more care and write correct code from the start. In some respects µC programming is a bid like with the computers in the 1980s.

author: floobydust
author_rank: Super Contributor
timestamp: April 16, 2021, 06:41:47 pm
content: Quote from: MIS42N on April 15, 2021, 10:50:23 pmHardware is powerful enough now that we've gone full circle- interpreted languages such as BASIC, Python are getting popular (FORTH I will leave out).The main thing an interpreted language offers is run-time error checking. Instead of the shit that is C and C++ where you can punch a hole in an OS with an bad array index, or a buffer overrun inserting your favorite trojan, even antique BASIC spit out an error message and a programmer would know their code went past some limit for a variable.

author: IanB
author_rank: Super Contributor
timestamp: April 16, 2021, 06:52:57 pm
content: Quote from: floobydust on April 16, 2021, 06:41:47 pmLet's not exaggerate. There is no modern OS where this is possible. Memory pages have access protection at the hardware level and you cannot corrupt system memory from user space by writing to wrong memory addresses. You can write the crappiest program you like with complete confidence. The worst that will happen is that your program will crash.(The exception would be a simple microcontroller system like an Arduino, but then it is not running an OS either.)

author: floobydust
author_rank: Super Contributor
timestamp: April 16, 2021, 07:24:16 pm
content: Windows 10 "Page Fault In Nonpaged Area" and a BSOD. The hardware can catch it but the OS bungles it.We've had decades of blue screens, I don't think I'm exaggerating as far as modern personal computing still plagued by a rogue programming language.To this day we have buffer overruns as a security problem. At some point we need to acknowledge some programming languages are dangerous and not improving, instead relying on expertise.As far as retro-computing, learning it should be fun- not some venture into frustration that causes kids and noobs to dislike programming.BASIC as an antique language- slower, easier to learn and safer than C, C++ lol.

author: JohnnyMalaria
author_rank: Super Contributor
timestamp: April 16, 2021, 07:48:07 pm
content: Quote from: floobydust on April 16, 2021, 07:24:16 pmHow can that happen from user mode? i.e., how can writing to a memory address from a C/C++ program cause such a driver error?

author: Kleinstein
author_rank: Super Contributor
timestamp: April 16, 2021, 08:08:17 pm
content: Quote from: floobydust on April 16, 2021, 06:41:47 pmComplied code can also catch runtime errors. It is just a question of the compiler / settings. The extra checks take a little extra time and memory - today this should be not a problem at all. Pascal compilers usually did runtime checks by default, while C compilers usually did not - in part because things like overflow are "normal" with C. The C style strings were a bit error prone and hard to check. Pascal was more written for learning - stricter type checking and more checks.I initially liked Basic and Arex (a kind of Python predecessor on the Amiga), but now I miss the error checks done by the compiler. Especially with a longer program it is a big no go if a rarely used routine fails because of a syntax error. Compiler warnings are also really nice.

author: IanB
author_rank: Super Contributor
timestamp: April 16, 2021, 08:21:05 pm
content: Quote from: floobydust on April 16, 2021, 07:24:16 pmIf you can write a user mode program that does that without elevated privileges you can submit a bug report to Microsoft. That would be a serious security vulnerability in Windows and they would in due course roll out a patch to fix it through Windows updates.Such a thing could happen due to bugs in a device driver, but unfortunately there you are at the mercy of the hardware vendor. Unlike Apple, Microsoft does not control the hardware platform, and if the hardware screws up you cannot do much about it except to replace or reject the faulty hardware.

author: Phil_G
author_rank: Regular Contributor
timestamp: April 20, 2021, 04:10:49 pm
content: Quote from: rfclownIs it still running? cos I'm getting get those calls every day...