1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-26 06:29:29 +00:00

Deploying to gh-pages from @ sehugg/8bitworkshop@5a93bc8b75 🚀

This commit is contained in:
sehugg 2023-07-08 20:12:17 +00:00
parent d1024c06c6
commit 784ec76080
36 changed files with 492 additions and 87 deletions

View File

@ -0,0 +1,7 @@
import{I as z,h as W,k as N,p as F,t as H}from"./chunk-HB3LWF25.js";import{$ as I,J as B,U as M,V as f,W as O,Y as U,_ as E,da as _,g}from"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";var d=0,L=2,P=8,X=U([[f.A,P+0,128],[f.B,P+1,128],[f.SELECT,L,-2],[f.START,L,-1],[f.UP,d,-16],[f.DOWN,d,-32],[f.LEFT,d,-64],[f.RIGHT,d,-128],[f.P2_A,P+2,128],[f.P2_B,P+3,128],[f.P2_UP,d,-1],[f.P2_DOWN,d,-2],[f.P2_LEFT,d,-4],[f.P2_RIGHT,d,-8]]);var D=263,K=258-16,b=451,j=28,q=16,J=24,Y=2,$=D*60*Y,T=class{constructor(){this.regs=new Uint8Array(32)}reset(){this.regs.fill(0)}read(t){return this.regs[t]|0}write(t,e){this.regs[t]=e}saveState(){return{regs:this.regs.slice(0)}}loadState(t){for(let e=0;e<32;e++)this.write(e,t.regs[e])}static stateToLongString(t){let e="";return e+=M(t.regs,0,32),e}},k=class{constructor(){this.cycles=0;this.regs=new Uint8Array(32);this.offset=-1;this.dll=0;this.dlstart=0;this.dli=!1;this.h16=!1;this.h8=!1;this.indirect=!1;this.pixels=new Uint8Array(320);this.WSYNC=0}reset(){this.regs.fill(0)}read(t){return this.regs[t]|0}write(t,e){this.regs[t]=e,t==4&&this.WSYNC++}saveState(){return{regs:this.regs.slice(0),offset:this.offset,dll:this.dll,dlstart:this.dlstart,dli:this.dli,h16:this.h16,h8:this.h8,indirect:this.indirect}}loadState(t){for(let e=0;e<32;e++)this.write(e,t.regs[e]|0);this.offset=t.offset|0,this.dll=t.dll|0,this.dlstart=t.dlstart|0,this.dli=!!t.dli,this.h16=!!t.h16,this.h8=!!t.h8,this.indirect=!!t.indirect}isDMAEnabled(){return(this.regs[28]&96)==64}getDLLStart(){return(this.regs[12]<<8)+this.regs[16]}getCharBaseAddress(){return(this.regs[20]<<8)+this.offset}setVBLANK(t){t?(this.regs[8]|=128,this.offset=-1,this.dll=this.getDLLStart(),this.dli=this.bus&&(this.bus.read(this.dll)&128)!=0):this.regs[8]&=~128}readDLLEntry(t){if(this.dll>=16384)return;let e=t.read(this.dll);this.offset=e&15,this.h16=(e&64)!=0,this.h8=(e&32)!=0,this.dlstart=(t.read(this.dll+1)<<8)+t.read(this.dll+2),this.dll=this.dll+3&65535,this.dli=(t.read(this.dll)&128)!=0}isHoley(t){return this.indirect?!1:!!(t&32768&&(this.h16&&t&4096||this.h8&&t&2048))}readDMA(t){return this.isHoley(t)?0:(this.cycles+=3,this.bus.read(t))}doDMA(t){if(this.bus=t,this.cycles=0,this.pixels.fill(this.regs[0]),this.isDMAEnabled()){this.cycles+=this.offset==0?J:q,this.offset<0&&this.readDLLEntry(t);let i=this.dlstart&65280,h=this.dlstart&255;do{let n=t.read(i+(h+0&511)),c=t.read(i+(h+1&511));if(c==0||i>=16384)break;let A=t.read(i+(h+2&511)),m=t.read(i+(h+3&511)),x=!1;if((c&31)==0){var e=m>>5,a=32-(m&31),r=t.read(i+(h+4&511)),s=c&128;x=(c&32)!=0,h+=5,this.cycles+=10}else{var r=m,e=c>>5,a=32-(c&31),s=0;h+=4,this.cycles+=8}this.indirect=x;let v=n+((A+(x?0:this.offset)&255)<<8);r*=2;let C=(this.regs[28]&3)+(s?4:0),y=x&&(this.regs[28]&16)!=0;y&&(a*=2);for(var o=0;o<a;o++){let p=this.readDMA(y?v+(o>>1):v+o);if(x){let u=(this.regs[20]+this.offset<<8)+p;y&&o&1&&(u++,this.cycles-=3),p=this.readDMA(u)}switch(C){case 0:for(let u=0;u<4;u++){var l=p>>6&3;l>0&&(this.pixels[r]=this.pixels[r+1]=this.regs[(e<<2)+l]),p<<=2,r=r+2&511}break;case 2:case 3:for(let u=0;u<8;u++){var l=p&128?1:0;l>0&&(this.pixels[r]=this.regs[(e<<2)+l]),p<<=1,r=r+1&511}break}}}while(this.cycles<b);this.offset-=1}return this.cycles}doInterrupt(){return this.dli&&this.offset<0?(this.dli=!1,!0):!1}static stateToLongString(t){let e="";return e+=M(t.regs,0,32),e+=`
DLL: $`+g((t.regs[12]<<8)+t.regs[16],4)+" @ $"+g(t.dll,4),e+=`
DL: $`+g(t.dlstart,4),e+=`
Offset: `+t.offset,e+=`
DLI? `+t.dli,e}},R=class extends F{constructor(){super();this.cpuFrequency=1789772;this.canvasWidth=320;this.numTotalScanlines=D;this.numVisibleScanlines=K;this.defaultROMSize=49152;this.cpuCyclesPerLine=113.5;this.sampleRate=$;this.ram=new Uint8Array(4096);this.regs6532=new Uint8Array(4);this.piatimer=0;this.timerinterval=1;this.tia=new T;this.maria=new k;this.lastFrameCycles=0;this.xtracyc=0;this.cpu=new H,this.read=I([[8,13,15,t=>(this.xtracyc++,this.readInput(t))],[0,31,31,t=>(this.xtracyc++,this.tia.read(t))],[32,63,31,t=>this.maria.read(t)],[64,255,255,t=>this.ram[t+2048]],[256,319,255,t=>this.read(t)],[320,511,511,t=>this.ram[t+2048]],[640,767,127,t=>(this.xtracyc++,this.readPIA(t))],[6144,10239,65535,t=>this.ram[t-6144]],[10240,16383,2047,t=>this.read(t|8192)],[16384,65535,65535,t=>this.rom?this.rom[t-16384]:0],[0,65535,65535,t=>this.probe&&this.probe.logIllegal(t)]]),this.write=I([[21,26,31,(t,e)=>{this.xtracyc++,this.pokey1.setTIARegister(t,e)}],[0,31,31,(t,e)=>{this.xtracyc++,this.tia.write(t,e)}],[32,63,31,(t,e)=>{this.maria.write(t,e)}],[64,255,255,(t,e)=>{this.ram[t+2048]=e}],[256,319,255,(t,e)=>{this.write(t,e)}],[320,511,511,(t,e)=>{this.ram[t+2048]=e}],[640,767,127,(t,e)=>{this.xtracyc++,this.writePIA(t,e)}],[6144,10239,65535,(t,e)=>{this.ram[t-6144]=e}],[10240,16383,2047,(t,e)=>{this.write(t|8192,e)}],[49151,49151,65535,(t,e)=>{}],[0,65535,65535,(t,e)=>{this.probe&&this.probe.logIllegal(t)}]]),this.connectCPUMemoryBus(this),this.dmaBus=this.probeDMABus(this),this.handler=O(this.inputs,X),this.pokey1=new W,this.audioadapter=new N(this.pokey1,Y,$)}readConst(t){let e=this.probe;this.probe=null;let a=this.read(t);return this.probe=e,a}readInput(t){switch(t){case 12:return~this.inputs[8]&128;case 13:return~this.inputs[9]&128;default:return this.inputs[t]|0}}readPIA(t){switch(t){case 0:case 2:return this.inputs[t];case 1:case 3:return this.regs6532[t];case 4:return this.getPIATimerValue();default:return 0}}writePIA(t,e){switch(t){case 0:case 1:case 2:case 3:this.regs6532[t]=e;return;case 20:this.setPIATimer(e,0);return;case 21:this.setPIATimer(e,3);return;case 22:this.setPIATimer(e,6);return;case 23:this.setPIATimer(e,10);return;case 24:this.setPIATimer(e,6);return}}setPIATimer(t,e){this.piatimer=t+1<<e,this.timerinterval=e}getPIATimerValue(){let t=this.piatimer;return t>0?t>>this.timerinterval:t&255}advanceCPU(){var t=super.advanceCPU();return this.tickPIATimer(t),this.xtracyc&&(t+=this.xtracyc,this.tickClocks(this.xtracyc),this.xtracyc=0),t}tickClocks(t){this.probe.logClocks(t),this.tickPIATimer(t)}tickPIATimer(t){this.piatimer=Math.max(-256,this.piatimer-t)}advanceFrame(t){var e=this.pixels,a=0,r,s=0,o=0,l=0;this.probe.logNewFrame();for(var i=0;i<D;i++){this.scanline=i;var h=i<K;for(this.maria.setVBLANK(!h),this.maria.WSYNC=0;s<j&&!this.maria.WSYNC;){if(t&&t()){t=null,i=999;break}s+=this.advanceCPU()<<2,l++}if(h){let c=this.maria.doDMA(this.dmaBus);if(this.tickClocks(c>>2),s+=c,e)for(var n=0;n<320;n++)e[a++]=V[this.maria.pixels[n]]}for((h||i==D-1)&&this.maria.doInterrupt()&&(this.probe.logInterrupt(0),this.cpu.NMI());s<b;){if(this.maria.WSYNC){this.probe.logWait(0),this.tickClocks(b-s>>2),s=b;break}if(t&&t()){t=null,i=999;break}s+=this.advanceCPU()<<2,l++}this.audio&&this.audioadapter.generate(this.audio),s-=b,o+=s,this.probe.logNewScanline()}return this.lastFrameCycles=o,l}getRasterX(){return this.lastFrameCycles%b}getRasterY(){return this.scanline}loadROM(t){t.length==49280&&(t=t.slice(128)),this.rom=E(t,this.defaultROMSize,!0)}reset(){super.reset(),this.tia.reset(),this.maria.reset(),this.inputs.fill(0),this.inputs[d]=255,this.inputs[L]=1+2+8}readAddress(t){return this.read(t)|0}loadState(t){this.cpu.loadState(t.c),this.ram.set(t.ram),this.tia.loadState(t.tia),this.maria.loadState(t.maria),this.regs6532.set(t.regs6532),this.piatimer=t.pia.timer,this.timerinterval=t.pia.interval,this.loadControlsState(t)}saveState(){return{c:this.cpu.saveState(),ram:this.ram.slice(0),tia:this.tia.saveState(),maria:this.maria.saveState(),regs6532:this.regs6532.slice(0),inputs:this.inputs.slice(0),pia:{timer:this.piatimer,interval:this.timerinterval}}}loadControlsState(t){this.inputs.set(t.inputs)}saveControlsState(){return{inputs:this.inputs.slice(0)}}getDebugCategories(){return["CPU","Stack","TIA","MARIA"]}getDebugInfo(t,e){switch(t){case"TIA":return T.stateToLongString(e.tia);case"MARIA":return k.stateToLongString(e.maria)+`
Scanline: `+this.scanline}}getDebugDisplayLists(){let t={},e=this.maria.getDLLStart(),a=0;for(;a<240;){let r=this.readConst(e),s=r&15,o=(r&64)!=0,l=(r&32)!=0,i=(this.readConst(e+1)<<8)+this.readConst(e+2);e=e+3&65535;let h=(this.readConst(e)&128)!=0,n="DL $"+g(i,4)+" "+a+"-"+(a+s);o&&(n+=" H16"),l&&(n+=" H8"),h&&(n+=" DLI"),t[n]={$$:this._readDebugDisplayList(i)},a+=s+1}return t}_readDebugDisplayList(t){return()=>this.readDebugDisplayList(t)}readDebugDisplayList(t){let e=[],a=t&65280,r=t&255;do{let h=this.readConst(a+(r+0&511)),n=this.readConst(a+(r+1&511));if(n==0)break;let c=this.readConst(a+(r+2&511)),A=this.readConst(a+(r+3&511)),m=!1,x="";if((n&31)==0){var s=A>>5,o=32-(A&31),l=this.readConst(a+(r+4&511)),i=n&128;m=(n&32)!=0,r+=5,x+="X="+l+" W="+o+" P="+s+" "+(i?"WRITE":"")}else{var l=A,s=n>>5,o=32-(n&31),i=0;r+=4,x+="X="+l+" W="+o+" P="+s}let v=h+((c+(m?0:this.maria.offset)&255)<<8),C=(this.maria.regs[28]&3)+(i?4:0),y=m&&(this.maria.regs[28]&16)!=0;C&&(x+=" READMODE="+C),y&&(x+=" DBL"),m&&(x+=" CHR=$"+g(this.maria.regs[20]+this.maria.offset&255)+"xx"),x=" $"+g(v,4)+" "+x,e.push(x)}while(r<512);return e}},V=new Uint32Array(256);for(S=0;S<256;S++)V[S]=_(S);var S;var Q=[{id:"sprites.dasm",name:"Sprites (ASM)"},{id:"wsync.c",name:"WSYNC"},{id:"sprites.c",name:"Double Buffering"},{id:"scroll.c",name:"Scrolling"}],G=class extends z{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"TIA",start:0,size:32,type:"io"},{name:"MARIA",start:32,size:32,type:"io"},{name:"RAM (6166 Block 0)",start:64,size:192,type:"ram"},{name:"RAM (6166 Block 1)",start:320,size:192,type:"ram"},{name:"PIA",start:640,size:24,type:"io"},{name:"RAM",start:6144,size:4096,type:"ram"},{name:"Cartridge ROM",start:16384,size:49152,type:"rom"}]}}}newMachine(){return new R}getPresets(){return Q}getDefaultExtension(){return".c"}readAddress(t){return this.machine.readConst(t)}getROMExtension(){return".a78"}getDebugTree(){let t=super.getDebugTree();return t.display_list=this.machine.getDebugDisplayLists(),t}};B.atari7800=G;
//# sourceMappingURL=atari7800-5KKGRW7B.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
import{I as W,h as E,k as N,p as F,t as _}from"./chunk-HB3LWF25.js";import{$ as w,J as k,U as M,V as r,W as I,Y as T,_ as U,da as O,g as b}from"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";var h=0,P=2,A=8,j=T([[r.A,A+0,128],[r.B,A+1,128],[r.SELECT,P,-2],[r.START,P,-1],[r.UP,h,-16],[r.DOWN,h,-32],[r.LEFT,h,-64],[r.RIGHT,h,-128],[r.P2_A,A+2,128],[r.P2_B,A+3,128],[r.P2_UP,h,-1],[r.P2_DOWN,h,-2],[r.P2_LEFT,h,-4],[r.P2_RIGHT,h,-8]]);var S=262,z=258-16,u=454,q=28,K=2,Y=S*60*K,L=class{constructor(){this.regs=new Uint8Array(32)}reset(){this.regs.fill(0)}read(t){return this.regs[t]|0}write(t,e){this.regs[t]=e}saveState(){return{regs:this.regs.slice(0)}}loadState(t){for(let e=0;e<32;e++)this.write(e,t.regs[e])}static stateToLongString(t){let e="";return e+=M(t.regs,0,32),e}},R=class{constructor(){this.cycles=0;this.regs=new Uint8Array(32);this.offset=-1;this.dll=0;this.dlstart=0;this.dli=!1;this.h16=!1;this.h8=!1;this.pixels=new Uint8Array(320);this.WSYNC=0}reset(){this.regs.fill(0)}read(t){return this.regs[t]|0}write(t,e){this.regs[t]=e,t==4&&this.WSYNC++}saveState(){return{regs:this.regs.slice(0),offset:this.offset,dll:this.dll,dlstart:this.dlstart,dli:this.dli,h16:this.h16,h8:this.h8}}loadState(t){for(let e=0;e<32;e++)this.write(e,t.regs[e]|0);this.offset=t.offset|0,this.dll=t.dll|0,this.dlstart=t.dlstart|0,this.dli=!!t.dli,this.h16=!!t.h16,this.h8=!!t.h8}isDMAEnabled(){return(this.regs[28]&96)==64}getDLLStart(){return(this.regs[12]<<8)+this.regs[16]}getCharBaseAddress(){return(this.regs[20]<<8)+this.offset}setVBLANK(t){t?(this.regs[8]|=128,this.offset=-1,this.dll=this.getDLLStart(),this.dli=this.bus&&(this.bus.read(this.dll)&128)!=0):this.regs[8]&=~128}readDLLEntry(t){if(this.dll>=16384)return;let e=t.read(this.dll);this.offset=e&15,this.h16=(e&64)!=0,this.h8=(e&32)!=0,this.dlstart=(t.read(this.dll+1)<<8)+t.read(this.dll+2),this.dll=this.dll+3&65535,this.dli=(t.read(this.dll)&128)!=0}isHoley(t){return!!(t&32768&&(this.h16&&t&4096||this.h8&&t&2048))}readDMA(t){return this.isHoley(t)?0:(this.cycles+=3,this.bus.read(t))}doDMA(t){if(this.bus=t,this.cycles=0,this.pixels.fill(this.regs[0]),this.isDMAEnabled()){this.cycles+=16,this.offset<0&&this.readDLLEntry(t);let s=this.dlstart&65280,a=this.dlstart&255;do{let m=t.read(s+(a+0&511)),f=t.read(s+(a+1&511));if(f==0||s>=16384)break;let G=t.read(s+(a+2&511)),v=t.read(s+(a+3&511)),p=!1;if((f&31)==0){var e=v>>5,c=32-(v&31),n=t.read(s+(a+4&511)),i=f&128;p=(f&32)!=0,a+=5,this.cycles+=10}else{var n=v,e=f>>5,c=32-(f&31),i=0;a+=4,this.cycles+=8}let D=m+((G+(p?0:this.offset)&255)<<8);n*=2;let $=(this.regs[28]&3)+(i?4:0),C=p&&(this.regs[28]&16)!=0;C&&(c*=2);for(var o=0;o<c;o++){let d=this.readDMA(C?D+(o>>1):D+o);if(p){let x=(this.regs[20]+this.offset<<8)+d;C&&o&1&&(x++,this.cycles-=3),d=this.readDMA(x)}switch($){case 0:for(let x=0;x<4;x++){var l=d>>6&3;l>0&&(this.pixels[n]=this.pixels[n+1]=this.regs[(e<<2)+l]),d<<=2,n=n+2&511}break;case 2:case 3:for(let x=0;x<8;x++){var l=d&128?1:0;l>0&&(this.pixels[n]=this.regs[(e<<2)+l]),d<<=1,n=n+1&511}break}}}while(this.cycles<u);this.offset-=1}return this.cycles}doInterrupt(){return this.dli&&this.offset<0?(this.dli=!1,!0):!1}static stateToLongString(t){let e="";return e+=M(t.regs,0,32),e+=`
DLL: $`+b((t.regs[12]<<8)+t.regs[16],4)+" @ $"+b(t.dll,4),e+=`
DL: $`+b(t.dlstart,4),e+=`
Offset: `+t.offset,e+=`
DLI? `+t.dli,e}},B=class extends F{constructor(){super();this.cpuFrequency=1789772;this.canvasWidth=320;this.numTotalScanlines=S;this.numVisibleScanlines=z;this.defaultROMSize=49152;this.cpuCyclesPerLine=113.5;this.sampleRate=Y;this.ram=new Uint8Array(4096);this.regs6532=new Uint8Array(4);this.tia=new L;this.maria=new R;this.lastFrameCycles=0;this.xtracyc=0;this.cpu=new _,this.read=w([[8,13,15,t=>(this.xtracyc++,this.readInput(t))],[0,31,31,t=>(this.xtracyc++,this.tia.read(t))],[32,63,31,t=>this.maria.read(t)],[64,255,255,t=>this.ram[t+2048]],[256,319,255,t=>this.read(t)],[320,511,511,t=>this.ram[t+2048]],[640,767,3,t=>(this.xtracyc++,this.inputs[t])],[6144,10239,65535,t=>this.ram[t-6144]],[10240,16383,2047,t=>this.read(t|8192)],[16384,65535,65535,t=>this.rom?this.rom[t-16384]:0],[0,65535,65535,t=>this.probe&&this.probe.logIllegal(t)]]),this.write=w([[21,26,31,(t,e)=>{this.xtracyc++,this.pokey1.setTIARegister(t,e)}],[0,31,31,(t,e)=>{this.xtracyc++,this.tia.write(t,e)}],[32,63,31,(t,e)=>{this.maria.write(t,e)}],[64,255,255,(t,e)=>{this.ram[t+2048]=e}],[256,319,255,(t,e)=>{this.write(t,e)}],[320,511,511,(t,e)=>{this.ram[t+2048]=e}],[640,767,3,(t,e)=>{this.xtracyc++,this.regs6532[t]=e}],[6144,10239,65535,(t,e)=>{this.ram[t-6144]=e}],[10240,16383,2047,(t,e)=>{this.write(t|8192,e)}],[49151,49151,65535,(t,e)=>{}],[0,65535,65535,(t,e)=>{this.probe&&this.probe.logIllegal(t)}]]),this.connectCPUMemoryBus(this),this.dmaBus=this.probeDMABus(this),this.handler=I(this.inputs,j),this.pokey1=new E,this.audioadapter=new N(this.pokey1,K,Y)}readConst(t){let e=this.probe;this.probe=null;let c=this.read(t);return this.probe=e,c}readInput(t){switch(t){case 12:return~this.inputs[8]&128;case 13:return~this.inputs[9]&128;default:return this.inputs[t]|0}}advanceCPU(){var t=super.advanceCPU();return this.xtracyc&&(t+=this.xtracyc,this.probe.logClocks(this.xtracyc),this.xtracyc=0),t}advanceFrame(t){var e=this.pixels,c=0,n,i=0,o=0,l=0;this.probe.logNewFrame();for(var s=0;s<S;s++){this.scanline=s;var a=s<z;for(this.maria.setVBLANK(!a),this.maria.WSYNC=0;i<q&&!this.maria.WSYNC;){if(t&&t()){t=null,s=999;break}i+=this.advanceCPU()<<2,l++}if(a){let f=this.maria.doDMA(this.dmaBus);if(this.probe.logClocks(f>>2),i+=f,e)for(var m=0;m<320;m++)e[c++]=H[this.maria.pixels[m]]}for((a||s==S-1)&&this.maria.doInterrupt()&&(this.probe.logInterrupt(0),this.cpu.NMI());i<u;){if(this.maria.WSYNC){this.probe.logWait(0),this.probe.logClocks(u-i>>2),i=u;break}if(t&&t()){t=null,s=999;break}i+=this.advanceCPU()<<2,l++}this.audio&&this.audioadapter.generate(this.audio),i-=u,o+=i,this.probe.logNewScanline()}return this.lastFrameCycles=o,l}getRasterX(){return this.lastFrameCycles%u}getRasterY(){return this.scanline}loadROM(t){t.length==49280&&(t=t.slice(128)),this.rom=U(t,this.defaultROMSize,!0)}reset(){super.reset(),this.tia.reset(),this.maria.reset(),this.inputs.fill(0),this.inputs[h]=255,this.inputs[P]=1+2+8}readAddress(t){return this.read(t)|0}loadState(t){this.cpu.loadState(t.c),this.ram.set(t.ram),this.tia.loadState(t.tia),this.maria.loadState(t.maria),this.regs6532.set(t.regs6532),this.loadControlsState(t)}saveState(){return{c:this.cpu.saveState(),ram:this.ram.slice(0),tia:this.tia.saveState(),maria:this.maria.saveState(),regs6532:this.regs6532.slice(0),inputs:this.inputs.slice(0)}}loadControlsState(t){this.inputs.set(t.inputs)}saveControlsState(){return{inputs:this.inputs.slice(0)}}getDebugCategories(){return["CPU","Stack","TIA","MARIA"]}getDebugInfo(t,e){switch(t){case"TIA":return L.stateToLongString(e.tia);case"MARIA":return R.stateToLongString(e.maria)+`
Scanline: `+this.scanline}}},H=new Uint32Array(256);for(g=0;g<256;g++)H[g]=O(g);var g;var X=[{id:"sprites.dasm",name:"Sprites (ASM)"},{id:"wsync.c",name:"WSYNC"},{id:"sprites.c",name:"Double Buffering"},{id:"scroll.c",name:"Scrolling"}],V=class extends W{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"TIA",start:0,size:32,type:"io"},{name:"MARIA",start:32,size:32,type:"io"},{name:"RAM (6166 Block 0)",start:64,size:192,type:"ram"},{name:"RAM (6166 Block 1)",start:320,size:192,type:"ram"},{name:"PIA",start:640,size:24,type:"io"},{name:"RAM",start:6144,size:4096,type:"ram"},{name:"Cartridge ROM",start:16384,size:49152,type:"rom"}]}}}newMachine(){return new B}getPresets(){return X}getDefaultExtension(){return".c"}readAddress(t){return this.machine.readConst(t)}getROMExtension(){return".a78"}};k.atari7800=V;
//# sourceMappingURL=atari7800-CBAOXRGJ.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
gen/atari8-P6UBBVZK.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
import{a as d}from"./chunk-3XE5YOCV.js";import{o as c}from"./chunk-R63KYPGV.js";import"./chunk-SXEVG2WS.js";import"./chunk-5SHCNQ2O.js";import"./chunk-Z2IKIN54.js";import{I as m,o as u,t as h}from"./chunk-HB3LWF25.js";import{$ as i,B as o,J as l,m as n}from"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";var s=31,a=class extends u{constructor(){super();this.cpuFrequency=1e6;this.defaultROMSize=32768;this.cpu=new h;this.ram=new Uint8Array(16384);this.read=i([[0,16383,16383,e=>this.ram[e]],[16384,16384,65535,e=>this.serial.byteAvailable()?128:0],[16385,16385,65535,e=>this.serial.recvByte()],[16386,16386,65535,e=>this.serial.clearToSend()?128:0],[32768,65535,32767,e=>this.rom&&this.rom[e]]]);this.write=i([[0,16383,16383,(e,t)=>{this.ram[e]=t}],[16387,16387,65535,(e,t)=>this.serial.sendByte(t)],[16399,16399,65535,(e,t)=>{this.inputs[s]=1}]]);this.connectCPUMemoryBus(this)}connectSerialIO(e){this.serial=e}readConst(e){return this.read(e)}advanceFrame(e){for(var t=0;t<this.cpuFrequency/60&&!(e&&e());)t+=this.advanceCPU();return t}advanceCPU(){if(this.isHalted())return 1;var e=super.advanceCPU();return this.serial&&this.serial.advance(e),e}reset(){this.inputs[s]=0,super.reset(),this.serial&&this.serial.reset()}isHalted(){return this.inputs[s]!=0}};var S=[{id:"hello.dasm",name:"Hello World (ASM)"}],f=class{constructor(e){e.style.overflowY="auto";var t=$('<div id="gameport"/>').appendTo(e);$('<p class="transcript-header">Serial Output</p>').appendTo(t);var y=$('<div id="windowport" class="transcript"/>').appendTo(t);this.div=y[0]}start(){this.tty=new d(this.div,!1)}reset(){this.tty.clear()}saveState(){return this.tty.saveState()}loadState(e){this.tty.loadState(e)}};function p(r){return r==10?"":r<32?String.fromCharCode(r+9216):String.fromCharCode(r)}var v=class{constructor(){this.bufferedRead=!0;this.cyclesPerByte=1e6/(57600/8);this.maxOutputBytes=4096}clearToSend(){return this.outputBytes.length<this.maxOutputBytes}sendByte(e){this.clearToSend()&&(this.outputBytes.push(e),this.viewer.tty.addtext(p(e),2|32),e==10&&this.viewer.tty.newline(),this.clearToSend()||(this.viewer.tty.newline(),this.viewer.tty.addtext("\u26A0\uFE0F OUTPUT BUFFER FULL \u26A0\uFE0F",4)))}byteAvailable(){return this.readIndex()>this.inputIndex}recvByte(){var e=this.readIndex();this.inputIndex=e;var t=(this.inputBytes&&this.inputBytes[e])|0;return this.viewer.tty.addtext(p(t),2|16),t==10&&this.viewer.tty.newline(),t}readIndex(){return this.bufferedRead?this.inputIndex+1:Math.floor(this.clk/this.cyclesPerByte)}reset(){this.inputIndex=-1,this.clk=0,this.outputBytes=[],this.bufin=""}advance(e){this.clk+=e}saveState(){return{clk:this.clk,idx:this.inputIndex,out:this.outputBytes.slice()}}loadState(e){this.clk=e.clk,this.inputIndex=e.idx,this.outputBytes=e.out.slice()}},x=class extends m{constructor(e){super(e);this.getMemoryMap=function(){return{main:[{name:"RAM",start:0,size:16384,type:"ram"},{name:"ROM",start:32768,size:32768,type:"rom"}]}};this.serview=new f(e)}async start(){super.start(),this.serial=new v,this.serial.viewer=this.serview,this.serview.start(),this.machine.connectSerialIO(this.serial)}reset(){this.serial.inputBytes=o(this.internalFiles["serialin.dat"]),super.reset(),this.serview.reset()}isBlocked(){return this.machine.isHalted()}advance(e){return this.isBlocked()?(this.internalFiles["serialout.dat"]=n(this.serial.outputBytes),c(),0):super.advance(e)}saveState(){var e=super.saveState();return e.serial=this.serial.saveState(),e.serview=this.serview.saveState(),e}loadState(e){super.loadState(e),this.serial.loadState(e.serial),this.serview.loadState(e.serview)}newMachine(){return new a}getPresets(){return S}getDefaultExtension(){return".dasm"}readAddress(e){return this.machine.readConst(e)}};l["devel-6502"]=x;export{v as SerialTestHarness};
//# sourceMappingURL=devel-364UXGWH.js.map
import{a as d}from"./chunk-3XE5YOCV.js";import{o as c}from"./chunk-MMLUO3PV.js";import"./chunk-SXEVG2WS.js";import"./chunk-5SHCNQ2O.js";import"./chunk-OCFU6ZP7.js";import{I as m,o as u,t as h}from"./chunk-HB3LWF25.js";import{$ as i,B as o,J as l,m as n}from"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";var s=31,a=class extends u{constructor(){super();this.cpuFrequency=1e6;this.defaultROMSize=32768;this.cpu=new h;this.ram=new Uint8Array(16384);this.read=i([[0,16383,16383,e=>this.ram[e]],[16384,16384,65535,e=>this.serial.byteAvailable()?128:0],[16385,16385,65535,e=>this.serial.recvByte()],[16386,16386,65535,e=>this.serial.clearToSend()?128:0],[32768,65535,32767,e=>this.rom&&this.rom[e]]]);this.write=i([[0,16383,16383,(e,t)=>{this.ram[e]=t}],[16387,16387,65535,(e,t)=>this.serial.sendByte(t)],[16399,16399,65535,(e,t)=>{this.inputs[s]=1}]]);this.connectCPUMemoryBus(this)}connectSerialIO(e){this.serial=e}readConst(e){return this.read(e)}advanceFrame(e){for(var t=0;t<this.cpuFrequency/60&&!(e&&e());)t+=this.advanceCPU();return t}advanceCPU(){if(this.isHalted())return 1;var e=super.advanceCPU();return this.serial&&this.serial.advance(e),e}reset(){this.inputs[s]=0,super.reset(),this.serial&&this.serial.reset()}isHalted(){return this.inputs[s]!=0}};var S=[{id:"hello.dasm",name:"Hello World (ASM)"}],f=class{constructor(e){e.style.overflowY="auto";var t=$('<div id="gameport"/>').appendTo(e);$('<p class="transcript-header">Serial Output</p>').appendTo(t);var y=$('<div id="windowport" class="transcript"/>').appendTo(t);this.div=y[0]}start(){this.tty=new d(this.div,!1)}reset(){this.tty.clear()}saveState(){return this.tty.saveState()}loadState(e){this.tty.loadState(e)}};function p(r){return r==10?"":r<32?String.fromCharCode(r+9216):String.fromCharCode(r)}var v=class{constructor(){this.bufferedRead=!0;this.cyclesPerByte=1e6/(57600/8);this.maxOutputBytes=4096}clearToSend(){return this.outputBytes.length<this.maxOutputBytes}sendByte(e){this.clearToSend()&&(this.outputBytes.push(e),this.viewer.tty.addtext(p(e),2|32),e==10&&this.viewer.tty.newline(),this.clearToSend()||(this.viewer.tty.newline(),this.viewer.tty.addtext("\u26A0\uFE0F OUTPUT BUFFER FULL \u26A0\uFE0F",4)))}byteAvailable(){return this.readIndex()>this.inputIndex}recvByte(){var e=this.readIndex();this.inputIndex=e;var t=(this.inputBytes&&this.inputBytes[e])|0;return this.viewer.tty.addtext(p(t),2|16),t==10&&this.viewer.tty.newline(),t}readIndex(){return this.bufferedRead?this.inputIndex+1:Math.floor(this.clk/this.cyclesPerByte)}reset(){this.inputIndex=-1,this.clk=0,this.outputBytes=[],this.bufin=""}advance(e){this.clk+=e}saveState(){return{clk:this.clk,idx:this.inputIndex,out:this.outputBytes.slice()}}loadState(e){this.clk=e.clk,this.inputIndex=e.idx,this.outputBytes=e.out.slice()}},x=class extends m{constructor(e){super(e);this.getMemoryMap=function(){return{main:[{name:"RAM",start:0,size:16384,type:"ram"},{name:"ROM",start:32768,size:32768,type:"rom"}]}};this.serview=new f(e)}async start(){super.start(),this.serial=new v,this.serial.viewer=this.serview,this.serview.start(),this.machine.connectSerialIO(this.serial)}reset(){this.serial.inputBytes=o(this.internalFiles["serialin.dat"]),super.reset(),this.serview.reset()}isBlocked(){return this.machine.isHalted()}advance(e){return this.isBlocked()?(this.internalFiles["serialout.dat"]=n(this.serial.outputBytes),c(),0):super.advance(e)}saveState(){var e=super.saveState();return e.serial=this.serial.saveState(),e.serview=this.serview.saveState(),e}loadState(e){super.loadState(e),this.serial.loadState(e.serial),this.serview.loadState(e.serview)}newMachine(){return new a}getPresets(){return S}getDefaultExtension(){return".dasm"}readAddress(e){return this.machine.readConst(e)}};l["devel-6502"]=x;export{v as SerialTestHarness};
//# sourceMappingURL=devel-GTEJKQ3P.js.map

View File

@ -1,2 +1,2 @@
import{b as w,c as x}from"./chunk-Z2IKIN54.js";import{D as v,J as c,k as m,l as u,x as g,z as p}from"./chunk-ATS7PSQG.js";import{e as I}from"./chunk-5XVCUSSZ.js";var h=I(x()),i,a,l,y=function(e){if(!e||e.length==0)return{};for(var r={},t=0;t<e.length;++t){var o=e[t].split("=",2);o.length==1?r[o[0]]="":r[o[0]]=decodeURIComponent(o[1].replace(/\+/g," "))}return r}(window.location.search.substr(1).split("&"));function P(){typeof window.onerror=="object"&&(window.onerror=function(e,r,t,o,n){var s=e+" "+r+" "+t+":"+o+", "+n;$.get("/error?msg="+encodeURIComponent(s),"text")})}function M(){var e=!1;document.addEventListener("visibilitychange",function(r){document.visibilityState=="hidden"&&a.isRunning()?(a.pause(),e=!0):document.visibilityState=="visible"&&e&&(a.resume(),e=!1)}),$(window).on("focus",function(){e&&(a.resume(),e=!1)}),$(window).on("blur",function(){a.isRunning()&&(a.pause(),e=!0)})}async function k(e,r){if(!r){alert("No ROM found.");return}console.log(r.length+" bytes"),await a.loadROM(e,r),a.resume()}function R(){return $("#emulator").find("canvas")}function E(e,r,t){v("gif.js/dist/gif.js").then(()=>{var o=R()[0];if(!o){alert("Could not find canvas element to record video!");return}var n=0;o.style&&o.style.transform&&(o.style.transform.indexOf("rotate(-90deg)")>=0?n=-1:o.style.transform.indexOf("rotate(90deg)")>=0&&(n=1));var s=new GIF({workerScript:"gif.js/dist/gif.worker.js",workers:4,quality:10,rotate:n});s.on("finished",function(C){console.log("finished encoding GIF"),t(C)}),e=e||100+(Math.random()*256&3),r=r||100+(Math.random()*256&15);var f=0;console.log("Recording video",o);var d=()=>{f++>r?(console.log("Rendering video"),s.render()):(s.addFrame(o,{delay:e,copy:!0}),setTimeout(d,e))};d()})}async function S(e){if(!c[i])throw Error("Invalid platform '"+i+"'.");a=new c[i]($("#emuscreen")[0]),await a.start(),e.rec&&R().on("focus",()=>{a.resume()});var r=e.n||"Game",t,o=e.url,n=e.r;if(o)return console.log(o),g(o,f=>{k(r,f)},"arraybuffer"),!0;if(n){var s=u(atob(n));t=new m().decode(s)}return M(),k(r,t),!0}async function b(e){if(e.data&&(e=e.data),i=e.p,!i)throw new Error("No platform variable!");try{var r=await w(p(i));console.log("starting platform",i),await S(e)}catch(t){console.log(t),alert('Platform "'+i+'" not supported.')}}function F(){P(),y.p&&b(y)}window.addEventListener("message",O,!1);function O(e){if(e.data){var r=e.data.cmd;if(r=="start"&&!a)b(e);else if(r=="reset")a.reset(),l.reset();else if(r=="getReplay"){var t={frameCount:l.frameCount,checkpoints:l.checkpoints,framerecs:l.framerecs,checkpointInterval:l.checkpointInterval,maxCheckpoints:l.maxCheckpoints};e.source.postMessage({ack:r,replay:t},e.origin)}else if(r=="watchState"){var o=new Function("platform","state",e.data.fn);l.callbackNewCheckpoint=n=>{e.source.postMessage({ack:r,state:o(a,n)},e.origin)}}else r=="recordVideo"?E(e.data.intervalMsec,e.data.maxFrames,function(n){e.data.filename&&(0,h.saveAs)(n,e.data.filename),e.source.postMessage({ack:r,gif:n},e.origin)}):console.log("Unknown data.cmd: "+r)}}self===top&&(document.body.style.backgroundColor="#555");F();export{a as platform,i as platform_id,F as startEmbed,l as stateRecorder};
import{b as w,c as x}from"./chunk-OCFU6ZP7.js";import{D as v,J as c,k as m,l as u,x as g,z as p}from"./chunk-ATS7PSQG.js";import{e as I}from"./chunk-5XVCUSSZ.js";var h=I(x()),i,a,l,y=function(e){if(!e||e.length==0)return{};for(var r={},t=0;t<e.length;++t){var o=e[t].split("=",2);o.length==1?r[o[0]]="":r[o[0]]=decodeURIComponent(o[1].replace(/\+/g," "))}return r}(window.location.search.substr(1).split("&"));function P(){typeof window.onerror=="object"&&(window.onerror=function(e,r,t,o,n){var s=e+" "+r+" "+t+":"+o+", "+n;$.get("/error?msg="+encodeURIComponent(s),"text")})}function M(){var e=!1;document.addEventListener("visibilitychange",function(r){document.visibilityState=="hidden"&&a.isRunning()?(a.pause(),e=!0):document.visibilityState=="visible"&&e&&(a.resume(),e=!1)}),$(window).on("focus",function(){e&&(a.resume(),e=!1)}),$(window).on("blur",function(){a.isRunning()&&(a.pause(),e=!0)})}async function k(e,r){if(!r){alert("No ROM found.");return}console.log(r.length+" bytes"),await a.loadROM(e,r),a.resume()}function R(){return $("#emulator").find("canvas")}function E(e,r,t){v("gif.js/dist/gif.js").then(()=>{var o=R()[0];if(!o){alert("Could not find canvas element to record video!");return}var n=0;o.style&&o.style.transform&&(o.style.transform.indexOf("rotate(-90deg)")>=0?n=-1:o.style.transform.indexOf("rotate(90deg)")>=0&&(n=1));var s=new GIF({workerScript:"gif.js/dist/gif.worker.js",workers:4,quality:10,rotate:n});s.on("finished",function(C){console.log("finished encoding GIF"),t(C)}),e=e||100+(Math.random()*256&3),r=r||100+(Math.random()*256&15);var f=0;console.log("Recording video",o);var d=()=>{f++>r?(console.log("Rendering video"),s.render()):(s.addFrame(o,{delay:e,copy:!0}),setTimeout(d,e))};d()})}async function S(e){if(!c[i])throw Error("Invalid platform '"+i+"'.");a=new c[i]($("#emuscreen")[0]),await a.start(),e.rec&&R().on("focus",()=>{a.resume()});var r=e.n||"Game",t,o=e.url,n=e.r;if(o)return console.log(o),g(o,f=>{k(r,f)},"arraybuffer"),!0;if(n){var s=u(atob(n));t=new m().decode(s)}return M(),k(r,t),!0}async function b(e){if(e.data&&(e=e.data),i=e.p,!i)throw new Error("No platform variable!");try{var r=await w(p(i));console.log("starting platform",i),await S(e)}catch(t){console.log(t),alert('Platform "'+i+'" not supported.')}}function F(){P(),y.p&&b(y)}window.addEventListener("message",O,!1);function O(e){if(e.data){var r=e.data.cmd;if(r=="start"&&!a)b(e);else if(r=="reset")a.reset(),l.reset();else if(r=="getReplay"){var t={frameCount:l.frameCount,checkpoints:l.checkpoints,framerecs:l.framerecs,checkpointInterval:l.checkpointInterval,maxCheckpoints:l.maxCheckpoints};e.source.postMessage({ack:r,replay:t},e.origin)}else if(r=="watchState"){var o=new Function("platform","state",e.data.fn);l.callbackNewCheckpoint=n=>{e.source.postMessage({ack:r,state:o(a,n)},e.origin)}}else r=="recordVideo"?E(e.data.intervalMsec,e.data.maxFrames,function(n){e.data.filename&&(0,h.saveAs)(n,e.data.filename),e.source.postMessage({ack:r,gif:n},e.origin)}):console.log("Unknown data.cmd: "+r)}}self===top&&(document.body.style.backgroundColor="#555");F();export{a as platform,i as platform_id,F as startEmbed,l as stateRecorder};
//# sourceMappingURL=embedui.js.map

View File

@ -29,11 +29,14 @@ const Atari7800_KEYCODE_MAP = (0, emu_1.makeKeycodeMap)([
]);
// http://www.ataripreservation.org/websites/freddy.offenga/megazine/ISSUE5-PALNTSC.html
// http://7800.8bitdev.org/index.php/7800_Software_Guide#APPENDIX_4:_FRAME_TIMING
// https://forums.atariage.com/topic/224025-7800-hardware-facts/
const CLK = 3579545;
const linesPerFrame = 262;
const linesPerFrame = 263;
const numVisibleLines = 258 - 16;
const colorClocksPerLine = 454; // 456?
const colorClocksPerLine = 451; // 451? 452? 456?
const colorClocksPreDMA = 28;
const colorClocksShutdownOther = 16;
const colorClocksShutdownLast = 24;
const audioOversample = 2;
const audioSampleRate = linesPerFrame * 60 * audioOversample;
// TIA chip
@ -76,6 +79,7 @@ class MARIA {
this.dli = false;
this.h16 = false;
this.h8 = false;
this.indirect = false;
this.pixels = new Uint8Array(320);
this.WSYNC = 0;
}
@ -101,6 +105,7 @@ class MARIA {
dli: this.dli,
h16: this.h16,
h8: this.h8,
indirect: this.indirect,
};
}
loadState(s) {
@ -112,6 +117,7 @@ class MARIA {
this.dli = !!s.dli;
this.h16 = !!s.h16;
this.h8 = !!s.h8;
this.indirect = !!s.indirect;
}
isDMAEnabled() {
return (this.regs[0x1c] & 0x60) == 0x40;
@ -148,6 +154,8 @@ class MARIA {
this.dli = (bus.read(this.dll) & 0x80) != 0; // DLI flag is from next DLL entry
}
isHoley(a) {
if (this.indirect)
return false;
if (a & 0x8000) {
if (this.h16 && (a & 0x1000))
return true;
@ -157,8 +165,9 @@ class MARIA {
return false;
}
readDMA(a) {
if (this.isHoley(a))
if (this.isHoley(a)) {
return 0;
}
else {
this.cycles += 3;
return this.bus.read(a);
@ -169,7 +178,8 @@ class MARIA {
this.cycles = 0;
this.pixels.fill(this.regs[0x0]);
if (this.isDMAEnabled()) {
this.cycles += 16; // TODO: last line in zone gets additional 8 cycles
// last line in zone gets additional 8 cycles
this.cycles += this.offset == 0 ? colorClocksShutdownLast : colorClocksShutdownOther;
// time for a new DLL entry?
if (this.offset < 0) {
this.readDLLEntry(bus);
@ -209,6 +219,7 @@ class MARIA {
dlofs += 4;
this.cycles += 8;
}
this.indirect = indirect;
let gfxadr = b0 + (((b2 + (indirect ? 0 : this.offset)) & 0xff) << 8);
xpos *= 2;
// copy graphics data (direct)
@ -292,6 +303,8 @@ class Atari7800 extends devices_1.BasicMachine {
this.sampleRate = audioSampleRate;
this.ram = new Uint8Array(0x1000);
this.regs6532 = new Uint8Array(4);
this.piatimer = 0;
this.timerinterval = 1;
this.tia = new TIA();
this.maria = new MARIA();
this.lastFrameCycles = 0;
@ -304,7 +317,7 @@ class Atari7800 extends devices_1.BasicMachine {
[0x0040, 0x00ff, 0xff, (a) => { return this.ram[a + 0x800]; }],
[0x0100, 0x013f, 0xff, (a) => { return this.read(a); }],
[0x0140, 0x01ff, 0x1ff, (a) => { return this.ram[a + 0x800]; }],
[0x0280, 0x02ff, 0x3, (a) => { this.xtracyc++; return this.inputs[a]; }],
[0x0280, 0x02ff, 0x7f, (a) => { this.xtracyc++; return this.readPIA(a); }],
[0x1800, 0x27ff, 0xffff, (a) => { return this.ram[a - 0x1800]; }],
[0x2800, 0x3fff, 0x7ff, (a) => { return this.read(a | 0x2000); }],
[0x4000, 0xffff, 0xffff, (a) => { return this.rom ? this.rom[a - 0x4000] : 0; }],
@ -317,7 +330,7 @@ class Atari7800 extends devices_1.BasicMachine {
[0x0040, 0x00ff, 0xff, (a, v) => { this.ram[a + 0x800] = v; }],
[0x0100, 0x013f, 0xff, (a, v) => { this.write(a, v); }],
[0x0140, 0x01ff, 0x1ff, (a, v) => { this.ram[a + 0x800] = v; }],
[0x0280, 0x02ff, 0x3, (a, v) => { this.xtracyc++; this.regs6532[a] = v; /*TODO*/ }],
[0x0280, 0x02ff, 0x7f, (a, v) => { this.xtracyc++; this.writePIA(a, v); }],
[0x1800, 0x27ff, 0xffff, (a, v) => { this.ram[a - 0x1800] = v; }],
[0x2800, 0x3fff, 0x7ff, (a, v) => { this.write(a | 0x2000, v); }],
[0xbfff, 0xbfff, 0xffff, (a, v) => { }],
@ -344,15 +357,75 @@ class Atari7800 extends devices_1.BasicMachine {
default: return this.inputs[a] | 0;
}
}
readPIA(a) {
switch (a) {
case 0x0:
case 0x2:
return this.inputs[a]; // SWCHA, SWCHB
case 0x1:
case 0x3:
return this.regs6532[a]; // CTLSWA, CTLSWB
case 0x4:
return this.getPIATimerValue(); // INTIM
default:
return 0;
}
}
writePIA(a, v) {
switch (a) {
case 0x0:
case 0x1:
case 0x2:
case 0x3:
this.regs6532[a] = v;
return;
case 0x14:
this.setPIATimer(v, 0);
return; // TIM1T
case 0x15:
this.setPIATimer(v, 3);
return; // TIM8T
case 0x16:
this.setPIATimer(v, 6);
return; // TIM64T
case 0x17:
this.setPIATimer(v, 10);
return; // T1024T
case 0x18:
this.setPIATimer(v, 6);
return; // TIM64TI (TODO)
}
}
setPIATimer(v, shift) {
this.piatimer = (v + 1) << shift;
this.timerinterval = shift;
}
getPIATimerValue() {
let t = this.piatimer;
if (t > 0) {
return t >> this.timerinterval;
}
else {
return t & 0xff;
}
}
advanceCPU() {
var clk = super.advanceCPU();
this.tickPIATimer(clk); // TODO?
if (this.xtracyc) {
clk += this.xtracyc;
this.probe.logClocks(this.xtracyc);
this.tickClocks(this.xtracyc);
this.xtracyc = 0;
}
return clk;
}
tickClocks(clocks) {
this.probe.logClocks(clocks);
this.tickPIATimer(clocks);
}
tickPIATimer(clocks) {
this.piatimer = Math.max(-256, this.piatimer - clocks);
}
advanceFrame(trap) {
var idata = this.pixels;
var iofs = 0;
@ -384,7 +457,7 @@ class Atari7800 extends devices_1.BasicMachine {
if (visible) {
// do DMA for scanline?
let dmaClocks = this.maria.doDMA(this.dmaBus);
this.probe.logClocks(dmaClocks >> 2); // TODO: logDMA
this.tickClocks(dmaClocks >> 2); // TODO: logDMA
mc += dmaClocks;
// copy line to frame buffer
if (idata) {
@ -402,7 +475,7 @@ class Atari7800 extends devices_1.BasicMachine {
while (mc < colorClocksPerLine) {
if (this.maria.WSYNC) {
this.probe.logWait(0);
this.probe.logClocks((colorClocksPerLine - mc) >> 2);
this.tickClocks((colorClocksPerLine - mc) >> 2);
mc = colorClocksPerLine;
break;
}
@ -453,6 +526,8 @@ class Atari7800 extends devices_1.BasicMachine {
this.tia.loadState(state.tia);
this.maria.loadState(state.maria);
this.regs6532.set(state.regs6532);
this.piatimer = state.pia.timer;
this.timerinterval = state.pia.interval;
this.loadControlsState(state);
}
saveState() {
@ -462,7 +537,8 @@ class Atari7800 extends devices_1.BasicMachine {
tia: this.tia.saveState(),
maria: this.maria.saveState(),
regs6532: this.regs6532.slice(0),
inputs: this.inputs.slice(0)
inputs: this.inputs.slice(0),
pia: { timer: this.piatimer, interval: this.timerinterval }
};
}
loadControlsState(state) {
@ -483,6 +559,83 @@ class Atari7800 extends devices_1.BasicMachine {
//default: return super.getDebugInfo(category, state);
}
}
getDebugDisplayLists() {
// return display list in human-readable JSON object
let display_lists = {};
let dll_ofs = this.maria.getDLLStart();
// read the address of each DLL entry
let y = 0;
while (y < 240) {
let x = this.readConst(dll_ofs);
let offset = (x & 0xf);
let h16 = (x & 0x40) != 0;
let h8 = (x & 0x20) != 0;
let dlstart = (this.readConst(dll_ofs + 1) << 8) + this.readConst(dll_ofs + 2);
dll_ofs = (dll_ofs + 3) & 0xffff; // TODO: can also only cross 1 page?
let dli = (this.readConst(dll_ofs) & 0x80) != 0; // DLI flag is from next DLL entry
let title = "DL $" + (0, util_1.hex)(dlstart, 4) + " " + y + "-" + (y + offset);
if (h16)
title += " H16";
if (h8)
title += " H8";
if (dli)
title += " DLI";
display_lists[title] = { "$$": this._readDebugDisplayList(dlstart) };
y += offset + 1;
}
return display_lists;
}
_readDebugDisplayList(dlstart) {
return () => this.readDebugDisplayList(dlstart);
}
readDebugDisplayList(dlstart) {
let display_list = [];
let dlhi = dlstart & 0xff00;
let dlofs = dlstart & 0xff;
do {
// read DL entry
let b0 = this.readConst(dlhi + ((dlofs + 0) & 0x1ff));
let b1 = this.readConst(dlhi + ((dlofs + 1) & 0x1ff));
if (b1 == 0)
break; // end of DL
// display lists must be in RAM (TODO: probe?)
let b2 = this.readConst(dlhi + ((dlofs + 2) & 0x1ff));
let b3 = this.readConst(dlhi + ((dlofs + 3) & 0x1ff));
// extended header?
let indirect = false;
let description = "";
if ((b1 & 31) == 0) {
var pal = b3 >> 5;
var width = 32 - (b3 & 31);
var xpos = this.readConst(dlhi + ((dlofs + 4) & 0x1ff));
var writemode = b1 & 0x80;
indirect = (b1 & 0x20) != 0;
dlofs += 5;
description += "X=" + xpos + " W=" + width + " P=" + pal + " " + (writemode ? "WRITE" : "");
}
else {
// direct mode
var xpos = b3;
var pal = b1 >> 5;
var width = 32 - (b1 & 31);
var writemode = 0;
dlofs += 4;
description += "X=" + xpos + " W=" + width + " P=" + pal;
}
let gfxadr = b0 + (((b2 + (indirect ? 0 : this.maria.offset)) & 0xff) << 8);
let readmode = (this.maria.regs[0x1c] & 0x3) + (writemode ? 4 : 0);
let dbl = indirect && (this.maria.regs[0x1c] & 0x10) != 0;
if (readmode)
description += " READMODE=" + readmode;
if (dbl)
description += " DBL";
if (indirect)
description += " CHR=$" + (0, util_1.hex)((this.maria.regs[0x14] + this.maria.offset) & 0xff) + "xx";
description = " $" + (0, util_1.hex)(gfxadr, 4) + " " + description;
display_list.push(description);
} while (dlofs < 0x200);
return display_list;
}
}
exports.Atari7800 = Atari7800;
///

File diff suppressed because one or more lines are too long

View File

@ -402,6 +402,58 @@ class Atari800 extends devices_1.BasicScanlineMachine {
setPaddleInput(controller, value) {
this.irq_pokey.pot_inputs[controller] = 255 - value;
}
getDebugDisplayList() {
let pc = this.antic.getDlistAddr();
const nextInsn = () => {
let b = this.read(pc);
pc = ((pc + 1) & 0x3ff) | (pc & ~0x3ff);
return b;
};
let dlist = {};
let y = 0;
for (let i = 0; i < 256 && y < 240; i++) {
let pc0 = pc;
let op = nextInsn(); // get mode
let mode = op & 0xf;
let debugmsg = ""; // op=" + hex(op);
let jmp = false;
let lines;
if (mode == 0) {
lines = (((op >> 4) & 7) + 1);
debugmsg += " blank=" + lines;
}
else {
lines = antic_1.MODE_LINES[mode];
debugmsg += " mode=" + (0, util_1.hex)(mode);
debugmsg += " lines=" + lines;
jmp = (op & ~0x40) == 0x01; // JMP insn?
let lms = (op & 0x40) != 0 && (op & 0xf) != 0; // LMS insn?
if (jmp && (op & 0x40)) {
debugmsg += " JVB";
}
else if (jmp)
debugmsg += " JMP";
else if (lms)
debugmsg += " LMS";
if (this.antic.isPlayfieldDMAEnabled() && (jmp || lms)) {
let dlarg_lo = nextInsn();
let dlarg_hi = nextInsn();
debugmsg += " $" + (0, util_1.hex)(dlarg_hi) + "" + (0, util_1.hex)(dlarg_lo);
}
if (op & 0x10) {
debugmsg += " HSCROL";
}
if (op & 0x20) {
debugmsg += " VSCROL";
}
}
dlist["$" + (0, util_1.hex)(pc0) + " y=" + y] = debugmsg;
if (jmp)
break;
y += lines;
}
return dlist;
}
}
exports.Atari800 = Atari800;
class Atari5200 extends Atari800 {

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ANTIC = exports.MODE_SHIFT = void 0;
exports.ANTIC = exports.MODE_SHIFT = exports.MODE_LINES = void 0;
const emu_1 = require("../../common/emu");
const util_1 = require("../../common/util");
// ANTIC
@ -38,7 +38,7 @@ const WSYNC_CYCLE = 212;
const ANTIC_LEFT = 17 - 4; // gtia 34, 4 cycle delay
const ANTIC_RIGHT = 110 - 4; // gtia 221, 4 cycle delay
const LAST_DMA_H = 105; // last DMA cycle
const MODE_LINES = [0, 0, 8, 10, 8, 16, 8, 16, 8, 4, 4, 2, 1, 2, 1, 1];
exports.MODE_LINES = [0, 0, 8, 10, 8, 16, 8, 16, 8, 4, 4, 2, 1, 2, 1, 1];
// how many bits before DMA clock repeats?
const MODE_PERIOD = [0, 0, 2, 2, 2, 2, 4, 4, 8, 4, 4, 4, 4, 2, 2, 2];
const MODE_YPERIOD = [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 1, 0, 0, 0, 0];
@ -131,7 +131,7 @@ class ANTIC {
this.dmaclock = 0;
}
else {
this.linesleft = MODE_LINES[this.mode];
this.linesleft = exports.MODE_LINES[this.mode];
this.period = MODE_PERIOD[this.mode];
if (this.jmp) {
this.regs[DLISTL] = this.dlarg_lo;
@ -187,8 +187,11 @@ class ANTIC {
this.nmi();
}
}
getDlistAddr() {
return this.regs[DLISTL] + (this.regs[DLISTH] << 8);
}
nextInsn() {
let pc = this.regs[DLISTL] + (this.regs[DLISTH] << 8);
let pc = this.getDlistAddr();
let b = this.read(pc);
//console.log('nextInsn', hex(pc), hex(b), this.v);
pc = ((pc + 1) & 0x3ff) | (pc & ~0x3ff);

File diff suppressed because one or more lines are too long

View File

@ -31,6 +31,11 @@ class Atari7800Platform extends baseplatform_1.Base6502MachinePlatform {
;
readAddress(a) { return this.machine.readConst(a); }
getROMExtension() { return ".a78"; }
getDebugTree() {
let tree = super.getDebugTree();
tree['display_list'] = this.machine.getDebugDisplayLists();
return tree;
}
}
///
emu_1.PLATFORMS['atari7800'] = Atari7800Platform;

View File

@ -1 +1 @@
{"version":3,"file":"atari7800.js","sourceRoot":"","sources":["../../src/platform/atari7800.ts"],"names":[],"mappings":";;AACA,oDAAiD;AACjD,yDAA2E;AAC3E,uCAA0C;AAE1C,IAAI,iBAAiB,GAAG;IACtB,EAAC,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC,eAAe,EAAC;IACzC,EAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,OAAO,EAAC;IAC5B,EAAC,EAAE,EAAC,WAAW,EAAE,IAAI,EAAC,kBAAkB,EAAC;IACzC,EAAC,EAAE,EAAC,UAAU,EAAE,IAAI,EAAC,WAAW,EAAC;CAClC,CAAC;AAEF,MAAM,iBAAkB,SAAQ,sCAAkC;IAAlE;;QAME,oDAAoD;QACpD,iBAAY,GAAG;YAAa,OAAO,EAAE,IAAI,EAAC;oBACtC,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC3C,EAAC,IAAI,EAAC,OAAO,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC7C,EAAC,IAAI,EAAC,oBAAoB,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC;oBAC3D,EAAC,IAAI,EAAC,oBAAoB,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC;oBAC5D,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC5C,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAC;oBAChD,EAAC,IAAI,EAAC,eAAe,EAAC,KAAK,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAC;iBAC7D,EAAE,CAAA;QAAC,CAAC,CAAC;IAER,CAAC;IAfC,UAAU,KAAc,OAAO,IAAI,qBAAS,EAAE,CAAC,CAAC,CAAC;IACjD,UAAU,KAAc,OAAO,iBAAiB,CAAC,CAAC,CAAC;IACnD,mBAAmB,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAAA,CAAC;IACvC,WAAW,CAAC,CAAC,IAAW,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAW3D,eAAe,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC;CACrC;AAED,GAAG;AAEH,eAAS,CAAC,WAAW,CAAC,GAAG,iBAAiB,CAAC"}
{"version":3,"file":"atari7800.js","sourceRoot":"","sources":["../../src/platform/atari7800.ts"],"names":[],"mappings":";;AACA,oDAAiD;AACjD,yDAA2E;AAC3E,uCAA0C;AAE1C,IAAI,iBAAiB,GAAG;IACtB,EAAC,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC,eAAe,EAAC;IACzC,EAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,OAAO,EAAC;IAC5B,EAAC,EAAE,EAAC,WAAW,EAAE,IAAI,EAAC,kBAAkB,EAAC;IACzC,EAAC,EAAE,EAAC,UAAU,EAAE,IAAI,EAAC,WAAW,EAAC;CAClC,CAAC;AAEF,MAAM,iBAAkB,SAAQ,sCAAkC;IAAlE;;QAME,oDAAoD;QACpD,iBAAY,GAAG;YAAa,OAAO,EAAE,IAAI,EAAC;oBACtC,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC3C,EAAC,IAAI,EAAC,OAAO,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC7C,EAAC,IAAI,EAAC,oBAAoB,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC;oBAC3D,EAAC,IAAI,EAAC,oBAAoB,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC;oBAC5D,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC;oBAC5C,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAC;oBAChD,EAAC,IAAI,EAAC,eAAe,EAAC,KAAK,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAC;iBAC7D,EAAE,CAAA;QAAC,CAAC,CAAC;IAOR,CAAC;IApBC,UAAU,KAAc,OAAO,IAAI,qBAAS,EAAE,CAAC,CAAC,CAAC;IACjD,UAAU,KAAc,OAAO,iBAAiB,CAAC,CAAC,CAAC;IACnD,mBAAmB,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAAA,CAAC;IACvC,WAAW,CAAC,CAAC,IAAW,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAW3D,eAAe,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC;IACpC,YAAY;QACV,IAAI,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,GAAG;AAEH,eAAS,CAAC,WAAW,CAAC,GAAG,iBAAiB,CAAC"}

View File

@ -64,6 +64,11 @@ class Atari800Platform extends baseplatform_1.Base6502MachinePlatform {
else
throw new Error('could not load BIOS file');
}
getDebugTree() {
let tree = super.getDebugTree();
tree['display_list'] = this.machine.getDebugDisplayList();
return tree;
}
}
class Atari5200Platform extends Atari800Platform {
constructor() {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
import{b as a,c as b,d as c,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,q as p,r as q,s as r,t as s,u as t,v as u,w as v,x as w}from"./chunk-R63KYPGV.js";import"./chunk-SXEVG2WS.js";import"./chunk-5SHCNQ2O.js";import"./chunk-Z2IKIN54.js";import"./chunk-HB3LWF25.js";import"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";export{l as clearBreakpoint,h as compparams,f as current_project,u as emulationHalted,p as getPlatformAndRepo,t as getSaveState,s as getTestOutput,n as haltEmulation,w as highlightSearch,i as lastDebugState,e as platform,b as platform_id,g as projectWindows,a as qs,v as reloadWorkspaceFile,d as repo_id,k as runToPC,m as setFrameRateUI,r as setTestInput,j as setupBreakpoint,o as setupSplits,q as startUI,c as store_id};
import{b as a,c as b,d as c,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,q as p,r as q,s as r,t as s,u as t,v as u,w as v,x as w}from"./chunk-MMLUO3PV.js";import"./chunk-SXEVG2WS.js";import"./chunk-5SHCNQ2O.js";import"./chunk-OCFU6ZP7.js";import"./chunk-HB3LWF25.js";import"./chunk-ATS7PSQG.js";import"./chunk-5XVCUSSZ.js";export{l as clearBreakpoint,h as compparams,f as current_project,u as emulationHalted,p as getPlatformAndRepo,t as getSaveState,s as getTestOutput,n as haltEmulation,w as highlightSearch,i as lastDebugState,e as platform,b as platform_id,g as projectWindows,a as qs,v as reloadWorkspaceFile,d as repo_id,k as runToPC,m as setFrameRateUI,r as setTestInput,j as setupBreakpoint,o as setupSplits,q as startUI,c as store_id};
//# sourceMappingURL=ui.js.map

View File

@ -23,16 +23,6 @@ body {
</style>
<link rel="stylesheet" href="css/ui.css">
<!-- google analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
if (window.location.host.endsWith('8bitworkshop.com')) {
ga('create', 'UA-54497476-9', 'auto');
ga('set', 'anonymizeIp', true);
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
</head>
<body>
@ -204,7 +194,6 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="?platform=basic">BASIC</a></li>
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
</ul>
</li>
<li class="dropdown dropdown-submenu">

View File

@ -28,6 +28,10 @@ interface Atari7800State extends Atari7800StateBase, Atari7800ControlsState {
offset,dll,dlstart : number;
dli,h16,h8 : boolean;
};
pia : {
timer: number;
interval: number;
}
}
const SWCHA = 0;
@ -56,11 +60,14 @@ const Atari7800_KEYCODE_MAP = makeKeycodeMap([
// http://www.ataripreservation.org/websites/freddy.offenga/megazine/ISSUE5-PALNTSC.html
// http://7800.8bitdev.org/index.php/7800_Software_Guide#APPENDIX_4:_FRAME_TIMING
// https://forums.atariage.com/topic/224025-7800-hardware-facts/
const CLK = 3579545;
const linesPerFrame = 262;
const linesPerFrame = 263;
const numVisibleLines = 258-16;
const colorClocksPerLine = 454; // 456?
const colorClocksPerLine = 451; // 451? 452? 456?
const colorClocksPreDMA = 28;
const colorClocksShutdownOther = 16;
const colorClocksShutdownLast = 24;
const audioOversample = 2;
const audioSampleRate = linesPerFrame*60*audioOversample;
@ -106,6 +113,7 @@ class MARIA {
dli : boolean = false;
h16 : boolean = false;
h8 : boolean = false;
indirect : boolean = false;
pixels = new Uint8Array(320);
WSYNC : number = 0;
@ -130,6 +138,7 @@ class MARIA {
dli: this.dli,
h16: this.h16,
h8: this.h8,
indirect: this.indirect,
};
}
loadState(s) {
@ -141,6 +150,7 @@ class MARIA {
this.dli = !!s.dli;
this.h16 = !!s.h16;
this.h8 = !!s.h8;
this.indirect = !!s.indirect;
}
isDMAEnabled() {
return (this.regs[0x1c] & 0x60) == 0x40;
@ -174,6 +184,7 @@ class MARIA {
this.dli = (bus.read(this.dll) & 0x80) != 0; // DLI flag is from next DLL entry
}
isHoley(a : number) : boolean {
if (this.indirect) return false;
if (a & 0x8000) {
if (this.h16 && (a & 0x1000)) return true;
if (this.h8 && (a & 0x800)) return true;
@ -181,9 +192,9 @@ class MARIA {
return false;
}
readDMA(a : number) : number {
if (this.isHoley(a))
if (this.isHoley(a)) {
return 0;
else {
} else {
this.cycles += 3;
return this.bus.read(a);
}
@ -193,7 +204,8 @@ class MARIA {
this.cycles = 0;
this.pixels.fill(this.regs[0x0]);
if (this.isDMAEnabled()) {
this.cycles += 16; // TODO: last line in zone gets additional 8 cycles
// last line in zone gets additional 8 cycles
this.cycles += this.offset == 0 ? colorClocksShutdownLast : colorClocksShutdownOther;
// time for a new DLL entry?
if (this.offset < 0) {
this.readDLLEntry(bus);
@ -229,6 +241,7 @@ class MARIA {
dlofs += 4;
this.cycles += 8;
}
this.indirect = indirect;
let gfxadr = b0 + (((b2 + (indirect?0:this.offset)) & 0xff) << 8);
xpos *= 2;
// copy graphics data (direct)
@ -312,6 +325,8 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
cpu : MOS6502;
ram : Uint8Array = new Uint8Array(0x1000);
regs6532 = new Uint8Array(4);
piatimer : number = 0;
timerinterval : number = 1;
tia : TIA = new TIA();
maria : MARIA = new MARIA();
pokey1; //TODO: type
@ -335,7 +350,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
[0x0040, 0x00ff, 0xff, (a) => { return this.ram[a + 0x800]; }],
[0x0100, 0x013f, 0xff, (a) => { return this.read(a); }], // shadow
[0x0140, 0x01ff, 0x1ff, (a) => { return this.ram[a + 0x800]; }],
[0x0280, 0x02ff, 0x3, (a) => { this.xtracyc++; return this.inputs[a]; }],
[0x0280, 0x02ff, 0x7f, (a) => { this.xtracyc++; return this.readPIA(a); }],
[0x1800, 0x27ff, 0xffff, (a) => { return this.ram[a - 0x1800]; }],
[0x2800, 0x3fff, 0x7ff, (a) => { return this.read(a | 0x2000); }], // shadow
[0x4000, 0xffff, 0xffff, (a) => { return this.rom ? this.rom[a - 0x4000] : 0; }],
@ -348,7 +363,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
[0x0040, 0x00ff, 0xff, (a,v) => { this.ram[a + 0x800] = v; }],
[0x0100, 0x013f, 0xff, (a,v) => { this.write(a,v); }], // shadow
[0x0140, 0x01ff, 0x1ff, (a,v) => { this.ram[a + 0x800] = v; }],
[0x0280, 0x02ff, 0x3, (a,v) => { this.xtracyc++; this.regs6532[a] = v; /*TODO*/ }],
[0x0280, 0x02ff, 0x7f, (a,v) => { this.xtracyc++; this.writePIA(a,v) }],
[0x1800, 0x27ff, 0xffff, (a,v) => { this.ram[a - 0x1800] = v; }],
[0x2800, 0x3fff, 0x7ff, (a,v) => { this.write(a | 0x2000, v); }], // shadow
[0xbfff, 0xbfff, 0xffff, (a,v) => { }], // TODO: bank switching?
@ -378,16 +393,70 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
}
}
readPIA(a:number) : number {
switch (a) {
case 0x0:
case 0x2:
return this.inputs[a]; // SWCHA, SWCHB
case 0x1:
case 0x3:
return this.regs6532[a]; // CTLSWA, CTLSWB
case 0x4:
return this.getPIATimerValue(); // INTIM
default:
return 0;
}
}
writePIA(a:number, v:number) : void {
switch (a) {
case 0x0:
case 0x1:
case 0x2:
case 0x3:
this.regs6532[a] = v;
return;
case 0x14: this.setPIATimer(v, 0); return; // TIM1T
case 0x15: this.setPIATimer(v, 3); return; // TIM8T
case 0x16: this.setPIATimer(v, 6); return; // TIM64T
case 0x17: this.setPIATimer(v, 10); return; // T1024T
case 0x18: this.setPIATimer(v, 6); return; // TIM64TI (TODO)
}
}
setPIATimer(v:number, shift:number) : void {
this.piatimer = (v + 1) << shift;
this.timerinterval = shift;
}
getPIATimerValue() : number {
let t = this.piatimer;
if (t > 0) {
return t >> this.timerinterval;
} else {
return t & 0xff;
}
}
advanceCPU() : number {
var clk = super.advanceCPU();
this.tickPIATimer(clk); // TODO?
if (this.xtracyc) {
clk += this.xtracyc;
this.probe.logClocks(this.xtracyc);
this.tickClocks(this.xtracyc);
this.xtracyc = 0;
}
return clk;
}
tickClocks(clocks:number) {
this.probe.logClocks(clocks);
this.tickPIATimer(clocks);
}
tickPIATimer(clocks:number) {
this.piatimer = Math.max(-256, this.piatimer - clocks);
}
advanceFrame(trap) : number {
var idata = this.pixels;
var iofs = 0;
@ -418,7 +487,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
if (visible) {
// do DMA for scanline?
let dmaClocks = this.maria.doDMA(this.dmaBus);
this.probe.logClocks(dmaClocks >> 2); // TODO: logDMA
this.tickClocks(dmaClocks >> 2); // TODO: logDMA
mc += dmaClocks;
// copy line to frame buffer
if (idata) {
@ -436,7 +505,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
while (mc < colorClocksPerLine) {
if (this.maria.WSYNC) {
this.probe.logWait(0);
this.probe.logClocks((colorClocksPerLine - mc) >> 2);
this.tickClocks((colorClocksPerLine - mc) >> 2);
mc = colorClocksPerLine;
break;
}
@ -491,6 +560,8 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
this.tia.loadState(state.tia);
this.maria.loadState(state.maria);
this.regs6532.set(state.regs6532);
this.piatimer = state.pia.timer;
this.timerinterval = state.pia.interval;
this.loadControlsState(state);
}
saveState() : Atari7800State {
@ -500,7 +571,8 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
tia:this.tia.saveState(),
maria:this.maria.saveState(),
regs6532:this.regs6532.slice(0),
inputs:this.inputs.slice(0)
inputs:this.inputs.slice(0),
pia:{timer:this.piatimer, interval: this.timerinterval}
};
}
loadControlsState(state:Atari7800ControlsState) : void {
@ -522,6 +594,75 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
//default: return super.getDebugInfo(category, state);
}
}
getDebugDisplayLists() {
// return display list in human-readable JSON object
let display_lists = {};
let dll_ofs = this.maria.getDLLStart();
// read the address of each DLL entry
let y = 0;
while (y < 240) {
let x = this.readConst(dll_ofs);
let offset = (x & 0xf);
let h16 = (x & 0x40) != 0;
let h8 = (x & 0x20) != 0;
let dlstart = (this.readConst(dll_ofs+1)<<8) + this.readConst(dll_ofs+2);
dll_ofs = (dll_ofs + 3) & 0xffff; // TODO: can also only cross 1 page?
let dli = (this.readConst(dll_ofs) & 0x80) != 0; // DLI flag is from next DLL entry
let title = "DL $" + hex(dlstart,4) + " " + y + "-" + (y+offset);
if (h16) title += " H16";
if (h8) title += " H8";
if (dli) title += " DLI";
display_lists[title] = { "$$": this._readDebugDisplayList(dlstart) };
y += offset + 1;
}
return display_lists;
}
_readDebugDisplayList(dlstart: number) {
return () => this.readDebugDisplayList(dlstart);
}
readDebugDisplayList(dlstart: number) {
let display_list = [];
let dlhi = dlstart & 0xff00;
let dlofs = dlstart & 0xff;
do {
// read DL entry
let b0 = this.readConst(dlhi + ((dlofs+0) & 0x1ff));
let b1 = this.readConst(dlhi + ((dlofs+1) & 0x1ff));
if (b1 == 0) break; // end of DL
// display lists must be in RAM (TODO: probe?)
let b2 = this.readConst(dlhi + ((dlofs+2) & 0x1ff));
let b3 = this.readConst(dlhi + ((dlofs+3) & 0x1ff));
// extended header?
let indirect = false;
let description = "";
if ((b1 & 31) == 0) {
var pal = b3 >> 5;
var width = 32 - (b3 & 31);
var xpos = this.readConst(dlhi + ((dlofs+4) & 0x1ff));
var writemode = b1 & 0x80;
indirect = (b1 & 0x20) != 0;
dlofs += 5;
description += "X=" + xpos + " W=" + width + " P=" + pal + " " + (writemode?"WRITE":"");
} else {
// direct mode
var xpos = b3;
var pal = b1 >> 5;
var width = 32 - (b1 & 31);
var writemode = 0;
dlofs += 4;
description += "X=" + xpos + " W=" + width + " P=" + pal;
}
let gfxadr = b0 + (((b2 + (indirect?0:this.maria.offset)) & 0xff) << 8);
let readmode = (this.maria.regs[0x1c] & 0x3) + (writemode?4:0);
let dbl = indirect && (this.maria.regs[0x1c] & 0x10) != 0;
if (readmode) description += " READMODE=" + readmode;
if (dbl) description += " DBL";
if (indirect) description += " CHR=$" + hex((this.maria.regs[0x14] + this.maria.offset) & 0xff) + "xx";
description = " $" + hex(gfxadr,4) + " " + description;
display_list.push(description);
} while (dlofs < 0x200);
return display_list;
}
}
///

View File

@ -5,7 +5,7 @@ import { AcceptsKeyInput, AcceptsPaddleInput, AcceptsROM, BasicScanlineMachine,
import { KeyFlags, Keys, makeKeycodeMap, newAddressDecoder, newKeyboardHandler } from "../common/emu";
import { hex } from "../common/util";
import { BaseWASIMachine } from "../common/wasmplatform";
import { ANTIC, MODE_SHIFT } from "./chips/antic";
import { ANTIC, MODE_LINES, MODE_SHIFT } from "./chips/antic";
import { CONSOL, GTIA, TRIG0 } from "./chips/gtia";
import { POKEY } from "./chips/pokey";
@ -410,6 +410,49 @@ export class Atari800 extends BasicScanlineMachine implements AcceptsPaddleInput
this.irq_pokey.pot_inputs[controller] = 255 - value;
}
getDebugDisplayList() {
let pc = this.antic.getDlistAddr();
const nextInsn = () => {
let b = this.read(pc);
pc = ((pc + 1) & 0x3ff) | (pc & ~0x3ff);
return b;
}
let dlist = {};
let y = 0;
for (let i=0; i<256 && y<240; i++) {
let pc0 = pc;
let op = nextInsn(); // get mode
let mode = op & 0xf;
let debugmsg = ""; // op=" + hex(op);
let jmp = false;
let lines;
if (mode == 0) {
lines = (((op >> 4) & 7) + 1);
debugmsg += " blank=" + lines;
} else {
lines = MODE_LINES[mode];
debugmsg += " mode=" + hex(mode);
debugmsg += " lines=" + lines;
jmp = (op & ~0x40) == 0x01; // JMP insn?
let lms = (op & 0x40) != 0 && (op & 0xf) != 0; // LMS insn?
if (jmp && (op & 0x40)) { debugmsg += " JVB"; }
else if (jmp) debugmsg += " JMP";
else if (lms) debugmsg += " LMS";
if (this.antic.isPlayfieldDMAEnabled() && (jmp || lms)) {
let dlarg_lo = nextInsn();
let dlarg_hi = nextInsn();
debugmsg += " $" + hex(dlarg_hi) + "" + hex(dlarg_lo);
}
if (op & 0x10) { debugmsg += " HSCROL"; }
if (op & 0x20) { debugmsg += " VSCROL"; }
}
dlist["$"+hex(pc0) + " y=" + y] = debugmsg;
if (jmp) break;
y += lines;
}
return dlist;
}
}
export class Atari5200 extends Atari800 {

View File

@ -42,7 +42,7 @@ const ANTIC_LEFT = 17 - 4; // gtia 34, 4 cycle delay
const ANTIC_RIGHT = 110 - 4; // gtia 221, 4 cycle delay
const LAST_DMA_H = 105; // last DMA cycle
const MODE_LINES = [0, 0, 8, 10, 8, 16, 8, 16, 8, 4, 4, 2, 1, 2, 1, 1];
export const MODE_LINES = [0, 0, 8, 10, 8, 16, 8, 16, 8, 4, 4, 2, 1, 2, 1, 1];
// how many bits before DMA clock repeats?
const MODE_PERIOD = [0, 0, 2, 2, 2, 2, 4, 4, 8, 4, 4, 4, 4, 2, 2, 2];
const MODE_YPERIOD = [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 1, 0, 0, 0, 0];
@ -199,8 +199,12 @@ export class ANTIC {
}
}
getDlistAddr() {
return this.regs[DLISTL] + (this.regs[DLISTH] << 8);
}
nextInsn(): number {
let pc = this.regs[DLISTL] + (this.regs[DLISTH] << 8);
let pc = this.getDlistAddr();
let b = this.read(pc);
//console.log('nextInsn', hex(pc), hex(b), this.v);
pc = ((pc + 1) & 0x3ff) | (pc & ~0x3ff);

View File

@ -27,6 +27,11 @@ class Atari7800Platform extends Base6502MachinePlatform<Atari7800> implements Pl
{name:'Cartridge ROM',start:0x4000,size:0xc000,type:'rom'},
] } };
getROMExtension() { return ".a78"; }
getDebugTree() {
let tree = super.getDebugTree();
tree['display_list'] = this.machine.getDebugDisplayLists();
return tree;
}
}
///

View File

@ -63,6 +63,11 @@ class Atari800Platform extends Base6502MachinePlatform<Atari800> {
return new Uint8Array(biosBinary);
} else throw new Error('could not load BIOS file');
}
getDebugTree() {
let tree = super.getDebugTree();
tree['display_list'] = this.machine.getDebugDisplayList();
return tree;
}
}
class Atari5200Platform extends Atari800Platform {