# altair.awk BEGIN { PROCINFO["/dev/stdin", "RETRY"] = 1 PROCINFO["/dev/stdin", "READ_TIMEOUT"] = 10 MAX_MEMORY=65536 hexstr["0"]=0 hexstr["1"]=1 hexstr["2"]=2 hexstr["3"]=3 hexstr["4"]=4 hexstr["5"]=5 hexstr["6"]=6 hexstr["7"]=7 hexstr["8"]=8 hexstr["9"]=9 hexstr["A"]=10 hexstr["B"]=11 hexstr["C"]=12 hexstr["D"]=13 hexstr["E"]=14 hexstr["F"]=15 mmscale=44.2 xrescale=48.0 xadrescale=72.0 xcenterrescale=72.00+4 ydatarescale=8.0+37 yaddrrescale=20.0+37 ysenserescale=32.0+37 ycenterrescale=44.0+37 for(i=1;i<256;i++){ asc[sprintf("%c",i)]=i } y1paper=8*mmscale y2paper=80*mmscale x1paper=112*mmscale x2paper=208*mmscale dx=5.0 dy=8.10 dgx=dx*3.43457 LXIreg="BCDEHLSs" MOVreg="BCDEHLmA" abottext[0]="HLDA" abottext[1]="WAIT" atoptext[0]="INT" atoptext[1]="WO" atoptext[2]="STACK" atoptext[3]="HLTA" atoptext[4]="OUT" atoptext[5]="MI" atoptext[6]="INP" atoptext[7]="MEMR" atoptext[8]="PROT" atoptext[9]="INTR" acentertop[0]="Aux 1." acentertop[1]="Aux 2." acentertop[2]="Protect" acentertop[3]="Reset" acentertop[4]="Deposit" acentertop[5]="Examine" acentertop[6]="Single" acentertop[7]="Stop" acentertop[8]="On" acenterbot[0]="" acenterbot[1]="" acenterbot[2]="Unprotect" acenterbot[3]="Clr" acenterbot[4]="Next" acenterbot[5]="Next" acenterbot[6]="Step" acenterbot[7]="Run" acenterbot[8]="Off" y=ysenserescale*mmscale x=10000-(xadrescale+1.74+xrescale)*mmscale for ( i = 0; i < 16; i++ ) { senseSWx[i]=x-((int(i/3)*dgx+(i%3)*dx)*mmscale);senseSWy[i]=y } y=ycenterrescale*mmscale; x=10000-(xcenterrescale+1.64+xrescale)*mmscale; for ( i = 0; i < 9; i++ ) { centerSWx[i]=x-i*2*dx*mmscale;centerSWy[i]=y } printf( "Fo 0 88 3\nFo 2 128 3\nFo 1 128 3\nFo 3 128 3\n" );fflush(stdout) LEDstr="21a6b9a8b7a5B5a6B4a5bC5b3a5bDC5bA4bc3dc5bA4bCdC5bA5b3c6b3a6B4a6B5a5B7a8b9a5b22a" centerSWstr="41a15b8Ab5c6daCb8AbC3d5cD3cb7AbCd3c5eCdCb7Abcdc8fEcDcb6Abcdc11fecDb11abcdc13fecdcb5Abcdc7FCdb9abcdc15fecdcb8abcdc8Fecdb7abcdc8f3e6fecdcb6abcdc8f3de5fecdcb5abCdc7fcdcDe4fecdCb4abcdc7fcb3cDe3fEcdcb3abCdc6fc3b3cDeFEcdCbAbCdc6f4b3cDeFEcdCb3abcdc6f5bc3deFEcdCb3abCdc6fcBc3de3fEcdcb5abcdc7f5de4f3eCb6abdc7fe3de5fEcdb7abcdc7f3e6fecdcb8abdc15fEcdb9abcdc7Fecdcb5Abdc13fEcdb11abcdc11fEcdcb6Abcdc9fEcDb13abCdC7eCdCb7AbCD7cDCb15ab4c7d4cb8A15b40a" downSWstr="41a15b8Ab5c6daCb8AbC3d5cD3cb7AbCd3c5eCdCb7Abcdc8fEcDcb6Abcdc11fecDb11abcdc13fecdcb5Abcdc7FCdb9abcdc15fecdcb8abcdc8Fecdb7abcdc17fecdcb6abcdc17fecdcb5abCdc8fede6fecdCb4abcdc8fe3de5fEcdcb3abCdc7fEdcde5fEcdCbAbCdc7fedCdE4fEcdCb3abcdc7fedbcDe4fEcdCb3abCdc6fDbcDe4fEcdcb5abcdc7fdBcd5f3eCb6abdc7fdcbcd5fEcdb7abcdc6fdBC5fecdcb8abdc5fdc3bc4fEcdb9abcdc5fc3bc4fecdcb5Abdc5fc3bc3fEcdb11abcdc4fcBCFEcdcb6Abcdc4f3cFEcDb13abCdC7eCdCb7AbCD7cDCb15ab4c7d4cb8A15b40a" upSWstr="6AdC3bcd21a3bdc5bcd3b8Ab3cdc5bdaCb8AbCDc5bD3cb7AbCdcdc5bdcdCb7AbcdceDc3bcdecDcb6Abcdc3edc3bcFecDb11abcdc4edc3bc3eecdcb5Abcdc5eCBc4eCdb9abcdc6ed3bc4eecdcb8abcdc6ed3bd5eecdb7abcdc7edcbcd5eecdcb6abcdc7edBcd5eecdcb5abCdc7edBc6eecdCb4abcdc8eDbce5eEcdcb3abCdc7eeDCe5eEcdCbAbCdc7eEdcde5eEcdCb3abcdc7e3ede6eEcdCb3abCdc7e4e6eEcdcb5abcdc17e3eCb6abdc17eEcdb7abcdc8Fecdcb8abdc15eEcdb9abcdc7Fecdcb5Abdc13eEcdb11abcdc11eEcdcb6Abcdc9eEcDb13abCdC7eCdCb7AbCD7cDCb15ab4c7d4cb8A15b40a" gfverbose=0 gfverbosestderr=0 gfttystderr=0 areg["A"]=0 areg["B"]=0 areg["C"]=0 areg["D"]=0 areg["E"]=0 areg["H"]=0 areg["L"]=0 areg["S"]=int(MAX_MEMORY/256) areg["s"]=(MAX_MEMORY%256) for ( pc=0; pc < 65536; pc++ ) { setmem(pc,0x0) } if ( 0 ) { #another altair app Tim wrote in 1978 fn = "monitor.oct" while ( getline < fn > 0 ) { i=1 if ( $1 ~ /^[0-7][0-7][0-7]:[0-7][0-7][0-7]:$/ ) { upper=$1 lower=$1 sub(/:.*/, "", upper ) sub(/^[0-7][0-7]*:/, "", lower ) pc=colon(stroct(upper),stroct(lower)) i++ } else if ( $1 ~ /^[0-7][0-7]*:$/ ) { pc=stroct($1) i++ } for ( ; i <= NF; i++ ) { setmem(pc,stroct($i));pc=and(0xffff,(pc+1)) } } pc=colon(030,0135) # breakpoints[colon(030,0370)]++ } else { #parseasm( "basic.lst" ) parsehex( "8kbas.hex" ) #parsehex( "altdos.hex" ) #parsehex( "exbas.hex" ) } pc=0 ipc=0 topsw=128+32+2 botsw=0 fnotexit=1 while (fnotexit) { status = (getline < "/dev/stdin") if (status == -2) { if ( fnotexit ) { exe() } } else if (status > 0) { if ( $1 == "drawapp" ) { delete acachedbmps drawpanel() printf( "F 0 16777215\n" );fflush(stdout) printf( "B 0 %d\n", 0x777777 ) printf( "B 2 %d\n", 0x777777 ) printf( "F 3 0\n" ) printf( "B 3 %d\n", 0xE0C9A6 ) drawdatatexts() drawaddresstexts() drawsensetexts() drawcentertexts() drawtoptexts() drawbottexts() drawdataLEDs(mem(pc)) drawtopstatusLEDs(topsw) drawbotstatusLEDs(botsw) drawaddressLEDs(pc) drawcenterSWs() drawsenseSWs(ipc) drawregisters() drawpaper() printf( "B 1 %d\n", 0x777777 ) printf( "F 1 0\nL$ 1 1000 300 \"awk cloud app transparent shell stdinout\"\nZ \n" );fflush(stdout) } else if ( $1 == "QUERY_REMOTE" ) { printf( "Rz 1600 658\n" );fflush(stdout) } else { button = 0+$1 x = 0+$2 y = 0+$3 if ( x == -2 ) { #ASC(key) if ( fexecution ) { if ( button > 0 ) { ginputbuffer="" ginputbuffer sprintf( "%c", button ) } } else if ( button == 114 ) { clickrun() } else if ( button == 101 ) {examinenext()} else if ( button == 69 ) {examine()} else if ( button == 100 ) {depositnext()} else if ( button == 68 ) {deposit()} else if ( button == 112 ) {step();drawdataLEDs(mem(pc));drawaddressLEDs(pc);drawregisters()} } else if ( x == -4 ) { printf( "Rz %d %d\n", button, y );fflush(stdout); } else if ( x == -5 ) { printf( "Mv %d %d\n", button, y );fflush(stdout); } else if ( x == -98 ) { sstr=sprintf( "sleep %4.3f\n", 0.001*y ) system( sstr ) } else if ( button == 3 ) { drawdataLEDs(mem(pc)) drawtopstatusLEDs(topsw) drawbotstatusLEDs(botsw) drawaddressLEDs(pc) drawsenseSWs(ipc) fnotexit=0 printf( "O 0 0 0\n" );fflush(stdout); } else { if ( ( y > senseSWy[0]-dy*mmscale ) && ( y < senseSWy[0]+dy*mmscale ) ) { i2=1 fnotdone=1 for ( i = 0; fnotdone && (i < 16 ); i++ ) { if ( ( x > senseSWx[i] ) && ( x < senseSWx[i]+dx*mmscale ) ) { if ( y < senseSWy[i] ) {ipc=or(ipc,i2);fnotdone=0 } else if ( ( y > senseSWy[i] ) && ( y < senseSWy[i]+dy*mmscale ) ) { ipc=and(ipc,compl(i2));fnotdone=0 } } i2 *= 2 } if ( fnotdone == 0 ) { drawsenseSWs(ipc) } } if ( ( y > centerSWy[0]-dy*mmscale ) && ( y < centerSWy[0]+dy*mmscale ) ) { i2=1 fnotdone=1 for ( i = 0; fnotdone && (i < 9 ); i++ ) { if ( ( x > centerSWx[i] ) && ( x < centerSWx[i]+dx*mmscale ) ) { if ( y < centerSWy[i] ) { if ( i == 5 ) { examine() } else if ( i == 4 ) { deposit() } else if ( i == 6 ) { step() drawdataLEDs(mem(pc)) drawaddressLEDs(pc) drawregisters()} else if ( i == 7 ) { fexecution=0 } fnotdone=0 } else if ( ( y > centerSWy[i] ) && ( y < centerSWy[i]+dy*mmscale ) ) { if ( i == 5 ) { examinenext() } else if ( i == 4 ) { depositnext() } else if ( i == 6 ) { step() drawdataLEDs(mem(pc)) drawaddressLEDs(pc) drawregisters() } else if ( i == 7 ) { clickrun() } else if ( i == 8 ) { printf( "O 0 0 0\n" );fflush(stdout) fnotexit=0 } fnotdone=0 } } i2 *= 2 } if ( fnotdone == 0 ) { drawsenseSWs(ipc) } } } } if ( fnotexit ) { exe() } } else if (status == 0) { fnotexit = 0 # End of input } } exit(0) } function parsehex( fn, comment,pc, i, len, j ) { while ( getline < fn > 0 ) { pc=strhex($1) for ( i = 2; i <= NF; i++ ) { len=length($i) for ( j = 1; j < len; j += 2 ) { setmem(pc,strhex(substr($i,j,2)));pc=and(0xffff,(pc+1)) } } } } function parseasm( fn, comment,pc, i, len ) { while ( getline < fn > 0 ) { if ( $0 ~ /^[0-9a-fA-F][0-9a-fA-F]*:/ ) { comment=$0 sub( /^[^\t][^\t]*\t/, "\t", comment ) gsub( / .*$/, "" ) pc=strhex($1) acomment[pc]=comment len=length($2) for ( i = 1; i < len; i += 2 ) { setmem(pc,strhex(substr($2,i,2)));pc=and(0xffff,(pc+1)) } } } } function exe( fstep, fnotbail, instr ) { fstep = 0 fnotbail = 1 if ( fexecution == 1 ) { while ( fnotbail && ( fstep < 20000 ) ) { instr = mem(pc);port=mem(pc+1) if ( instr == 211 ) { drawdataLEDs(mem(pc)) drawaddressLEDs(pc) drawregisters() fflush(stdout) fnotbail = 0 } step() if ( ( ( instr == 219 ) && ( (port%2) == 1) ) || ( gfverbose == 1 ) ) { drawdataLEDs(mem(pc)) drawaddressLEDs(pc) drawregisters() fflush(stdout) } if ( gfverbose == 1 ) { fstep = 10000 } else { fstep++ } if ( fnotbail == 0 ) { return } } drawdataLEDs(mem(pc)) #Might be too much drawaddressLEDs(pc) drawregisters() } } function drawpaper(str,x,y) { printf( "F 0 %d\n", 0xE0C9A6 ) printf( "FR 0 %d %d %d %d\n", x1paper, y1paper, x2paper, y2paper ) printf( "F 0 %d\n", 0x0 ) } function drawregisterbox(x1,y1,x2,y2) { printf( "F 0 %d\n", 0x330000 ) printf( "R 0 %d %d %d %d\n", x1-20,y1-20,x2,y2) printf( "F 0 %d\n", 0x777777 ) printf( "FR 0 %d %d %d %d\n", x1,y1,x2,y2) printf( "F 2 %d\n", 0x550000 ) } function drawregisterA(y){ drawregisterbox(12*mmscale,int((y-2.0)*mmscale),12*mmscale+int(5*4*mmscale*0.6),int(y*mmscale)+int(mmscale/2)) if ( gfverbosestderr == 1 ) { printf( "A:%3.3o", areg["A"] ) >"/dev/stderr" } printf( "L$ 2 %d %d \"A:%3.3o\"\n", 12*mmscale, int((y+0.4)*mmscale), areg["A"] ) } function drawregisterpair(y,hi,low) { drawregisterbox(12*mmscale,int((y-2.0)*mmscale),12*mmscale+int(11*4*mmscale*0.6),int(y*mmscale)+int(mmscale/2)) if ( gfverbosestderr == 1 ) { printf( " %s:%3.3o %s:%3.3o", hi, areg[hi], low, areg[low] )>"/dev/stderr" } printf( "L$ 2 %d %d \"%s:%3.3o %s:%3.3o\"\n", 12*mmscale, int((y+0.4)*mmscale), hi, areg[hi], low, areg[low] ) } function drawregistersnp(y,label,val) { drawregisterbox(12*mmscale,int((y-2.0)*mmscale),12*mmscale+int(11*4*mmscale*0.6),int(y*mmscale)+int(mmscale/2)) if ( gfverbosestderr == 1 ) { printf( " %s:%3.3o:%3.3o", label, int(val/256), (val%256))>"/dev/stderr" } printf( "L$ 2 %d %d \"%s:%3.3o:%3.3o\"\n", 12*mmscale, int((y+0.4)*mmscale), label, int(val/256), (val%256) ) } function drawregisterFlags(y){ y=11.80 drawregisterbox(28*mmscale,int((y-2.0)*mmscale),28*mmscale+int(26*4*mmscale*0.6),int(y*mmscale)+int(mmscale/2)) printf( "L$ 2 %d %d \"Flags:%2.2s:%2.2s:0:%2.2s:0:%2.2s:1:%2.2s\"\n", 28*mmscale, (12+0.2)*mmscale, (aflags["S"]?"N-":"P+"), (aflags["Z"]?"Z":"NZ"), (aflags["A"]?"AC":"NA"), (aflags["P"]?"PE":"PO"), (aflags["C"]?"CY":"NC") ) if ( gfverbosestderr == 1 ) { printf( " Flags:%2.2s:%s:0:%2.2s:0:%2.2s:1:%2.2s", (aflags["S"]?"N-":"P+"), (aflags["Z"]?"Z":"NZ"), (aflags["A"]?"AC":"NA"), (aflags["P"]?"PE":"PO"), (aflags["C"]?"CY":"NC") )>"/dev/stderr" } } function drawregisters(str,x,y) { y=12 x=12 drawregisterA(11.80); drawregisterFlags(11.80) drawregisterpair(11.80+3.15, "B", "C") drawregisterpair(11.80+2*3.15, "D", "E") drawregisterpair(11.80+3*3.15, "H", "L") drawregistersnp(11.80+4*3.15, "SP", areg["S"]*256+areg["s"]) drawregistersnp(11.80+5*3.15, "PC", pc) show(pc) } function dispop1(opstr,instr,x,y) { y=32*mmscale;x=12*mmscale;len=16 drawregisterbox(x,y-3*mmscale,x+int(4*mmscale*len*0.6),int(y+mmscale/2)) printf( "L$ 2 %d %d \"%s\"\n", x,y, opstr ) if ( gfverbosestderr == 1 ) { printf( " %s\n", opstr )>"/dev/stderr" } } function dispop2(opstr,argstr,instr,x,y) { y=32*mmscale;x=12*mmscale;len=16 drawregisterbox(x,y-3*mmscale,x+int(4*mmscale*len*0.6),int(y+mmscale/2)) printf( "L$ 2 %d %d \"%s %s\"\n",x,y,opstr,argstr ) if ( gfverbosestderr == 1 ) { printf( " %s %s\n",opstr,argstr )>"/dev/stderr" } } function cacheupswitch(x1,y1,x2,y2) { if ( 0 in acachedbmps ) { printf( "Gl %d %d %d %d 0\nZ \n", x1, y1, x2,y2);fflush(stdout) } else { printf( "Ga %d %d %d %d 0\"32 32 =a777=bfff=cbbb=d555=e111=f000 %s\"\nZ \n", x1, y1, x2,y2, upSWstr );fflush(stdout) acachedbmps[0]=0 } } function cachedownswitch(x1,y1,x2,y2) { if ( 1 in acachedbmps ) { printf( "Gl %d %d %d %d 1\nZ \n", x1, y1, x2,y2);fflush(stdout) } else { printf( "Ga %d %d %d %d 1\"32 32 =a777=bfff=cbbb=d555=e111=f000 %s\"\nZ \n", x1, y1, x2,y2, downSWstr );fflush(stdout) acachedbmps[1]=1 } } function cachecenterswitch(x1,y1,x2,y2) { if ( 2 in acachedbmps ) { printf( "Gl %d %d %d %d 2\nZ \n", x1, y1, x2,y2);fflush(stdout) } else { printf( "Ga %d %d %d %d 2\"32 32 =a777=bfff=cbbb=d555=e111=f000 %s\"\nZ \n", x1, y1, x2,y2, centerSWstr );fflush(stdout) acachedbmps[2]=2 } } function cacheledon(x1,y1,x2,y2) { if ( 3 in acachedbmps ) { printf( "Gl %d %d %d %d 3\nZ \n", x1, y1, x2, y2 );fflush(stdout) } else { printf( "Ga %d %d %d %d 3\"16 16 =a777=bf00=cf22=df77 %s\"\nZ \n", x1, y1, x2, y2, LEDstr );fflush(stdout) acachedbmps[3]=3 } } function cacheledoff(x1,y1,x2,y2) { if ( 4 in acachedbmps ) { printf( "Gl %d %d %d %d 4\nZ \n", x1, y1, x2,y2);fflush(stdout) } else { printf( "Ga %d %d %d %d 4\"16 16 =a777=b300=c422=d533 %s\"\nZ \n", x1, y1, x2,y2, LEDstr );fflush(stdout) acachedbmps[4]=4 } } # collapse everything but the thing and call a common drawfrontpanel function examine() { drawcenterSW(centerSWx[5],centerSWy[5],+1) pc=ipc drawaddressLEDs(pc) drawdataLEDs(mem(pc)) drawcenterSW(centerSWx[5],centerSWy[5],0) drawregisters() } function examinenext() { drawcenterSW(centerSWx[5],centerSWy[5],-1) pc=and(0xffff,(pc+1)) drawaddressLEDs(pc) drawdataLEDs(mem(pc)) drawcenterSW(centerSWx[5],centerSWy[5],0) drawregisters() } function deposit() { drawcenterSW(centerSWx[4],centerSWy[4],+1) setmem(pc,and(255,ipc)) drawaddressLEDs(pc) drawdataLEDs(mem(pc)) drawcenterSW(centerSWx[4],centerSWy[4],0) drawregisters() } function depositnext() { drawcenterSW(centerSWx[4],centerSWy[4],-1) setmem(++pc,and(255,ipc)) drawaddressLEDs(pc) drawdataLEDs(mem(pc)) drawcenterSW(centerSWx[4],centerSWy[4],0) drawregisters() } function drawcenterSW(x,y,upcenterdown) { if ( upcenterdown == 1 ) { cacheupswitch( x, y, x+3.51*mmscale,y+3.51*mmscale ) } else if ( upcenterdown == -1 ) { cachedownswitch( x, y, x+3.51*mmscale,y+3.51*mmscale ) } else { cachecenterswitch( x, y, x+3.51*mmscale,y+3.51*mmscale) } } function drawSW(x,y,onoff) { if ( onoff == 0 ) { cachedownswitch( x, y, x+3.51*mmscale,y+3.51*mmscale ) } else { cacheupswitch( x, y, x+3.51*mmscale,y+3.51*mmscale) } } function drawLED(x,y,onoff) { if ( onoff == 0 ) { cacheledoff( x, y, x+3.51*mmscale,y+3.51*mmscale ) } else { cacheledon( x, y, x+3.51*mmscale,y+3.51*mmscale) } } function drawtopstatusLEDs(topstatus,x,y,i,bit) { y=ydatarescale*mmscale;x=(101.41-xrescale)*mmscale; for ( i = 0; i < 10; i++ ) { bit=(topstatus%2); if ( bit != alasttopstatus[i] ) { drawLED(x-i*dx*mmscale,y,bit); alasttopstatus[i]=bit }; topstatus = int(topstatus/2) } } function drawbotstatusLEDs(botstatus,x,y,i,bit) { y=yaddrrescale*mmscale;x=(101.41-xrescale)*mmscale; for ( i = 0; i < 2; i++ ) { bit=(botstatus%2); if ( bit != alastbotstatus[i] ) { drawLED(x-(i+8)*dx*mmscale,y,bit); alastbotstatus[i]=bit }; botstatus = int(botstatus/2) } } function drawaddresstexts(x,y,i,bit) { y=(yaddrrescale-1.38)*mmscale; x=10000-(xadrescale+xrescale)*mmscale for ( i = 0; i < 16; i++ ) { printf( "C$ 0 %d %d \"A%d\"\n", x-((int(i/3)*dgx+(i%3)*dx)*mmscale),y,i);fflush(stdout) } } function drawsensetexts(x,y,i,bit) { y=(ysenserescale-1.38)*mmscale; x=10000-(xadrescale+xrescale)*mmscale for ( i = 0; i < 16; i++ ) { printf( "C$ 0 %d %d \"%d\"\n", x-((int(i/3)*dgx+(i%3)*dx)*mmscale),y,i);fflush(stdout) } } function drawtoptexts(x,y,i,bit) { y=(ydatarescale-1.38)*mmscale; x=(103.04-xrescale)*mmscale for ( i = 0; i < 16; i++ ) { if ( length(atoptext[i])>0) { printf( "C$ 0 %d %d \"%s\"\n", x-i*dx*mmscale,y,atoptext[i]);fflush(stdout) } } } function drawbottexts(x,y,i,bit) { y=(yaddrrescale-1.38)*mmscale; x=(103.04-xrescale)*mmscale for ( i = 0; i < 2; i++ ) { if ( length(abottext[i])>0) { printf( "C$ 0 %d %d \"%s\"\n", x-(i+8)*dx*mmscale,y,abottext[i]);fflush(stdout) } } } function drawdatatexts(x,y,i,bit) { y=(ydatarescale-1.38)*mmscale; x=10000-(xadrescale+xrescale)*mmscale for ( i = 0; i < 8; i++ ) { printf( "C$ 0 %d %d \"D%d\"\n", x-((int(i/3)*dgx+(i%3)*dx)*mmscale),y,i);fflush(stdout) } } function drawdataLEDs(data,x,y,i,bit) { y=ydatarescale*mmscale; x=10000-(xadrescale+1.74+xrescale)*mmscale for ( i = 0; i < 8; i++ ) { bit=(data%2) if ( bit != alastdata[i] ) { drawLED(x-((int(i/3)*dgx+(i%3)*dx)*mmscale),y,bit) alastdata[i]=bit } fflush(stderr) data = int(data/2) } } function drawaddressLEDs(addr,x,y,i,bit) { y=yaddrrescale*mmscale; x=10000-(xadrescale+1.74+xrescale)*mmscale for ( i = 0; i < 16; i++ ) { bit=(addr%2) if ( bit != alastaddr[i] ) { drawLED(x-((int(i/3)*dgx+(i%3)*dx)*mmscale),y,bit);alastaddr[i]=bit } addr = int(addr/2) } } function drawsenseSWs(sense,x,y,i,bit) { for ( i = 0; i < 16; i++ ) { bit=(sense%2); if ( bit != alastsense[i] ) { drawSW(senseSWx[i],senseSWy[i],bit);alastsense[i]=bit }; sense = int(sense/2) } } function drawcenterSWs(data,x,y,i,bit) { for ( i = 0; i < 9; i++ ) { drawcenterSW(centerSWx[i],centerSWy[i],0) }; drawcenterSW(centerSWx[8],centerSWy[8],1) } function drawcentertexts(x,y,i) { x=10000-(xcenterrescale+xrescale)*mmscale for ( i = 0; i < 9; i++ ) { if ( length(acentertop[i])>0 ) { printf( "C$ 0 %d %d \"%s\"\n", x-i*2*dx*mmscale,(ycenterrescale-1.38)*mmscale,acentertop[i]);fflush(stdout) } if ( length(acenterbot[i])>0 ) { printf( "C$ 0 %d %d \"%s\"\n", x-i*2*dx*mmscale,(ycenterrescale+4.36)*mmscale,acenterbot[i]);fflush(stdout) } } } function drawpanel(i) { printf( "F 0 %d\n", 723967 );fflush(stdout); printf( "FR 0 0 0 10000 4108\n" );fflush(stdout); printf( "F 0 %d\n", 7829367 );fflush(stdout) printf( "FR 0 106 106 %d %d\n", 10000-106,4108-106 );fflush(stdout) for ( i=0;i<16;i++) { alastsense[i]=-1 }; for ( i=0;i<8;i++) { alastdata[i]=-1 }; for ( i=0;i<2;i++) { alastbotstatus[i]=-1 } for ( i=0;i<10;i++) { alasttopstatus[i]=-1 }; for ( i=0;i<16;i++) { alastaddr[i]=-1 } } function stroct(s,len,i,ret) { len=length(s);ret=0 for (i = 1; i <= len; i++ ) { if ( substr(s,i,1) ~ /[0-7]/ ) { ret *= 8;ret += (0+substr(s,i,1)) } else { return( ret ) } } return( ret ) } function strhex(s,len,i,ret) { len=length(s);ret=0 for (i = 1; i <= len; i++ ) { if ( substr(s,i,1) ~ /[0-9A-Z]/ ) { ret *= 16;ret += hexstr[substr(s,i,1)] } else { return( ret ) } } return( ret ) } function show(pc,instr,unib,lnib,tmp,src,dest) { if ( ( gfverbosestderr == 1 ) && ( pc in acomment ) ) { printf( "%s\n", acomment[pc] )>"/dev/stderr" } instr=mem(pc);unib=int(instr/16);lnib=(instr%16) if ( unib<4 ) { if ( and(lnib,7) == 0 ) { dispop1("NOP",instr) } else if ( instr == 0x02 ) { dispop2("STAX", "[BC]<=A",instr) } else if ( instr == 0x12 ) { dispop2("STAX", "[DE]<=A",instr) } else if ( instr == 0x22 ) { dispop2("SHLD", sprintf( "%3.3o:%3.3o", mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0x32 ) { dispop1("STA",instr) } else if ( instr == 0x09 ) { dispop2("DAD", "BC",instr) } else if ( instr == 0x19 ) { dispop2("DAD", "DE",instr) } else if ( instr == 0x29 ) { dispop2("DAD", "HL",instr) } else if ( instr == 0x39 ) { dispop2("DAD", "SP",instr) } else if ( instr == 0x0A ) { dispop2("LDAX", "B",instr) } else if ( instr == 0x1A ) { dispop2("LDAX", "D",instr) } else if ( instr == 0x2A ) { tmp=mem(pc+2)*256+mem(pc+1) dispop2("LHLD", sprintf( "%3.3o:%3.3o", (tmp%256), int(tmp/256)),instr)} else if ( instr == 0x3A ) { tmp=mem(pc+2)*256+mem(pc+1) dispop1("LDA",instr)} else if ( instr == 0x31 ) { dispop2("LXI", sprintf( "SP %3.3o:%3.3o", mem(pc+1), mem(pc+2)),instr)} else if ( instr == 0x34 ) { dispop2("INR", "[HL]",instr) } else if ( instr == 0x35 ) { dispop2("DCR", "[HL]",instr) } else if ( instr == 0x36 ) { dispop2("MVI", sprintf( "[HL]", mem(pc+1)),instr)} else if ( instr == 0x07 ) { dispop1("RLC",instr) } else if ( instr == 0x17 ) { dispop1("RAL",instr) } else if ( instr == 0x27 ) { dispop1("DAA",instr) } else if ( instr == 0x37 ) { dispop1("STC",instr) } else if ( instr == 0x3E ) { dispop2("MVI", sprintf("A,%3.3o",mem(pc+1)),instr) } else if ( instr == 0x0F ) { dispop1("RRC",instr) } else if ( instr == 0x1F ) { dispop1("RAR",instr) } else if ( instr == 0x2F ) { dispop1("CMA",instr) } else if ( instr == 0x3F ) { dispop1("CMC",instr) } else if ( lnib == 1 ) { dispop2("LXI", sprintf("%2.2s,%3.3o:%3.3o", substr(LXIreg,unib*2+1,2), mem(pc+1),mem(pc+2)),instr) } else if ( lnib == 3 ) { dispop2("INX",sprintf("%2.2s", substr(LXIreg,unib*2+1,2)),instr)} else if ( lnib == 4 ) { dispop2("INR",sprintf("%1.1s", substr(MOVreg,unib*2+1,1)),instr)} else if ( lnib == 12 ) { dispop2("INR",sprintf("%1.1s", substr(MOVreg,unib*2+2,1)),instr)} else if ( lnib == 5 ) { dispop2("DCR",sprintf("%1.1s", substr(MOVreg,unib*2+1,1)),instr)} else if ( lnib == 13 ) { dispop2("DCR",sprintf("%1.1s", substr(MOVreg,unib*2+2,1)),instr)} else if ( lnib == 6 ) { dispop2("MVI",sprintf("%1.1s,%3.3o", substr(MOVreg,unib*2+1,1),mem(pc+1)),instr)} else if ( lnib == 14 ) { dispop2("MVI",sprintf("%1.1s,%3.3o", substr(MOVreg,unib*2+2,1),mem(pc+1)),instr)} else if ( lnib == 0xB ) { dispop2("DCX",sprintf("%2.2s", substr(LXIreg,unib*2+1,2)),instr)} } else if ( unib < 8 ) { #MOV if ( instr == 0x76 ) { dispop1("HLT",instr) } else { dest=substr(MOVreg,int(and(0x38,instr)/8)+1,1); src=substr(MOVreg,and(0x07,instr)+1,1) if ( src == "m" ) { src="M" } if ( dest == "m" ) { dest="M" } dispop2("MOV",sprintf("%s,%s", dest,src),instr) } } else if ( unib == 8 ) { #ADD/#ADC if ( lnib < 8 ) { tmp="ADD" } else { tmp="ADC" } src=substr(MOVreg,and(0x7,instr)+1,1) if ( src == "m" ) { src="M" } dispop2( tmp, src ,instr) } else if ( unib == 9 ) { #SUB/#SBB Questionable BUGBUG src=substr(MOVreg,and(0x7,instr)+1,1) if ( lnib < 8 ) { tmp="SUB" } else { tmp="SBB" } if ( src == "m" ) { src="M" } dispop2( tmp, src ,instr) } else if ( unib == 0xA ) { #ANA/#XRA src=substr(MOVreg,and(0x7,instr)+1,1) if ( lnib < 8 ) { tmp="ANA" } else { tmp="XRA" } if ( src == "m" ) { src="M" } dispop2( tmp, src ,instr) } else if ( unib == 0xB ) { #ORA/#CMPA src=substr(MOVreg,and(0x7,instr)+1,1) if ( lnib < 8 ) { tmp="ORA" } else { tmp="CMP" } if ( src == "m" ) { src="M" } dispop2( tmp, src ,instr) } else if ( instr == 0xC0 ) { dispop1("RNZ",instr) } else if ( instr == 0xC1 ) { dispop2("POP","B",instr) } else if ( instr == 0xC2 ) { dispop2("JNZ",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xC3 ) { dispop2("JMP",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xC4 ) { dispop2("CNZ",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xC5 ) { dispop2("PUSH","B",instr) } else if ( instr == 0xC6 ) { dispop2("ADI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xC7 ) { dispop2("RST","$0",instr) } else if ( instr == 0xC8 ) { dispop1("RZ",instr) } else if ( instr == 0xC9 ) { dispop1("RET",instr) } else if ( instr == 0xCA ) { dispop2("JZ",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xCB ) { dispop2("*JMP",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xCC ) { dispop2("CZ",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xCD ) { dispop2("CALL",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xCE ) { dispop2("ACI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xCF ) { dispop2("RST","$1",instr) } else if ( instr == 0xD0 ) { dispop1("RNC",instr) } else if ( instr == 0xD1 ) { dispop2("POP","D",instr) } else if ( instr == 0xD2 ) { dispop2("JNC",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xD3 ) { dispop2("OUT",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xD4 ) { dispop2("CNC",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xD5 ) { dispop2("PUSH","D",instr) } else if ( instr == 0xD6 ) { dispop2("SUI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xD7 ) { dispop2("RST","$2",instr) } else if ( instr == 0xD8 ) { dispop1("RC",instr) } else if ( instr == 0xD9 ) { dispop1("*RET",instr) } else if ( instr == 0xDA ) { dispop2("JC",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xDB ) { dispop2("IN",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xDC ) { dispop2("CC",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xDD ) { dispop2("*CALL",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xDE ) { dispop2("SBI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xDF ) { dispop2("RST","$3",instr) } else if ( instr == 0xE0 ) { dispop1("RPO",instr) } else if ( instr == 0xE1 ) { dispop2("POP","H",instr) } else if ( instr == 0xE2 ) { dispop2("JPO",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xE3 ) { dispop1("XTHL",instr) } else if ( instr == 0xE4 ) { dispop2("CPO",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xE5 ) { dispop2("PUSH","H",instr) } else if ( instr == 0xE6 ) { dispop2("ANI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xE7 ) { dispop2("RST","$4",instr) } else if ( instr == 0xE8 ) { dispop1("RPE",instr) } else if ( instr == 0xE9 ) { dispop1("PCHL",instr) } else if ( instr == 0xEA ) { dispop2("JPE",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xEB ) { dispop1("XCHG",instr) } else if ( instr == 0xEC ) { dispop2("CPE",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xED ) { dispop2("*CALL",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xEF ) { dispop2("RST","$5",instr) } else if ( instr == 0xF0 ) { dispop1("RP",instr) } else if ( instr == 0xF1 ) { dispop2("POP","PSW",instr) } else if ( instr == 0xF2 ) { dispop2("JP",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xF3 ) { dispop1("DI",instr) } else if ( instr == 0xF4 ) { dispop2("CP",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xF5 ) { dispop2("PUSH","PSW",instr) } else if ( instr == 0xF6 ) { dispop2("ORI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xF7 ) { dispop2("RST","$6",instr) } else if ( instr == 0xF8 ) { dispop1("RM",instr) } else if ( instr == 0xF9 ) { dispop1("SPHL",instr) } else if ( instr == 0xFA ) { dispop2("JM",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xF3 ) { dispop1("EI",instr) } else if ( instr == 0xF4 ) { dispop2("CM",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xFD ) { dispop2("*CALL",sprintf("%3.3o:%3.3o",mem(pc+1),mem(pc+2)),instr) } else if ( instr == 0xFE ) { dispop2("CPI",sprintf("%3.3o",mem(pc+1)),instr) } else if ( instr == 0xFF ) { dispop2("RST","$7",instr) } } function step(instr,unib,lnib,tmp,src,dest) { instr=mem(pc);unib=int(instr/16);lnib=(instr%16) if ( unib<4 ) { if ( and(lnib,7) == 0 ) { pc=and(0xffff,(pc+1)) } #NOP else if ( instr == 0x02 ) { setmem(areg["B"]*256+areg["C"],areg["A"]);pc=and(0xffff,(pc+1)) } #STAX B else if ( instr == 0x12 ) { setmem(areg["D"]*256+areg["E"],areg["A"]);pc=and(0xffff,(pc+1)) } #STAX D else if ( instr == 0x22 ) { tmp=mem(pc+2)*256+mem(pc+1) setmem(tmp,areg["L"]) setmem(and(0xffff,tmp+1),areg["H"]) pc=and(0xffff,(pc+3)) } #SHLD else if ( instr == 0x32 ) { setmem(mem(pc+2)*256+mem(pc+1),areg["A"]);pc=and(0xffff,(pc+3)) } #STA else if ( instr == 0x09 ) { tmp=setflags16("C",areg["H"]*256+areg["L"],areg["H"]*256+areg["L"]+areg["B"]*256+areg["C"]);areg["H"]=int(tmp/256);areg["L"]=(tmp%256);pc=and(0xffff,(pc+1)) } #DAD B else if ( instr == 0x19 ) { tmp=setflags16("C",areg["H"]*256+areg["L"],areg["H"]*256+areg["L"]+areg["D"]*256+areg["E"]);areg["H"]=int(tmp/256);areg["L"]=(tmp%256);pc=and(0xffff,(pc+1)) } #DAD D else if ( instr == 0x29 ) { tmp=areg["H"]*256+areg["L"];tmp=setflags16("C",tmp,tmp*2);areg["H"]=int(tmp/256);areg["L"]=(tmp%256);pc=and(0xffff,(pc+1)) } #DAD H else if ( instr == 0x39 ) { tmp=setflags16("C",areg["H"]*256+areg["L"],areg["H"]*256+areg["L"]+areg["S"]*256+areg["s"]);areg["H"]=int(tmp/256);areg["L"]=(tmp%256);pc=and(0xffff,(pc+1)) } #DAD D else if ( instr == 0x0A ) { areg["A"]=mem(areg["B"]*256+areg["C"]);pc=and(0xffff,(pc+1)) } #LDAX B else if ( instr == 0x1A ) { areg["A"]=mem(areg["D"]*256+areg["E"]);pc=and(0xffff,(pc+1)) } #LDAX D else if ( instr == 0x2A ) { tmp=mem(pc+2)*256+mem(pc+1) areg["L"]=mem(tmp);areg["H"]=mem(and(0xffff,tmp+1));pc=and(0xffff,(pc+3)) } #LHLD else if ( instr == 0x3A ) { areg["A"]=mem(mem(pc+1)+mem(pc+2)*256);pc=and(0xffff,(pc+3)) } #LDA else if ( instr == 0x31 ) { areg["s"]=mem(pc+1);areg["S"]=mem(pc+2);pc=and(0xffff,(pc+3)) } #LXI SP else if ( instr == 0x34 ) { tmp=mem(areg["H"]*256+areg["L"]);tmp=setflags8("SZAP",tmp,tmp+1);setmem(areg["H"]*256+areg["L"],tmp);pc=and(0xffff,(pc+1)) } #INR M else if ( instr == 0x35 ) { tmp=mem(areg["H"]*256+areg["L"]);tmp=setflags8("SZAP",tmp,tmp+0xff);setmem(areg["H"]*256+areg["L"],tmp);pc=and(0xffff,(pc+1)) } #DCR M else if ( instr == 0x36 ) { setmem(areg["H"]*256+areg["L"],mem(pc+1));pc=and(0xffff,(pc+2)) } #MVI M else if ( instr == 0x07 ) { tmp=areg["A"] aflags["C"]=int(tmp/128) areg["A"]=and(0xff,tmp*2)+int(tmp/128) pc=and(0xffff,(pc+1)) } #RLC else if ( instr == 0x17 ) { tmp=areg["A"] tmp=aflags["C"] aflags["C"]=int(areg["A"]/128) areg["A"]=and(0xff,(areg["A"]*2+tmp)) pc=and(0xffff,(pc+1)) } #RAL else if ( instr == 0x27 ) { #Guaranteed wrong implementation #DAA lnib=and(0xf,areg["A"]) unib=int(areg["A"]/256) if ( ( lnib > 9 ) || aflags["A"] ) { lnib += 6 } aflags["A"]=0 if ( lnib > 15) { unib++;lnib=(lnib%16) } if ( ( unib > 9 ) || aflags["C"] ) { unib += 6 } aflags["C"]=0 if ( unib > 15) { aflags["C"]=1;unib=(unib%16) } areg["A"]=unib*16+lnib pc=and(0xffff,(pc+1)) } #DAA else if ( instr == 0x37 ) { aflags["C"]=1;pc=and(0xffff,(pc+1)) } #STC else if ( instr == 0x3E ) { areg["A"]=mem(pc+1);pc=and(0xffff,(pc+2)) } #MVI A else if ( instr == 0x0F ) { aflags["C"]=(areg["A"]%2) areg["A"]=or(int(areg["A"]/2),aflags["C"]*128) pc=and(0xffff,(pc+1)) } #RRC else if ( instr == 0x1F ) { tmp=aflags["C"]*128 aflags["C"]=(areg["A"]%2) areg["A"]=or(tmp,int(areg["A"]/2)) pc=and(0xffff,(pc+1)) } #RAR else if ( instr == 0x2F ) { areg["A"]=(0xff-areg["A"]);pc=and(0xffff,(pc+1)) } #CMA else if ( instr == 0x3F ) { if ( aflags["C"] == 0 ) { aflags["C"]=1 } else { aflags["C"]=0 };pc=and(0xffff,(pc+1)) } #CMC else if ( lnib == 1 ) { movcr(mem(pc+2),substr(LXIreg,unib*2+1,1));movcr(mem(pc+1),substr(LXIreg,unib*2+2,1));pc=and(0xffff,(pc+3)) } #LXI else if ( lnib == 3 ) { tmp=and(0xffff,areg[substr(LXIreg,unib*2+1,1)]*256+areg[substr(LXIreg,unib*2+2,1)]+1) #INX areg[substr(LXIreg,unib*2+1,1)]=int(tmp/256);areg[substr(LXIreg,unib*2+2,1)]=(tmp%256);pc=and(0xffff,(pc+1)) } #INX else if ( lnib == 4 ) { tmp=areg[substr(MOVreg,unib*2+1,1)];areg[substr(MOVreg,unib*2+1,1)]=setflags8("SZAP",tmp,tmp+1);pc=and(0xffff,(pc+1)) } #INR else if ( lnib == 12 ) { tmp=areg[substr(MOVreg,unib*2+2,1)];areg[substr(MOVreg,unib*2+2,1)]=setflags8("SZAP",tmp,tmp+1);pc=and(0xffff,(pc+1)) } #INR else if ( lnib == 5 ) { tmp=areg[substr(MOVreg,unib*2+1,1)];areg[substr(MOVreg,unib*2+1,1)]=setflags8("SZAP",tmp,tmp+0xff);pc=and(0xffff,(pc+1)) } #DCR else if ( lnib == 13 ) { tmp=areg[substr(MOVreg,unib*2+2,1)];areg[substr(MOVreg,unib*2+2,1)]=setflags8("SZAP",tmp,tmp+0xff);pc=and(0xffff,(pc+1)) } #DCR else if ( lnib == 6 ) { areg[substr(MOVreg,unib*2+1,1)]=mem(pc+1);pc=and(0xffff,(pc+2)) } #MVI else if ( lnib == 14 ) { areg[substr(MOVreg,unib*2+2,1)]=mem(pc+1);pc=and(0xffff,(pc+2)) } #MVI else if ( lnib == 0xB ) { tmp=and(0xffff,areg[substr(LXIreg,unib*2+1,1)]*256+areg[substr(LXIreg,unib*2+2,1)]+0xffff) #DCX areg[substr(LXIreg,unib*2+1,1)]=int(tmp/256);areg[substr(LXIreg,unib*2+2,1)]=(tmp%256);pc=and(0xffff,(pc+1)) } #DCX } else if ( unib < 8 ) { #MOV if ( instr == 0x76 ) { pc=and(0xffff,(pc+1)) } #HLT fexecution=0 removed for testing else { dest=substr(MOVreg,int(and(0x38,instr)/8)+1,1); src=substr(MOVreg,and(0x07,instr)+1,1) if ( src == "m" ) { tmp=mem(areg["H"]*256+areg["L"]) } else { tmp=areg[src] } if ( dest == "m" ) { setmem(areg["H"]*256+areg["L"],tmp) } else { areg[dest]=tmp } pc=and(0xffff,(pc+1)) } } else if ( unib == 8 ) { #ADD/#ADC if ( lnib < 8 ) { tmp=0 } else { tmp=aflags["C"] } src=substr(MOVreg,and(0x7,instr)+1,1) if ( src == "m" ) { areg["A"]=setflags8("SZAPC",areg["A"],areg["A"]+mem(areg["H"]*256+areg["L"])+tmp);pc=and(0xffff,(pc+1)) } else { areg["A"]=setflags8("SZAPC",areg["A"],areg["A"]+areg[substr(MOVreg,and(0x07,instr)+1,1)]+tmp);pc=and(0xffff,(pc+1)) } } else if ( unib == 9 ) { #SUB/#SBB Questionable BUGBUG if ( lnib < 8 ) { tmp=1 } else { tmp=((1+aflags["C"])%2) } #invert bit trick src=substr(MOVreg,and(0x7,instr)+1,1) if ( src == "m" ) { areg["A"]=setflags8("SZAP-",areg["A"],areg["A"]+(0xff-mem(areg["H"]*256+areg["L"]))+tmp);pc=and(0xffff,(pc+1)) } else { areg["A"]=setflags8("SZAP-",areg["A"],areg["A"]+(0xff-areg[substr(MOVreg,and(0x07,instr)+1,1)])+tmp);pc=and(0xffff,(pc+1)) } } else if ( unib == 0xA ) { #ANA/#XRA src=substr(MOVreg,and(0x7,instr)+1,1) if ( lnib < 8 ) { #ANA if ( src == "m" ) { areg["A"]=setflags8("SZAPC",areg["A"],and(areg["A"],mem(areg["H"]*256+areg["L"]))) } else { areg["A"]=setflags8("SZAPC",areg["A"],and(areg["A"],areg[substr(MOVreg,and(0x07,instr)+1,1)])) } } else { #XRA if ( src == "m" ) { a = areg["A"];b=mem(areg["H"]*256+areg["L"]) } else { a=areg["A"];b=areg[substr(MOVreg,and(0x07,instr)+1,1)] } areg["A"]=setflags8("SZAPC",a,or(safeand(a,(0xff-b)),safeand((0xff-a),b))) } pc=and(0xffff,(pc+1)) } else if ( unib == 0xB ) { #ORA/#CMPA src=substr(MOVreg,and(0x7,instr)+1,1) if ( lnib < 8 ) { #ORA if ( src == "m" ) { areg["A"]=setflags8("SZAPC",areg["A"],or(areg["A"],mem(areg["H"]*256+areg["L"]))) } else { areg["A"]=setflags8("SZAPC",areg["A"],or(areg["A"],areg[substr(MOVreg,and(0x07,instr)+1,1)])) } } else { #CMPA Probably wrong BUGBUG if ( src == "m" ) { tmp = mem(areg["H"]*256+areg["L"]) } else { tmp=areg[substr(MOVreg,and(0x07,instr)+1,1)] } setflags8("SZAP-",areg["A"],(areg["A"]+(0xff-tmp)+1)) } pc=and(0xffff,(pc+1)) } else if ( instr == 0xC0 ) { if ( aflags["Z"] == 0 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RNZ } else if ( instr == 0xC1 ) { popreg("C");popreg("B");pc=and(0xffff,(pc+1)) #POP B } else if ( instr == 0xC2 ) { if ( aflags["Z"] == 0 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JNZ } else if ( instr == 0xC3 ) { jmp8080() #JMP } else if ( instr == 0xC4 ) { if ( aflags["Z"] == 0 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CNZ } else if ( instr == 0xC5 ) { pushreg("B");pushreg("C");pc=and(0xffff,(pc+1)) #PUSH B } else if ( instr == 0xC6 ) { areg["A"]=setflags8("SZAPC",areg["A"],areg["A"]+mem(pc+1));pc=and(0xffff,(pc+2)) #ADI } else if ( instr == 0xC7 ) { rst8080(0) #RST 0 } else if ( instr == 0xC8 ) { if ( aflags["Z"] == 1 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RZ } else if ( instr == 0xC9 ) { return8080() #RET } else if ( instr == 0xCA ) { if ( aflags["Z"] == 1 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JZ } else if ( instr == 0xCB ) { jmp8080() #*JMP } else if ( instr == 0xCC ) { if ( aflags["Z"] == 1 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CZ } else if ( instr == 0xCD ) { call8080(mem(pc+2)*256+mem(pc+1)) #CALL } else if ( instr == 0xCE ) { areg["A"]=setflags8("SZAPC",areg["A"],areg["A"]+mem(pc+1)+aflags["C"]);pc=and(0xffff,(pc+2)) #ADI } else if ( instr == 0xCF ) { rst8080(1) #RST 1 } else if ( instr == 0xD0 ) { if ( aflags["C"] == 0 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RNC } else if ( instr == 0xD1 ) { popreg("E");popreg("D");pc=and(0xffff,(pc+1)) #POP D } else if ( instr == 0xD2 ) { if ( aflags["C"] == 0 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } } else if ( instr == 0xD3 ) { out8080(mem(pc+1));pc=and(0xffff,(pc+2)) } else if ( instr == 0xD4 ) { if ( aflags["C"] == 0 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CNC } else if ( instr == 0xD5 ) { pushreg("D");pushreg("E");pc=and(0xffff,(pc+1)) #PUSH D } else if ( instr == 0xD6 ) { areg["A"]=setflags8("SZAP-",areg["A"],areg["A"]+(0xff-mem(pc+1))+1);pc=and(0xffff,(pc+2)) #SUI } else if ( instr == 0xD7 ) { rst8080(2) #RST 2 } else if ( instr == 0xD8 ) { if ( aflags["C"] == 1 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RC } else if ( instr == 0xD9 ) { return8080() #RET* } else if ( instr == 0xDA ) { if ( aflags["C"] == 1 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JC } else if ( instr == 0xDB ) { in8080(mem(pc+1)); pc=and(0xffff,(pc+2)) #IN D8 } else if ( instr == 0xDC ) { if ( aflags["C"] == 1 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CC } else if ( instr == 0xDD ) { call8080(mem(pc+2)*256+mem(pc+1)) #*CALL } else if ( instr == 0xDE ) { areg["A"]=setflags8("SZAP-",areg["A"],areg["A"]+(0xff-mem(pc+1))+((1+aflags["C"])%2));pc=and(0xffff,(pc+2)) #SBI invert bit trick } else if ( instr == 0xDF ) { rst8080(3) #RST 3 } else if ( instr == 0xE0 ) { if ( aflags["P"] == 0 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RPO } else if ( instr == 0xE1 ) { popreg("L");popreg("H");pc=and(0xffff,(pc+1)) #POP D } else if ( instr == 0xE2 ) { if ( aflags["P"] == 0 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JPO } else if ( instr == 0xE3 ) { sp=areg["S"]*256+areg["s"] tmp=areg["L"] areg["L"]=mem(sp) setmem(sp,tmp) sp=and(0xffff,sp+1) tmp=areg["H"] areg["H"]=mem(sp) setmem(sp,tmp) pc=and(0xffff,(pc+1)) #XTHL } else if ( instr == 0xE4 ) { if ( aflags["P"] == 0 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CPO } else if ( instr == 0xE5 ) { pushreg("H");pushreg("L");pc=and(0xffff,(pc+1)) #PUSH H } else if ( instr == 0xE6 ) { areg["A"]=setflags8("SZAPC",areg["A"],and(areg["A"],mem(pc+1)));pc=and(0xffff,(pc+2)) #ANI } else if ( instr == 0xE7 ) { rst8080(4) #RST 4 } else if ( instr == 0xE8 ) { if ( aflags["P"] == 1 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RPE } else if ( instr == 0xE9 ) { pc=areg["H"]*256+areg["L"] #PCHL } else if ( instr == 0xEA ) { if ( aflags["P"] == 1 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JPE } else if ( instr == 0xEB ) { tmp=areg["L"];areg["L"]=areg["E"];areg["E"]=tmp;tmp=areg["H"];areg["H"]=areg["D"];areg["D"]=tmp;pc=and(0xffff,(pc+1)) #XCHG } else if ( instr == 0xEC ) { if ( aflags["P"] == 1 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CPE } else if ( instr == 0xED ) { call8080(mem(pc+2)*256+mem(pc+1)) #*CALL } else if ( instr == 0xEE ) { a=areg["A"];b=mem(pc+1);areg["A"]=setflags8("SZAPC",a,or(safeand(a,(0xff-b)),safeand((0xff-a),b)));pc=and(0xffff,(pc+2)) #XRI } else if ( instr == 0xEF ) { rst8080(5) #RST 5 } else if ( instr == 0xF0 ) { if ( aflags["S"] == 0 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RP } else if ( instr == 0xF1 ) { popflagsandA();pc=and(0xffff,(pc+1)) #POP PSW } else if ( instr == 0xF2 ) { if ( aflags["S"] == 0 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JP } else if ( instr == 0xF3 ) { finterrupts=0; pc=and(0xffff,(pc+1)) #DI } else if ( instr == 0xF4 ) { if ( aflags["S"] == 0 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CP } else if ( instr == 0xF5 ) { pushflagsandA();pc=and(0xffff,(pc+1)) #PUSH PSW } else if ( instr == 0xF6 ) { areg["A"]=setflags8("SZAPC",areg["A"],or(areg["A"],mem(pc+1)));pc=and(0xffff,(pc+2)) #ORI } else if ( instr == 0xF7 ) { rst8080(6) #RST 6 } else if ( instr == 0xF8 ) { if ( aflags["S"] == 1 ) { return8080() } else { pc=and(0xffff,(pc+1)) } #RM } else if ( instr == 0xF9 ) { areg["S"]=areg["H"];areg["s"]=areg["L"];pc=and(0xffff,(pc+1)) #SPHL } else if ( instr == 0xFA ) { if ( aflags["S"] == 1 ) { jmp8080() } else { pc=and(0xffff,(pc+3)) } #JM } else if ( instr == 0xFB ) { finterrupts=1; pc=and(0xffff,(pc+1)) #EI } else if ( instr == 0xFC ) { if ( aflags["S"] == 1 ) { call8080(mem(pc+2)*256+mem(pc+1)) } else { pc=and(0xffff,(pc+3)) } #CM } else if ( instr == 0xFD ) { call8080(mem(pc+2)*256+mem(pc+1)) #*CALL } else if ( instr == 0xFE ) { setflags8("SZAP-",areg["A"],areg["A"]+(0xff-mem(pc+1))+1);pc=and(0xffff,(pc+2)) #CPI } else if ( instr == 0xFF ) { rst8080(7) #RST 7 } else { printf( "PANIC:%3.3o %2.2x not yet implemented\n", instr, instr ) >"/dev/stderr" pc=and(0xffff,(pc+1)) #Probably not implemented yet } pc = and( 0xffff,pc) if (pc in breakpoints) {fexecution=0} } function movcr(const,reg) { areg[reg]=and(255,const) } function movrr(reg1,reg2) { areg[reg2]=and(255,areg[reg1]) } function setflags16(flagstr,preval,postval,len,i,flag,p,ip) { len=length(flagstr) if ( postval < 0 ) { postval=0x100000+postval } for ( i = 1; i <= len; i++ ) { flag=substr(flagstr,i,1) if ( flag == "S" ) { if ( and(0x8000,postval) != 0 ) { aflags["S"]=1 } else { aflags["S"]=0 } } if ( flag == "C" ) { if ( and(0x10000,postval) != 0 ) { aflags["C"]=1 } else { aflags["C"]=0 } } else if ( flag == "Z" ) { if ( postval == 0 ) { aflags["Z"]=1 } else { aflags["Z"]=0 } } else if ( flag == "P" ) { p=0; for ( ip = 1; ip <= 65536; ip *= 2 ) { if ( and(ip,postval) ) { p++ } } if ( (p%2)==0 ) { aflags["P"]=1 } else { aflags["P"]=0 } } } return( and(0xffff,postval) ) } function setflags8(flagstr,preval,postval,len,i,flag,p,ip) { len=length(flagstr) if ( postval < 0 ) { postval=0x1000+postval } for ( i = 1; i <= len; i++ ) { flag=substr(flagstr,i,1) if ( flag == "S" ) { if ( and(0x80,postval) != 0 ) { aflags["S"]=1 } else { aflags["S"]=0 } } if ( flag == "A" ) { if ( and(0x10,postval) != and(0x10,preval) ) { aflags["A"]=1 } else { aflags["A"]=0 } } if ( flag == "C" ) { if ( and(0x100,postval) != 0 ) { aflags["C"]=1 } else { aflags["C"]=0 } } else if ( flag == "-" ) { if ( and(0x100,postval) != 0 ) { aflags["C"]=0 } else { aflags["C"]=1 } } else if ( flag == "Z" ) { if ( and(0xff,postval) == 0 ) { aflags["Z"]=1 } else { aflags["Z"]=0 } } else if ( flag == "P" ) { p=0; for ( ip = 1; ip <= 65536; ip *= 2 ) { if ( and(ip,postval) ) { p++ } } if ( (p%2)==0 ) { aflags["P"]=1 } else { aflags["P"]=0 } } } return( and(0xff,postval) ) } function popflagsandA(sp,tmp) { sp=areg["S"]*256+areg["s"] tmp=mem(sp) aflags["C"]=(tmp%2);tmp=int(tmp/4) aflags["P"]=(tmp%2);tmp=int(tmp/4) aflags["A"]=(tmp%2);tmp=int(tmp/4) aflags["Z"]=(tmp%2);tmp=int(tmp/2) aflags["S"]=(tmp%2) sp=and(0xffff,sp+1) areg["A"]=mem(sp) sp=and(0xffff,sp+1) areg["S"]=int(sp/256);areg["s"]=(sp%256) } function pushflagsandA(sp,tmp) { sp=areg["S"]*256+areg["s"] sp=safeand(0xffff,sp-1) setmem(sp,areg["A"]) tmp=aflags["S"];tmp*=2 tmp+=aflags["Z"];tmp*=4 tmp+=aflags["A"];tmp*=4 tmp+=aflags["P"];tmp*=2 tmp+=1;tmp*=2 tmp+=aflags["C"] sp=safeand(0xffff,sp-1) setmem(sp,tmp) areg["S"]=int(sp/256);areg["s"]=(sp%256) } function popreg(reg,sp) { sp=areg["S"]*256+areg["s"] areg[reg]=mem(sp) sp=safeand(0xffff,sp+1) areg["S"]=int(sp/256); areg["s"]=(sp%256) } function pushreg(reg,sp) { sp=areg["S"]*256+areg["s"] sp=safeand(0xffff,sp-1) setmem(sp,areg[reg]) areg["S"]=int(sp/256); areg["s"]=(sp%256) } function return8080(sp) { sp=areg["S"]*256+areg["s"] pc = mem(sp) sp=safeand(0xffff,sp+1) pc=and(0xffff,(pc+mem(sp)*256)) sp=safeand(0xffff,sp+1) areg["S"]=int(sp/256); areg["s"]=(sp%256) } function in8080(port,ch) { if ( port == 0 ) { if ( gfcharprinted == 0 ) { areg["A"]=0x00 #This means the 88-SIO has an empty output buffer. if ( length( ginputbuffer ) == 0 ) { areg["A"]=or(0x1,areg["A"]) #There are no characters waiting to be read. } } else { areg["A"]=0x80 #This means the 88-2SIO is busy, simulate non-instantaneous output? if ( length( ginputbuffer ) == 0 ) { areg["A"]=or(0x1,areg["A"]) #There are no characters waiting to be read. } gfcharprinted=0 #and next time say it's ready. } } else if ( ( port == 022 ) || ( port == 020 ) ) { if ( gfcharprinted == 0 ) { areg["A"]=2 #This means the 88-2SIO has an empty output buffer. if ( length( ginputbuffer ) > 0 ) { areg["A"]=or(0x1,areg["A"]) #There is a character waiting to be read. } } else { areg["A"]=0 #This means the 88-2SIO is busy, simulate non-instantaneous output? gfcharprinted=0 #and next time say it's ready. } } else if ( port == 1 ) { if ( length( ginputbuffer ) > 0 ) { ch=asc[substr(ginputbuffer,1,1)] if ( ch == 0177 ) { ch=0377 } areg["A"]=ch ginputbuffer=substr(ginputbuffer,2) } else { areg["A"]=000 } #printf( "Z \n" );fflush(stdout) } else if ( ( port == 023 ) || ( port == 021 ) ) { if ( length( ginputbuffer ) > 0 ) { ch=asc[substr(ginputbuffer,1,1)] if ( ch == 0177 ) { ch=0377 } areg["A"]=ch ginputbuffer=substr(ginputbuffer,2) printf( "Z \n" );fflush(stdout) } else { areg["A"]=000 } } else if ( port == 0xff ) { areg["A"]=(ipc%256) #front panel switches #printf( "Z \n" );fflush(stdout) } } function out8080(port,ch) { if ( ( port == 021 ) || ( port == 023 ) || ( port == 1 ) ) { ch=areg["A"] if ( ch == 10 ) { gychar++ gxchar=0 if ( gfttystderr == 1 ) { printf( "%c", and(0x7f,ch) )>"/dev/stderr" } } else if ( ch == 13 ) { gxchar=0 if ( gfttystderr == 1 ) { printf( "%c", and(0x7f,ch) )>"/dev/stderr" } } else if ( ch == 12 ) { gxchar=0;gychar=0 drawpaper() printf( "Z \n" );fflush(stdout) } else if ( ch >= 32 ) { if ( int(0.6*gxchar*3*mmscale)+x1paper > x2paper ) { gxchar=0;gychar++ } if ( gychar*3*mmscale+y1paper > y2paper ) { gxchar=0;gychar=0 drawpaper() } printf( "L$ 3 %d %d \"%c\"\n", int(0.6*gxchar*3*mmscale)+x1paper, (gychar+1)*3*mmscale+y1paper, and(0x7f,ch) ) printf( "Z \n" );fflush(stdout) gxchar++ if ( gfttystderr == 1 ) { printf( "%c", and(0x7f,ch) )>"/dev/stderr" } } gfcharprinted=1 #This should really delay by baud rate? } } function jmp8080(addr) { addr=mem(pc+2)*256+mem(pc+1) pc=addr } function rst8080(vector,sp) { pc=and(0xffff,(pc+1)) sp=areg["S"]*256+areg["s"] sp -= 2 setmem(sp,(pc%256)) setmem(sp+1,int(pc/256)) areg["S"]=int(sp/256); areg["s"]=(sp%256) pc=vector*8 } function call8080(addr,sp) { pc=and(0xffff,(pc+3)) sp=areg["S"]*256+areg["s"] sp=safeand(0xffff,sp-1) setmem(sp,int(pc/256)) sp=safeand(0xffff,sp-1) setmem(sp,(pc%256)) areg["S"]=int(sp/256); areg["s"]=(sp%256) pc=and(0xffff,addr) } function colon(upper,lower) { return( upper*256+lower ) } function mem(addr) { if ( ( addr >= 0 ) && ( addr < MAX_MEMORY ) ) { return(abytes[addr]) } else { return(int(rand()*256)) } } function setmem(addr,val) { if ( ( addr >= 0 ) && ( addr < MAX_MEMORY ) ) { abytes[addr]=and(0xff,val) } } function safeand(a,b) { if ( b < 0 ) { b=65536+b } return( and(a,b) ) } function clickrun() { fexecution=1 step() drawdataLEDs(mem(pc)) drawaddressLEDs(pc) drawregisters() }