Created
March 21, 2016 09:46
-
-
Save MagerValp/a51c5985eab3f25ddbe5 to your computer and use it in GitHub Desktop.
My first C64 emulator, in AmigaE from 1996
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -> emulate parts of a c64 | |
| OPT PREPROCESS | |
| /* #define DEBUG */ | |
| MODULE 'tools/file', 'intuition/screens', 'graphics/gfx', 'dos/dos' | |
| MODULE 'intuition/intuition' | |
| -> the different memory parts | |
| DEF mem=NIL:PTR TO CHAR,kernelrom=NIL:PTR TO CHAR, | |
| basicrom=NIL:PTR TO CHAR,charrom=NIL:PTR TO CHAR, | |
| io=NIL:PTR TO CHAR,size=NIL:PTR TO CHAR, | |
| time=NIL:PTR TO CHAR,ddr,ioport,opcodes=NIL, | |
| opcodelist[256]:LIST,cyclecount=0,verbose, | |
| linelist[25]:ARRAY OF CHAR,skipmemtest=1 | |
| -> processor registers | |
| DEF a=0,x=0,y=0,sp=0,pc=0,status=$20 | |
| PROC main() HANDLE | |
| DEF l,state,i,s:PTR TO screen,w:PTR TO window,pcstr[39]:STRING,fh, | |
| args:PTR TO LONG,rdargs,msg:PTR TO intuimessage | |
| /* | |
| FOR x:=0 TO 255 | |
| IF (x AND 7)=0 THEN PrintF('$\z\h[2] ',x) | |
| status:=$35 | |
| PrintF(' \z\h[2]',ror(x)) | |
| IF (x AND 7)=7 THEN PrintF('\n') | |
| ENDFOR | |
| Raise("brk") | |
| */ | |
| -> parse command line args | |
| args:=[0] | |
| IF (rdargs:=ReadArgs('VERBOSE/S',args,NIL))=NIL THEN Raise("args") | |
| IF args[0] THEN verbose:=1 ELSE verbose:=0 | |
| -> allocate ram and load roms | |
| mem:=NewR(65536) | |
| io:=NewR(4096) | |
| kernelrom,l:=readfile('kernel.rom') ;-> IF l<>8192 THEN Raise("kern") | |
| basicrom ,l:=readfile('basic.rom') ;-> IF l<>8192 THEN Raise("basi") | |
| charrom ,l:=readfile('char.rom') ;-> IF l<>4096 THEN Raise("char") | |
| size ,l:=readfile('6510size.tab') ;-> IF l<>256 THEN Raise("size") | |
| time ,l:=readfile('6510time.tab') ;-> IF l<>256 THEN Raise("time") | |
| opcodes ,l:=readfile('OpCodeList.asc') | |
| opcodelist:=stringsinfile(opcodes,l,256) | |
| PrintF('emulation buffers ok...\n') | |
| -> Open and init screen | |
| IF (s:=OpenScreenTagList(0, | |
| [SA_WIDTH,336, | |
| SA_HEIGHT,224+11, | |
| SA_DEPTH,1]))=NIL THEN Raise("CHIP") | |
| SetRGB4(s.viewport,0,1,2,10) | |
| SetRGB4(s.viewport,1,7,7,15) | |
| SetAPen(s.rastport,1) | |
| SetBPen(s.rastport,0) | |
| IF (w:=OpenWindowTagList(0, | |
| [WA_WIDTH, 336, | |
| WA_HEIGHT, 224+11, | |
| WA_TITLE, '6510emu', | |
| WA_CUSTOMSCREEN, s, | |
| WA_IDCMP, IDCMP_VANILLAKEY, | |
| WA_BACKDROP, TRUE, | |
| WA_BORDERLESS, TRUE, | |
| WA_ACTIVATE, TRUE, | |
| 0,0]))=NIL THEN Raise("CHIP") | |
| clearscreen(s) | |
| renderscreen(s,1024) | |
| PrintF('screen ok...\n') | |
| -> start the emulation | |
| reset() | |
| IF verbose=1 THEN PrintF('*** starting trace ***\n') | |
| REPEAT | |
| FOR i:=1 TO 100 | |
| state:=emulate() | |
| /* | |
| StringF(pcstr,'\z\h[4] \z\h[2] \z\h[2] \z\h[2] \z\h[2] \z\h[2] '+ | |
| ' ', | |
| pc,a,x,y,status,sp) | |
| IF verbose=0 THEN StrAdd(pcstr,'off') ELSE StrAdd(pcstr,' on') | |
| Move(s.rastport,0,233) | |
| Text(s.rastport,pcstr,EstrLen(pcstr)) | |
| */ | |
| IF (msg:=GetMsg(w.userport))<>NIL | |
| IF mem[198]<mem[649] | |
| mem[631+mem[198]]:=msg.code | |
| mem[198]:=mem[198]+1 | |
| ENDIF | |
| ReplyMsg(msg) | |
| ENDIF | |
| IF (Mouse()<>0) AND (s.mousey>207) | |
| verbose:=1-verbose | |
| IF verbose=0 THEN PrintF('*** stopping trace ***\n') ELSE PrintF('*** starting trace ***\n') | |
| WHILE Mouse()<>0 ; ENDWHILE | |
| ENDIF | |
| ENDFOR | |
| IF CtrlC() THEN Raise("ctlc") | |
| renderdiffs(s,1024) | |
| UNTIL state<0 | |
| EXCEPT DO | |
| IF w THEN CloseWindow(w) | |
| IF s THEN CloseScreen(s) | |
| IF mem AND ((fh:=Open('ram:mem.dump',MODE_NEWFILE))<>NIL) | |
| PrintF('Writing ram:mem.dump\n') | |
| Fwrite(fh,mem,65536,1) | |
| Close(fh) | |
| ENDIF | |
| IF io AND ((fh:=Open('ram:io.dump',MODE_NEWFILE))<>NIL) | |
| PrintF('Writing ram:io.dump\n') | |
| Fwrite(fh,io,4096,1) | |
| Close(fh) | |
| ENDIF | |
| IF mem THEN Dispose(mem) | |
| IF io THEN Dispose(io) | |
| IF kernelrom THEN freefile(kernelrom) | |
| IF basicrom THEN freefile(basicrom) | |
| IF charrom THEN freefile(charrom) | |
| IF size THEN freefile(size) | |
| IF opcodes THEN freefile(opcodes) | |
| SELECT exception | |
| CASE "MEM" ; PrintF('Out of memory!\n') | |
| CASE "OPEN" ; PrintF('Can\at open!\n') | |
| CASE "CHIP" ; PrintF('Out of chip memory!\n') | |
| CASE "kern" ; PrintF('Can\at load kerne roml!\n') | |
| CASE "basi" ; PrintF('Can\at load basic rom!\n') | |
| CASE "char" ; PrintF('Can\at load character rom!\n') | |
| CASE "size" ; PrintF('Can\at load size table!\n') | |
| CASE "time" ; PrintF('Can\at load time table!\n') | |
| CASE "args" ; PrintF('Usage: 6510emu [verbose]\n') | |
| DEFAULT | |
| PrintF('Exiting.\n') | |
| ENDSELECT | |
| ENDPROC | |
| PROC clearscreen(screen:PTR TO screen) | |
| DEF y,dy,i,base,sdata:PTR TO CHAR | |
| sdata:=screen.bitmap.planes[0]+(screen.bitmap.bytesperrow*11) | |
| FOR dy:=0 TO 7 | |
| base:=dy*screen.bitmap.bytesperrow | |
| FOR i:=0 TO 41 | |
| sdata[base+i]:=255 | |
| ENDFOR | |
| ENDFOR | |
| FOR y:=1 TO 25 | |
| FOR dy:=0 TO 7 | |
| base:=(y*8+dy)*screen.bitmap.bytesperrow | |
| sdata[base]:=255 | |
| sdata[base+41]:=255 | |
| FOR i:=1 TO 40 | |
| sdata[base+i]:=0 | |
| ENDFOR | |
| ENDFOR | |
| ENDFOR | |
| FOR dy:=0 TO 7 | |
| base:=(208+dy)*screen.bitmap.bytesperrow | |
| FOR i:=0 TO 41 | |
| sdata[base+i]:=255 | |
| ENDFOR | |
| ENDFOR | |
| ENDPROC | |
| PROC renderscreen(screen:PTR TO screen,charstart) | |
| DEF i | |
| FOR i:=0 TO 24 | |
| renderline(screen,i,charstart) | |
| ENDFOR | |
| ENDPROC | |
| PROC renderdiffs(screen:PTR TO screen,charstart) | |
| DEF i | |
| FOR i:=0 TO 24 | |
| IF linelist[i]<>0 | |
| renderline(screen,i,charstart) | |
| linelist[i]:=0 | |
| ENDIF | |
| ENDFOR | |
| ENDPROC | |
| /* | |
| PROC writechar(screen:PTR TO screen,sx,sy,asc) | |
| DEF dy,sdata:PTR TO CHAR | |
| IF ((sx<0) OR (sx>39)) OR ((sy<0) OR (sy>24)) | |
| PrintF('X: \d\n',sx) | |
| PrintF('Y: \d\n',sy) | |
| Raise("brk") | |
| ENDIF | |
| sdata:=screen.bitmap.planes[0]+(sx+1)+(((sy+1)*8+11)*screen.bitmap.bytesperrow) | |
| FOR dy:=0 TO 7 | |
| sdata[dy*screen.bitmap.bytesperrow]:=charrom[asc*8+dy] | |
| ENDFOR | |
| ENDPROC | |
| */ | |
| PROC renderline(screen:PTR TO screen,sy,charstart) | |
| DEF dx,dy,sdata:PTR TO CHAR,chardata | |
| IF ((sy<0) OR (sy>24)) | |
| PrintF('Y: \d\n',sy) | |
| Raise("brk") | |
| ENDIF | |
| chardata:=40*sy+charstart | |
| sdata:=screen.bitmap.planes[0]+1+(((sy+1)*8+11)*screen.bitmap.bytesperrow) | |
| FOR dy:=0 TO 7 | |
| FOR dx:=0 TO 39 | |
| sdata[dy*screen.bitmap.bytesperrow+dx]:=charrom[mem[chardata+dx]*8+dy] | |
| ENDFOR | |
| ENDFOR | |
| ENDPROC | |
| #define lb(val) (val AND $00ff) | |
| #define hb(val) Shr(val,8) | |
| #define deek(address) ((peek(address+1)*256)+peek(address)) | |
| /* | |
| $0000-$9fff $a000-$bfff $c000-$cfff $d000-$dfff $e000-$efff | |
| 000 0 ram ram ram ram ram | |
| 001 1 ram ram ram char rom ram | |
| 010 2 ram ram ram char rom kernel | |
| 011 3 ram basic ram char rom kernel | |
| 100 4 ram ram ram ram ram | |
| 101 5 ram ram ram i/o ram | |
| 110 6 ram ram ram i/o kernel | |
| 111 7 ram basic ram i/o kernel | |
| */ | |
| PROC peek(address) | |
| DEF i | |
| address:=address AND $ffff | |
| i:=ioport AND 7 | |
| SELECT 256 OF hb(address) | |
| CASE $00 | |
| IF address=0 THEN RETURN ddr | |
| IF address=1 THEN RETURN ioport | |
| RETURN mem[address] | |
| CASE $01 TO $9f | |
| RETURN mem[address] | |
| CASE $a0 TO $bf | |
| IF (i AND 3)=3 THEN RETURN basicrom[address-$a000] | |
| RETURN mem[address] | |
| CASE $c0 TO $cf | |
| RETURN mem[address] | |
| CASE $d0 TO $d3 | |
| IF i>=5 THEN RETURN readvic(address AND $3f) | |
| IF (i AND 3)=0 THEN RETURN mem[address] | |
| RETURN charrom[address-$d000] | |
| CASE $d4 TO $d7 | |
| IF i>=5 THEN RETURN readsid(address AND $1f) | |
| IF (i AND 3)=0 THEN RETURN mem[address] | |
| RETURN charrom[address-$d000] | |
| CASE $d8 TO $db | |
| IF i>=5 THEN RETURN (io[address-$d000] AND $0f) OR (RndQ(cyclecount) AND $f0) | |
| IF (i AND 3)=0 THEN RETURN mem[address] | |
| RETURN charrom[address-$d000] | |
| CASE $dc | |
| IF i>=5 THEN RETURN readcia(1,address AND $0f) | |
| IF (i AND 3)=0 THEN RETURN mem[address] | |
| RETURN charrom[address-$d000] | |
| CASE $dd | |
| IF i>=5 THEN RETURN readcia(2,address AND $0f) | |
| IF (i AND 3)=0 THEN RETURN mem[address] | |
| RETURN charrom[address-$d000] | |
| CASE $de TO $df | |
| RETURN RndQ(cyclecount) AND $ff | |
| CASE $e0 TO $ff | |
| IF (i AND 2)=2 THEN RETURN kernelrom[address-$e000] | |
| RETURN mem[address] | |
| ENDSELECT | |
| ENDPROC | |
| PROC poke(address,val) | |
| SELECT 256 OF hb(address) | |
| CASE $00 | |
| IF address=0 THEN ddr:=val | |
| IF address=1 THEN ioport:=val | |
| mem[address]:=val | |
| CASE $01 TO $cf | |
| mem[address]:=val | |
| CASE $d0 TO $d3 | |
| IF (ioport AND 7)>=5 THEN writevic(address AND $3f,val) | |
| mem[address]:=val | |
| CASE $d4 TO $d7 | |
| IF (ioport AND 7)>=5 THEN writesid(address AND $1f,val) | |
| mem[address]:=val | |
| CASE $d8 TO $db | |
| IF (ioport AND 7)>=5 THEN io[address-$d000]:=val | |
| mem[address]:=val | |
| CASE $dc | |
| IF (ioport AND 7)>=5 THEN writecia(1,address AND $0f,val) | |
| mem[address]:=val | |
| CASE $dd | |
| IF (ioport AND 7)>=5 THEN writecia(2,address AND $0f,val) | |
| mem[address]:=val | |
| CASE $e0 TO $ff | |
| mem[address]:=val | |
| ENDSELECT | |
| IF (address>=$0400) AND (address<$07e8) THEN linelist[(address-$400)/40]:=1 | |
| ENDPROC val | |
| PROC push(val) | |
| mem[sp+256]:=val | |
| sp:=(sp-1) AND 255 | |
| ENDPROC | |
| PROC pull() | |
| DEF val | |
| sp:=(sp+1) AND 255 | |
| val:=mem[sp+256] | |
| ENDPROC val | |
| #define setN status:=status OR $80 | |
| #define setV status:=status OR $40 | |
| #define setB status:=status OR $10 | |
| #define setD status:=status OR $08 | |
| #define setI status:=status OR $04 | |
| #define setZ status:=status OR $02 | |
| #define setC status:=status OR $01 | |
| #define clrN status:=status AND $7f | |
| #define clrV status:=status AND $bf | |
| #define clrB status:=status AND $ef | |
| #define clrD status:=status AND $f7 | |
| #define clrI status:=status AND $fb | |
| #define clrZ status:=status AND $fd | |
| #define clrC status:=status AND $fe | |
| PROC setnz(val) | |
| IF val=0 THEN setZ ELSE clrZ | |
| IF val AND 128 THEN setN ELSE clrN | |
| ENDPROC | |
| PROC incpc(val) | |
| pc:=pc+val | |
| IF val AND 128 THEN pc:=pc-256 | |
| pc:=pc AND 65535 | |
| ENDPROC | |
| PROC reset() | |
| ioport:=$37 | |
| ddr:=$2f | |
| pc:=deek($fffc) | |
| sp:=255 | |
| status:=$20 | |
| PrintF('Reset: PC $\z\h[4]\n',pc) | |
| ENDPROC | |
| /* | |
| PROC ioread(address) | |
| IF (address>=$d000) AND (address<=$d3ff) | |
| RETURN vicread(address AND 63) | |
| ELSEIF (address>=$d400) AND (address<=$d7ff) | |
| RETURN sidread(address AND 31) | |
| ELSEIF (address>=$d800) AND (address<=$dbff) | |
| RETURN (io[address-$d800] AND 15)+(RndQ(pc*a*x*y*cyclecount) AND 240) | |
| ELSEIF (address>=$dc00) AND (address<=$dcff) | |
| RETURN ciaread(1,address AND 15) | |
| ELSEIF (address>=$dd00) AND (address<=$ddff) | |
| RETURN ciaread(2,address AND 15) | |
| ELSEIF (address>=$de00) AND (address<=$dfff) | |
| RETURN Shl("0156",4*(address AND 3)) AND 255 | |
| ELSE | |
| PrintF('ioreading outside io area\n') | |
| Raise("brk") | |
| ENDIF | |
| ENDPROC | |
| */ | |
| /* | |
| PROC iowrite(address,val) | |
| IF (address>=$d000) AND (address<=$dfff) | |
| io[address-$d000]:=val | |
| ELSE | |
| PrintF('iowriting outside io area\n') | |
| Raise("brk") | |
| ENDIF | |
| ENDPROC val | |
| */ | |
| PROC readvic(address) | |
| DEF rasterrow | |
| rasterrow:=Mod(cyclecount,18593)/60 | |
| SELECT 64 OF address | |
| CASE $11 | |
| RETURN io[address+$d000] AND 127 OR (rasterrow/2 AND 128) | |
| CASE $12 | |
| RETURN rasterrow AND 255 | |
| CASE $13 | |
| RETURN 0 | |
| CASE $14 | |
| RETURN 0 | |
| CASE $19 | |
| RETURN 0 | |
| CASE $1e | |
| RETURN 0 | |
| CASE $1f | |
| RETURN 0 | |
| CASE $2f TO $3f | |
| RETURN 0 | |
| DEFAULT | |
| RETURN io[address+$d000] | |
| ENDSELECT | |
| ENDPROC | |
| PROC readsid(address) IS io[address+$400] | |
| PROC readcia(chip,address) IS io[address+$db00+(chip*$100)] | |
| PROC writevic(address,val) | |
| io[address]:=val | |
| ENDPROC | |
| PROC writesid(address,val) | |
| io[address+$400]:=val | |
| ENDPROC | |
| PROC writecia(chip,address,val) | |
| io[address+$db00+(chip*$100)]:=val | |
| ENDPROC | |
| PROC emulate() | |
| DEF m,a0,a1,a16,state,tmp | |
| DEF opname[3]:STRING,adrmode[8]:STRING,tmpstring[256]:STRING | |
| IF (pc=$fd68) AND (skipmemtest=1) AND ((ioport AND 3)=3) | |
| PrintF('Skipping memory test\n') | |
| pc:=$fd88 | |
| mem[$c1]:=$00 | |
| mem[$c2]:=$a0 | |
| y:=0 | |
| ENDIF | |
| /* | |
| IF (pc=$e5d6) AND (verbose=0) | |
| PrintF('***Reached $\z\h[4]***\n',pc) | |
| verbose:=1 | |
| ENDIF | |
| IF (pc=$e5cd) AND (verbose=1) | |
| PrintF('***Reached $\z\h[4]***\n',pc) | |
| verbose:=0 | |
| ENDIF | |
| */ | |
| state:=0 | |
| m:=peek(pc) | |
| a0:=peek(pc+1) | |
| a1:=peek(pc+2) | |
| a16:=a0+(a1*256) | |
| IF verbose=1 | |
| PrintF('\z\h[4] \z\h[2] ',pc,m) | |
| StrCopy(opname,opcodelist[m],3) | |
| MidStr(adrmode,opcodelist[m],3) | |
| IF StrCmp(adrmode,'') | |
| PrintF(' \s\t',opname) | |
| ELSEIF InStr(adrmode,'@3')>=0 | |
| tmp:=pc+2+a0 | |
| IF a0>127 THEN tmp:=tmp-256 | |
| PrintF('\z\h[2] \s $\z\h[4]',a0,opname,tmp AND 65535) | |
| ELSEIF (tmp:=InStr(adrmode,'@2'))>=0 | |
| StrCopy(tmpstring,adrmode,tmp) | |
| PrintF('\z\h[2] \z\h[2] \s\s\z\h[4]',a0,a1,opname,tmpstring,a16) | |
| MidStr(tmpstring,adrmode,tmp+4) | |
| PrintF('\s',tmpstring) | |
| ELSEIF (tmp:=InStr(adrmode,'@1'))>=0 | |
| StrCopy(tmpstring,adrmode,tmp) | |
| PrintF('\z\h[2] \s\s\z\h[2]',a0,opname,tmpstring,a0) | |
| MidStr(tmpstring,adrmode,tmp+2) | |
| PrintF('\s',tmpstring) | |
| ELSE | |
| PrintF('fucked up adrmode') | |
| ENDIF | |
| IF StrCmp(adrmode,' $@1')=TRUE THEN PrintF('\t') | |
| PrintF('\t A:\z\h[2] X:\z\h[2] Y:\z\h[2] SP:\z\h[2] SR:\z\h[2]\n',a,x,y,sp,status) | |
| ENDIF | |
| SELECT 256 OF m | |
| CASE $00 -> BRK | |
| incpc(2) | |
| push(hb(sp)) ; push(lb(sp)) | |
| setB | |
| push(status) | |
| setI | |
| sp:=deek($fffe) | |
| CASE $01 -> ORA ($01,x) | |
| setnz(a:=a OR peek(deek(a0+x))) | |
| CASE $05 -> ORA $01 | |
| setnz(a:=a OR peek(a0)) | |
| CASE $06 -> ASL $01 | |
| poke(a0,asl(peek(a0))) | |
| CASE $08 -> PHP | |
| push(status) | |
| CASE $09 -> ORA #$01 | |
| setnz(a:=a OR a0) | |
| CASE $0a -> ASL | |
| a:=asl(a) | |
| CASE $0d -> ORA $0201 | |
| setnz(a:=a OR peek(a16)) | |
| CASE $0e -> ASL $0201 | |
| poke(a16,asl(peek(a16))) | |
| CASE $10 -> BPL | |
| incpc(2) | |
| IF (status AND $80)=0 THEN incpc(a0) | |
| CASE $11 -> ORA ($01),y | |
| setnz(a:=a OR peek(deek(a0)+y)) | |
| CASE $15 -> ORA $01,x | |
| setnz(a:=a OR peek(a0+x)) | |
| CASE $16 -> ASL $01,x | |
| poke(a0+x,asl(peek(a0+x))) | |
| CASE $18 -> CLC | |
| clrC | |
| CASE $19 -> ORA $0201,y | |
| setnz(a:=a OR peek(a16+y)) | |
| CASE $1d -> ORA $0201,x | |
| setnz(a:=a OR peek(a16+x)) | |
| CASE $1e -> ASL $0201,x | |
| poke(a16+x,asl(peek(a16+x))) | |
| CASE $20 -> JSR $0201 | |
| incpc(3) | |
| push(hb(pc)) ; push(lb(pc)) | |
| pc:=a16 | |
| CASE $21 -> AND ($01,x) | |
| setnz(a:=a AND peek(deek(a0+x))) | |
| CASE $24 -> BIT $01 | |
| bit(peek(a0)) | |
| CASE $25 -> AND $01 | |
| setnz(a:=a AND peek(a0)) | |
| CASE $26 -> ROL $01 | |
| poke(a0,rol(peek(a0))) | |
| CASE $28 -> PLP | |
| status:=pull() | |
| CASE $29 -> AND #$01 | |
| setnz(a:=a AND a0) | |
| CASE $2a -> ROL | |
| a:=rol(a) | |
| CASE $2c -> BIT $0201 | |
| bit(peek(a16)) | |
| CASE $2d -> AND $0201 | |
| setnz(a:=a AND peek(a16)) | |
| CASE $2e -> ROL $0201 | |
| poke(a16,rol(peek(a16))) | |
| CASE $30 -> BMI | |
| incpc(2) | |
| IF (status AND $80) THEN incpc(a0) | |
| CASE $31 -> AND ($01),y | |
| setnz(a:=a AND peek(deek(a0)+y)) | |
| CASE $35 -> AND $01,x | |
| setnz(a:=a AND peek(a0+x)) | |
| CASE $36 -> ROL $01,x | |
| poke(a0+x,rol(peek(a0+x))) | |
| CASE $38 -> SEC | |
| setC | |
| CASE $39 -> AND $0201,y | |
| setnz(a:=a AND peek(a16+y)) | |
| CASE $3d -> AND $0201,x | |
| setnz(a:=a AND peek(a16+x)) | |
| CASE $3e -> ROL $0201,x | |
| poke(a16+x,rol(peek(a16+x))) | |
| CASE $40 -> RTI | |
| status:=pull() | |
| tmp:=pull() | |
| pc:=pull()*256+tmp | |
| CASE $41 -> EOR ($01,x) | |
| setnz(a:=Eor(a,peek(deek(a0+x)))) | |
| CASE $45 -> EOR $01 | |
| setnz(a:=Eor(a,peek(a0))) | |
| CASE $46 -> LSR $01 | |
| poke(a0,lsr(peek(a0))) | |
| CASE $48 -> PHA | |
| push(a) | |
| CASE $49 -> EOR #$01 | |
| setnz(a:=Eor(a,a0)) | |
| CASE $4a -> LSR | |
| a:=lsr(a) | |
| CASE $4c -> JMP $0201 | |
| pc:=a16 | |
| CASE $4d -> EOR $0201 | |
| setnz(a:=Eor(a,peek(a16))) | |
| CASE $4e -> LSR $0201 | |
| poke(a16,lsr(peek(a16))) | |
| CASE $50 -> BVC | |
| incpc(2) | |
| IF (status AND $40)=0 THEN incpc(a0) | |
| CASE $51 -> EOR ($01),y | |
| setnz(a:=Eor(a,peek(deek(a0)+y))) | |
| CASE $55 -> EOR $01,x | |
| setnz(a:=Eor(a,peek(a0+x))) | |
| CASE $56 -> LSR $01,x | |
| poke(a0+x,lsr(peek(a0+x))) | |
| CASE $58 -> CLI | |
| clrI | |
| CASE $59 -> EOR $0201,y | |
| setnz(a:=Eor(a,peek(a16+y))) | |
| CASE $5d -> EOR $0201,x | |
| setnz(a:=Eor(a,peek(a16+x))) | |
| CASE $5e -> LSR $0201,x | |
| poke(a16+x,lsr(peek(a16+x))) | |
| CASE $60 -> RTS | |
| tmp:=pull() | |
| pc:=pull()*256+tmp | |
| CASE $61 -> ADC ($01,x) | |
| adc(peek(deek(a0+x))) | |
| CASE $65 -> ADC $01 | |
| adc(peek(a0)) | |
| CASE $66 -> ROR $01 | |
| poke(a0,ror(peek(a0))) | |
| CASE $68 -> PLA | |
| a:=pull() | |
| CASE $69 -> ADC #$01 | |
| adc(a0) | |
| CASE $6a -> ROR | |
| a:=ror(a) | |
| CASE $6c -> JMP ($0201) | |
| pc:=deek(a16) | |
| CASE $6d -> ADC $0201 | |
| adc(peek(a16)) | |
| CASE $6e -> ROR $0201 | |
| poke(a16,ror(peek(a16))) | |
| CASE $70 -> BVS | |
| incpc(2) | |
| IF (status AND $40) THEN incpc(a0) | |
| CASE $71 -> ADC ($01),y | |
| adc(peek(deek(a0)+y)) | |
| CASE $75 -> ADC $01,x | |
| adc(peek(a0+x)) | |
| CASE $76 -> ROR $01,x | |
| poke(a0+x,ror(peek(a0+x))) | |
| CASE $78 -> SEI | |
| setI | |
| CASE $79 -> ADC $0201,y | |
| adc(peek(a16+y)) | |
| CASE $7d -> ADC $0201,x | |
| adc(peek(a16+x)) | |
| CASE $7e -> ROR $0201,x | |
| poke(a16+x,ror(peek(a16+x))) | |
| CASE $81 -> STA ($01,x) | |
| poke(deek(a0+x),a) | |
| CASE $84 -> STY $01 | |
| poke(a0,y) | |
| CASE $85 -> STA $01 | |
| poke(a0,a) | |
| CASE $86 -> STX $01 | |
| poke(a0,x) | |
| CASE $88 -> DEY | |
| setnz(y:=(y-1) AND 255) | |
| CASE $8a -> TXA | |
| setnz(a:=x) | |
| CASE $8c -> STY $0201 | |
| poke(a16,y) | |
| CASE $8d -> STA $0201 | |
| poke(a16,a) | |
| CASE $8e -> STX $0201 | |
| poke(a16,x) | |
| CASE $90 -> BCC | |
| incpc(2) | |
| IF (status AND 1)=0 THEN incpc(a0) | |
| CASE $91 -> STA ($01),y | |
| poke(deek(a0)+y,a) | |
| CASE $94 -> STY $01,x | |
| poke(a0+x,y) | |
| CASE $95 -> STA $01,x | |
| poke(a0+x,a) | |
| CASE $96 -> STX $01,y | |
| poke(a0+y,x) | |
| CASE $98 -> TYA | |
| setnz(a:=y) | |
| CASE $99 -> STA $0201,y | |
| poke(a16+y,a) | |
| CASE $9a -> TXS | |
| sp:=x | |
| CASE $9d -> STA $0201,x | |
| poke(a16+x,a) | |
| CASE $a0 -> LDY #$01 | |
| setnz(y:=a0) | |
| CASE $a1 -> LDA ($01,x) | |
| setnz(a:=peek(deek(a0+x))) | |
| CASE $a2 -> LDX #$01 | |
| setnz(x:=a0) | |
| CASE $a4 -> LDY $01 | |
| setnz(y:=peek(a0)) | |
| CASE $a5 -> LDA $01 | |
| setnz(a:=peek(a0)) | |
| CASE $a6 -> LDX $01 | |
| setnz(x:=peek(a0)) | |
| CASE $a8 -> TAY | |
| setnz(y:=a) | |
| CASE $a9 -> LDA #$01 | |
| setnz(a:=a0) | |
| CASE $aa -> TAX | |
| setnz(x:=a) | |
| CASE $ac -> LDY $0201 | |
| setnz(y:=peek(a16)) | |
| CASE $ad -> LDA $0201 | |
| setnz(a:=peek(a16)) | |
| CASE $ae -> LDX $0201 | |
| setnz(x:=peek(a16)) | |
| CASE $b0 -> BCS | |
| incpc(2) | |
| IF (status AND 1) THEN incpc(a0) | |
| CASE $b1 -> LDA ($01),y | |
| setnz(a:=peek(deek(a0)+y)) | |
| CASE $b4 -> LDY $01,x | |
| setnz(y:=peek(a0+x)) | |
| CASE $b5 -> LDA $01,x | |
| setnz(a:=peek(a0+x)) | |
| CASE $b6 -> LDX $01,y | |
| setnz(x:=peek(a0+y)) | |
| CASE $b8 -> CLV | |
| clrV | |
| CASE $b9 -> LDA $0201,y | |
| setnz(a:=peek(a16+y)) | |
| CASE $ba -> TSX | |
| setnz(x:=sp) | |
| CASE $bc -> LDY $0201,x | |
| setnz(y:=peek(a16+x)) | |
| CASE $bd -> LDA $0201,x | |
| setnz(a:=peek(a16+x)) | |
| CASE $be -> LDX $0201,y | |
| setnz(x:=peek(a16+y)) | |
| CASE $c0 -> CPY #$01 | |
| cmp(y,a0) | |
| CASE $c1 -> CMP ($01,x) | |
| cmp(a,peek(deek(a0+x))) | |
| CASE $c4 -> CPY $01 | |
| cmp(y,peek(a0)) | |
| CASE $c5 -> CMP $01 | |
| cmp(a,peek(a0)) | |
| CASE $c6 -> DEC $01 | |
| setnz(poke(a0,(peek(a0)-1) AND 255)) | |
| CASE $c8 -> INY | |
| setnz(y:=(y+1) AND 255) | |
| CASE $c9 -> CMP #$01 | |
| cmp(a,a0) | |
| CASE $ca -> DEX | |
| setnz(x:=(x-1) AND 255) | |
| CASE $cc -> CPY $0201 | |
| cmp(y,peek(a16)) | |
| CASE $cd -> CMP $0201 | |
| cmp(a,peek(a16)) | |
| CASE $ce -> DEC $0201 | |
| setnz(poke(a16,(peek(a16)-1) AND 255)) | |
| CASE $d0 -> BNE | |
| incpc(2) | |
| IF (status AND $02)=0 THEN incpc(a0) | |
| CASE $d1 -> CMP ($01),y | |
| cmp(a,peek(deek(a0)+y)) | |
| CASE $d5 -> CMP $01,x | |
| cmp(a,peek(a0+x)) | |
| CASE $d6 -> DEC $01,x | |
| setnz(poke(a0+x,(peek(a0+x)-1) AND 255)) | |
| CASE $d8 -> CLD | |
| clrD | |
| CASE $d9 -> CMP $0201,y | |
| cmp(a,peek(a16+y)) | |
| CASE $dd -> CMP $0201,x | |
| cmp(a,peek(a16+x)) | |
| CASE $de -> DEC $0201,x | |
| setnz(poke(a16+x,(peek(a16+x)-1) AND 255)) | |
| CASE $e0 -> CPX #$01 | |
| cmp(x,a0) | |
| CASE $e1 -> SBC ($01,x) | |
| sbc(peek(deek(a0+x))) | |
| CASE $e4 -> CPX $01 | |
| cmp(x,peek(a0)) | |
| CASE $e5 -> SBC $01 | |
| sbc(peek(a0)) | |
| CASE $e6 -> INC $01 | |
| setnz(poke(a0,(peek(a0)+1) AND 255)) | |
| CASE $e8 -> INX | |
| setnz(x:=(x+1) AND 255) | |
| CASE $e9 -> SBC #$01 | |
| sbc(a0) | |
| CASE $ea -> NOP | |
| -> NOP :) | |
| CASE $ec -> CPX $0201 | |
| cmp(x,peek(a16)) | |
| CASE $ed -> SBC $0201 | |
| sbc(peek(a16)) | |
| CASE $ee -> INC $0201 | |
| setnz(poke(a16,(peek(a16)+1) AND 255)) | |
| CASE $f0 -> BEQ | |
| incpc(2) | |
| IF (status AND $02) THEN incpc(a0) | |
| CASE $f1 -> SBC ($01),y | |
| sbc(peek(deek(a0)+y)) | |
| CASE $f5 -> SBC $01,x | |
| sbc(peek(a0+x)) | |
| CASE $f6 -> INC $01,x | |
| setnz(poke(a0+x,(peek(a0+x)+1) AND 255)) | |
| CASE $f8 -> SED | |
| setD | |
| CASE $f9 -> SBC $0201,y | |
| sbc(peek(a16+y)) | |
| CASE $fd -> SBC $0201,x | |
| sbc(peek(a16+x)) | |
| CASE $fe -> INC $0201,x | |
| setnz(poke(a16+x,(peek(a16+x)+1) AND 255)) | |
| DEFAULT | |
| state:=1 | |
| ENDSELECT | |
| incpc(size[m]) | |
| cyclecount:=cyclecount+time[m] | |
| ENDPROC state | |
| PROC bit(val) | |
| IF a AND val THEN clrZ ELSE setZ | |
| IF val AND 128 THEN setN ELSE clrN | |
| IF val AND 64 THEN setV ELSE clrV | |
| ENDPROC | |
| PROC asl(val) | |
| val:=Shl(val,1) | |
| IF val>255 THEN setC ELSE clrC | |
| val:=val AND 255 | |
| setnz(val) | |
| ENDPROC val | |
| PROC lsr(val) | |
| IF val AND 1 THEN setC ELSE clrC | |
| val:=Shr(val,1) | |
| setnz(val) | |
| ENDPROC val | |
| PROC rol(val) | |
| DEF tmp | |
| tmp:=(status AND 1) | |
| val:=tmp OR asl(val) | |
| ENDPROC val | |
| PROC ror(val) | |
| DEF tmp | |
| tmp:=(status AND 1) | |
| IF val AND 1 THEN setC ELSE clrC | |
| val:=Shr(val,1) OR (tmp*128) | |
| setnz(val) | |
| ENDPROC val | |
| PROC adc(val) -> finally working! | |
| DEF tmp | |
| IF (status AND $08) THEN PrintF('No decimal mode emulation - doing binary ADC\n') | |
| tmp:=a | |
| a:=a+val+(status AND 1) | |
| IF a>255 | |
| setC | |
| a:=a AND 255 | |
| ELSE | |
| clrC | |
| ENDIF | |
| setnz(a) | |
| IF (tmp<$80) AND (val<$80) AND (a>=$80) | |
| setV | |
| ELSEIF (tmp>=$80) AND (val>=$80) AND (a<$80) | |
| setV | |
| ELSE | |
| clrV | |
| ENDIF | |
| ENDPROC | |
| PROC sbc(val) | |
| DEF tmp | |
| IF (status AND $08) THEN PrintF('No decimal mode emulation - doing binary SBC\n') | |
| tmp:=a | |
| a:=a-val+(status AND 1)-1 | |
| IF a<0 | |
| clrC | |
| a:=a AND 255 | |
| ELSE | |
| setC | |
| ENDIF | |
| setnz(a) | |
| IF (tmp<$80) AND (val>=$80) AND (a>=$80) | |
| setV | |
| ELSEIF (tmp>=$80) AND (val<$80) AND (a<$80) | |
| setV | |
| ELSE | |
| clrV | |
| ENDIF | |
| ENDPROC | |
| PROC cmp(t1,t2) -> ugh, fix the kludge | |
| DEF tmp | |
| tmp:=t1-t2 | |
| IF tmp<0 | |
| clrC | |
| tmp:=tmp AND 255 | |
| ELSE | |
| setC | |
| ENDIF | |
| setnz(tmp) | |
| ENDPROC |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -> 6510 object | |
| OPT PREPROCESS | |
| OBJECT proc6510 | |
| a:CHAR | |
| x:CHAR | |
| y:CHAR | |
| sp:CHAR | |
| pc:WORD | |
| /* 84218421 */ | |
| /* NV#BDIZC */ | |
| status:CHAR | |
| ioport:CHAR | |
| ddr:CHAR | |
| PRIVATE | |
| peek:PTR TO LONG | |
| poke:PTR TO LONG | |
| resetState:CHAR | |
| nmiState:CHAR | |
| irqState:CHAR | |
| ENDOBJECT | |
| PROC start(pokefunc,peekfunc) OF proc6510 | |
| self.peek:=peekfunc | |
| self.poke:=pokefunc | |
| self.reset() | |
| ENDPROC | |
| PROC reset() OF proc6510 | |
| self.ioport:=$37 | |
| self.ddr:=$2f | |
| self.pc:=self.deek($fffc) | |
| self.sp:=255 | |
| self.status:=$20 | |
| self.a:=0 | |
| self.x:=0 | |
| self.y:=0 | |
| self.resetcycles() | |
| self.resetState:=FALSE | |
| self.nmiState:=FALSE | |
| self.irqState:=FALSE | |
| ENDPROC | |
| PROC nmi() OF proc6510 | |
| push(hb(self.pc)) ; push(lb(self.pc)) | |
| push(self.status) | |
| self.pc:=deek($fffa) | |
| self.addcycles(7) | |
| self.nmiState:=FALSE | |
| self.irqState:=FALSE | |
| ENDPROC | |
| PROC irq() OF proc6510 | |
| push(hb(self.pc)) ; push(lb(self.pc)) | |
| push(self.status) | |
| self.pc:=deek($fffe) | |
| self.addcycles(7) | |
| self.irqState:=FALSE | |
| ENDPROC | |
| PROC emulate() OF proc6510 | |
| DEF state=0 | |
| ENDPROC state |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ hexdump 6510SIZE.TAB | |
| 0000000 01 02 01 02 02 02 02 02 01 02 01 01 03 03 03 03 | |
| 0000010 00 02 01 02 02 02 02 02 01 03 01 03 02 03 03 03 | |
| 0000020 00 02 01 02 02 02 02 02 01 02 01 01 03 03 03 03 | |
| 0000030 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 0000040 00 02 01 02 02 02 02 02 01 02 01 01 00 03 03 03 | |
| 0000050 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 0000060 00 02 01 02 02 02 02 02 01 02 01 01 00 03 03 03 | |
| 0000070 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 0000080 02 02 02 02 02 02 02 02 01 02 01 02 03 03 03 03 | |
| 0000090 00 02 01 03 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 00000a0 02 02 02 02 02 02 02 02 01 02 01 01 03 03 03 03 | |
| 00000b0 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 00000c0 02 02 02 02 02 02 02 02 01 02 01 02 03 03 03 03 | |
| 00000d0 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 00000e0 02 02 02 03 02 02 02 02 01 02 01 01 03 03 03 03 | |
| 00000f0 00 02 01 02 02 02 02 02 01 03 01 03 03 03 03 03 | |
| 0000100 | |
| $ hexdump -v 6510TIME.TAB | |
| 0000000 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000010 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000020 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000030 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000040 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000050 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000060 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000070 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000080 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000090 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000a0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000b0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000c0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000d0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000e0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 00000f0 74 6a 6f 73 61 6e 74 6a 6f 73 61 6e 74 6a 6f 0a | |
| 0000100 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment