I need help from someone here who has written an Apple II emulator (or else knows a lot about how it works) and knows how to program in HyperTalk. I'm writing an Apple II emulator, and when I run it I get into an infinite loop. Here is what I found out the emulated processor was doing: $0000- BRK $C803- CLV $C804- PHA $C805- PHX $C806- TSX $C807- PLA $C808- PLA $C809- PLA $C80A- TXS $C80B- PHY $C80C- LDX $C066 $C80F- LDY $C067 $C812- CLD $C813- AND #$10 $C815- CMP #$10 $C817- LDA $C018 $C81A- AND $C01C $C81D- AND #$80 $C81F- BEQ +5 <<-- this in particular is what doesn't look right $0000- BRK <<-- BEQ instruction jumps to $0000 ????? Below I have my HyperTalk script for the processor emulation. Also, is there information somewhere that would tell someone who doesn't know C or C++ how to emulate game I/O, vertical blanking, disk images, mouse and clock cards, etc.? Does game I/O and vertical blanking require counting clock cycles or something? What I/O memory locations do you use to control the disk drive, get the mouse coordinates, and so on? -- HyperTalk script: Note: mpeek and mpoke are functions I put in the Apple II MMU script, which is seperate -- -- Carbon Dioxide 65C02 Emulator Core -- version 1.0 -- © 2001 Kreative Software, a division of Kreative Korp. -- http://kreativekorp.cjb.net -- on sixfiveohtwo -- this is the handler that emulates the 65C02 processor global C02_A, C02_X, C02_Y, C02_S, C02_P, C02_PC put C02_A into oldA put C02_X into oldX put C02_Y into oldY put decodeInstruction(d2h(mpeek(C02_PC),2)) into theInst add 1 to C02_PC put d2b(C02_P) into f put (char 1 of f is "1") into pfNegative put (char 2 of f is "1") into pfOverflow put (char 3 of f is "1") into pfWhatever put (char 4 of f is "1") into pfBreak put (char 5 of f is "1") into pfDecimal put (char 6 of f is "1") into pfInterrupt put (char 7 of f is "1") into pfZero put (char 8 of f is "1") into pfCarry put empty into operand if "MM" is in word 2 of theInst then put mpeek(C02_PC) + (256*mpeek(C02_PC + 1)) into operand add 2 to C02_PC else if "M" is in word 2 of theInst then put mpeek(C02_PC) into operand add 1 to C02_PC else if word 2 of theInst = "#N" then put "#" & mpeek(C02_PC) into operand add 1 to C02_PC end if if "M" is in word 2 of theInst then put decodeAddrMode(word 2 of theInst,operand) into operand delete word 2 of theInst -- at this moment, theInst contains the instruction mneumonic (PLA, STX, BRK, etc) -- and operand contains a memory address or a number (with "#" before it) or nothing -- doing the easy stuff first :) if char 1 to 2 of theInst = "cl" then changeFlagState (char 3 of theInst),false if char 1 to 2 of theInst = "se" then changeFlagState (char 3 of theInst),true if theInst = "tax" then put C02_A into C02_X if theInst = "tay" then put C02_A into C02_Y if theInst = "tsx" then put C02_S into C02_X if theInst = "txs" then put C02_X into C02_S if theInst = "txa" then put C02_X into C02_A if theInst = "tya" then put C02_Y into C02_A if theInst = "pha" then pushStack C02_A if theInst = "pla" then put popStack() into C02_A if theInst = "phx" then pushStack C02_X if theInst = "plx" then put popStack() into C02_X if theInst = "phy" then pushStack C02_Y if theInst = "ply" then put popStack() into C02_Y if theInst = "php" then pushStack C02_P if theInst = "plp" then put popStack() into C02_P if theInst = "lda" then put operandValue(operand) into C02_A if theInst = "ldx" then put operandValue(operand) into C02_X if theInst = "ldy" then put operandValue(operand) into C02_Y if theInst = "sta" then mpoke operand,C02_A if theInst = "stx" then mpoke operand,C02_X if theInst = "sty" then mpoke operand,C02_Y if theInst = "inx" then add 1 to C02_X if theInst = "iny" then add 1 to C02_Y if theInst = "dex" then subtract 1 from C02_X if theInst = "dey" then subtract 1 from C02_Y if theInst = "bcc" and not pfCarry then put operand into C02_PC if theInst = "bcs" and pfCarry then put operand into C02_PC if theInst = "beq" and pfZero then put operand into C02_PC if theInst = "bmi" and pfNegative then put operand into C02_PC if theInst = "bne" and not pfZero then put operand into C02_PC if theInst = "bpl" and not pfNegative then put operand into C02_PC if theInst = "bvc" and not pfOverflow then put operand into C02_PC if theInst = "bvs" and pfOverflow then put operand into C02_PC if theInst = "bra" or theInst = "jmp" then put operand into C02_PC if theInst = "inc" and operand is empty then add 1 to C02_A if theInst = "dec" and operand is empty then subtract 1 from C02_A if theInst = "and" then put binLogic(operandValue(operand),C02_A,"and") into C02_A if theInst = "eor" then put binLogic(operandValue(operand),C02_A,"xor") into C02_A if theInst = "ora" then put binLogic(operandValue(operand),C02_A,"or") into C02_A if theInst is in "asl lsr rol ror" and operand is empty then put bitshift(C02_A,theInst) into C02_A if theInst is in "asl lsr rol ror" and operand is not empty then mpoke operand,bitshift(mpeek(operand),theInst) -- now we get to the harder stuff if theInst = "inc" and operand is not empty then put mpeek(operand)+1 into v if v > 255 then subtract 256 from v changeFlagState "v",true end if mpoke operand,v end if if theInst = "dec" and operand is not empty then put mpeek(operand)-1 into v if v < 0 then add 256 to v changeFlagState "v",true end if mpoke operand,v end if if theInst = "jsr" then put C02_PC - 1 into a pushStack (a DIV 256) pushStack (a MOD 256) put operand into C02_PC end if if theInst = "rts" then put popStack() into a put popStack() into b put (256*b)+a+1 into C02_PC end if if theInst = "brk" then pushStack (C02_PC DIV 256) pushStack (C02_PC MOD 256) pushStack C02_P changeFlagState "b",true put mpeek(65534) + (256*mpeek(65535)) into C02_PC -- interrupt vector end if if theInst = "rti" then put popStack() into C02_P put popStack() into a put popStack() into b put (256*b)+a into C02_PC end if if theInst = "bit" then put operandValue(operand) into x if x > 127 then subtract 128 from x changeFlagState "n",true else changeFlagState "n",false if x > 63 then changeFlagState "v",true else changeFlagState "v",false end if if theInst = "adc" then put operandValue(operand) into x add x to C02_A if C02_A > 255 then subtract 256 from C02_A changeFlagState "v",true end if end if if theInst = "sbc" then put operandValue(operand) into x subtract x from C02_A if C02_A < 0 then add 256 to C02_A changeFlagState "v",false end if end if if theInst = "cmp" then put operandValue(operand) into x put C02_A into y changeFlagState "z",(x=y) changeFlagState "n",(not (x>y)) end if if theInst = "cpx" then put operandValue(operand) into x put C02_X into y changeFlagState "z",(x=y) changeFlagState "n",(not x>y) end if if theInst = "cpy" then put operandValue(operand) into x put C02_Y into y changeFlagState "z",(x=y) changeFlagState "n",(not x>y) end if if theInst is not in "cmp cpx cpy" then -- the above instructions are the ones exempt from neg/zero check -- instructions that don't change accumulator or indexes need not -- be exempted, since the following would never then execute if C02_A <> oldA then changeFlagState "n",(C02_A>127) changeFlagState "z",(C02_A=0) end if if C02_X <> oldX then changeFlagState "n",(C02_X>127) changeFlagState "z",(C02_X=0) end if if C02_Y <> oldY then changeFlagState "n",(C02_Y>127) changeFlagState "z",(C02_Y=0) end if end if changeFlagState "v",false if C02_A > 255 then subtract 256 from C02_A changeFlagState "v",true end if if C02_X > 255 then subtract 256 from C02_X changeFlagState "v",true end if if C02_Y > 255 then subtract 256 from C02_Y changeFlagState "v",true end if if C02_A < 0 then add 256 to C02_A changeFlagState "v",true end if if C02_X < 0 then add 256 to C02_X changeFlagState "v",true end if if C02_Y < 0 then add 256 to C02_Y changeFlagState "v",true end if if C02_S > 255 then subtract 256 from C02_S if C02_S < 0 then add 256 to C02_S -- stack overflow, but we don't seem to care if C02_PC > 65535 then subtract 65536 from C02_PC -- probably another thing that would normally cause a crash end sixfiveohtwo function decodeInstruction h -- this decodes the 65C02 opcode! if char 2 of h is in "3B" then return "NOP N/A" put offset(char 1 of h,"123456789ABCDEF") into a if char 2 of h is in "159D" then if h = "89" then return "bit #N" -- only exception to the pattern put item ((a DIV 2) + 1) of "ora,and,eor,adc,sta,lda,cmp,sbc" into r put offset(char 2 of h,"159D")*2 into b if (a/2) = (a DIV 2) then subtract 1 from b put space & word b of "(M,X) (M),Y M M,X #N MM,Y MM MM,X" after r return r end if if char 2 of h is in "7F" then put char (a DIV 8)+1 of "rs" into r if char 2 of h = "7" then put "mb" after r else put "bb" before r put (a MOD 8) after r if char 2 of h = "7" then put " M" after r if char 2 of h = "F" then put " +/-M" after r return r end if if char 2 of h is "8" then return (item a+1 of "php,clc,plp,sec,pha,cli,pla,sei,dey,tya,tay,clv,iny,cld,inx,sed") && "N/A" if char 2 of h is "A" then return (item a+1 of "asl,inc,rol,dec,lsr,phy,ror,ply,txa,txs,tax,tsx,dex,phx,nop,plx") && "N/A" if char 2 of h is in "6E" then if h = "9E" then return "stz MM,X" -- only exception to the pattern put (item ((a DIV 2) + 1) of "asl,rol,lsr,ror,stx,ldx,dec,inc") && "M" into r if char 2 of h = "E" then put "M" after r if (a/2) = (a DIV 2) then return r if (char 2 of h is "6") then return r & comma & char ((a+1)/2) of "XXXXYYXX" if (char 2 of h is "E") then return r & comma & char ((a+1)/2) of "XXXXXYXX" end if if char 2 of h = "2" then put item a+1 of "nop,ora,nop,and,nop,eor,nop,adc,nop,sta,ldx,lda,nop,cmp,nop,sbc" into r if r = "nop" then return r && "N/A" if r = "ldx" then return r && "#N" return r && "(M)" end if if char 2 of h = "4" then put item a+1 of "tsb,trb,bit,bit,nop,nop,stz,stz,sty,sty,ldy,ldy,cpy,nop,cpx,nop" into r return r && word a+1 of "M M M M,X N/A N/A M M,X M M,X M M,X M N/A M N/A" end if if char 2 of h = "C" then put item a+1 of "tsb,trb,bit,bit,jmp,nop,jmp,jmp,sty,stz,ldy,ldy,cpy,nop,cpx,nop" into r return r && word a+1 of "MM MM MM MM,X MM N/A (MM) (MM,X) MM MM MM MM,X MM N/A MM N/A" end if if char 2 of h = "0" then put item a+1 of "brk,bpl,jsr,bmi,rti,bvc,rts,bvs,bra,bcc,ldy,bcs,cpy,bne,cpx,beq" into r if (a/2) <> (a DIV 2) then return r && "+/-M" return r && word (a/2)+1 of "N/A MM N/A N/A +/-M #N #N #N" end if end decodeInstruction function decodeAddrMode origMA,addrMode global C02_X, C02_Y, C02_PC if addrMode = "M" or addrMode = "MM" then return origMA -- absolute if addrMode = "(M,X)" or addrMode = "(MM,X)" then return mpeek(origMA+C02_X)+(256*mpeek(origMA+C02_X+1)) -- indexed indirect if addrMode = "(M,Y)" or addrMode = "(MM,Y)" then return mpeek(origMA+C02_Y)+(256*mpeek(origMA+C02_Y+1)) -- indexed indirect if addrMode = "(M),X" or addrMode = "(MM),X" then return mpeek(origMA)+(256*mpeek(origMA+1))+C02_X -- indirect indexed if addrMode = "(M),Y" or addrMode = "(MM),Y" then return mpeek(origMA)+(256*mpeek(origMA+1))+C02_Y -- indirect indexed if addrMode = "M,X" or addrMode = "MM,X" then return origMA+C02_X -- absolute indexed if addrMode = "M,Y" or addrMode = "MM,Y" then return origMA+C02_Y -- absolute indexed if addrMode = "(M)" or addrMode = "(MM)" then return mpeek(origMA)+(256*mpeek(origMA+1)) -- indirect if addrMode = "+/-M" or addrMode = "+/-MM" then -- relative put origMa into r if r > 127 then subtract 256 from r return r + C02_PC -- may have to adjust a little afterwards if the program counter is off, though end if end decodeAddrMode on changeFlagState x,y global C02_P put "nvwbdizc" into flagcodes put d2b(C02_P) into b if y then put "1" into char offset(x,flagcodes) of b else put "0" into char offset(x,flagcodes) of b put b2d(b) into C02_P end changeFlagState function getFlagState x global C02_P put "nvwbdizc" into flagcodes put d2b(C02_P) into b return (char offset(x,flagcodes) of b is "1") end getFlagState on pushStack x global C02_S, C02_Running mpoke (256+C02_S),x subtract 1 from C02_S if C02_S < 0 then -- ooops! answer "Warning! Warning! 65C02 stack crashed into zero page. Should I continue?" with "Yes" or "No" if it is "No" then put false into C02_Running -- if using this variable for emulation control exit to hypercard else put 255 into C02_S end if end pushStack function popStack x global C02_S put mpeek(257+C02_S) into v add 1 to C02_S if C02_S > 255 then put 255 into C02_S -- not so serious, I think return v end popStack function bitshift val,typ -- use this to deal with asl, lsr, rol, and ror if typ = "asl" then put val*2 into x if x > 255 then subtract 256 from x return x else if typ = "lsr" then put val DIV 2 into x return x else if typ = "rol" then put val*2 into x if getFlagState("c") then add 1 to x if x > 255 then subtract 256 from x changeFlagState "c",true else changeFlagState "c",false return x else if typ = "ror" then put val/2 into x if getFlagState("c") then add 128 to x if x <> (x DIV 1) then subtract .5 from x changeFlagState "c",true else changeFlagState "c",false return x end if end bitshift function binlogic val,valu,typ -- use this to deal with and, eor, ora, and other logic functions put d2b(val) into a put d2b(valu) into b put empty into r if char 1 of typ = "n" then delete char 1 of typ put "0" into rv else put "1" into rv repeat with x = 1 to 8 put char x of a into c put char x of b into d put "0" into char x of r if rv="0" then put "1" into char x of r if typ="and" and c="1" and d="1" then put rv into char x of r if typ="or" and (c="1" or d="1") then put rv into char x of r if typ="xor" and c="1" and d="0" then put rv into char x of r if typ="xor" and d="1" and c="0" then put rv into char x of r end repeat return b2d(r) end binlogic function operandValue a if char 1 of a = "#" then delete char 1 of a return a else return mpeek(a) end operandValue on hitResetPin -- starts up the 65C02 processor global C02_A,C02_X,C02_Y,C02_S,C02_P,C02_PC put 0 into C02_A put 0 into C02_X put 0 into C02_Y put 255 into C02_S put 0 into C02_P put mpeek(65532) + (256*mpeek(65533)) into C02_PC -- reset vector end hitResetPin on hitIRQpin if getFlagState("i") then exit hitIRQpin pushStack (C02_PC DIV 256) pushStack (C02_PC MOD 256) pushStack C02_P changeFlagState("b",false) put mpeek(65534) + (256*mpeek(65535)) into C02_PC -- interrupt vector end hitIRQpin on hitNMIpin pushStack (C02_PC DIV 256) pushStack (C02_PC MOD 256) pushStack C02_P put mpeek(65530) + (256*mpeek(65531)) into C02_PC -- nmi vector end hitNMIpin function d2h x, r put empty into h repeat r put x MOD 16 into y put x DIV 16 into x put char (y+1) of "0123456789ABCDEF" before h end repeat return h end d2h function h2d x put 0 into r repeat with n = the number of chars in x down to 1 put (the number of chars in x) - n into p put offset(char n of x,"123456789ABCDEF") into z add (z*(16^p)) to r end repeat return r end h2d function d2b x put empty into r repeat with c = 7 down to 0 if x > (2^c) or x = (2^c) then put "1" after r subtract (2^c) from x else put "0" after r end repeat return r end d2b function b2d x put 0 into r repeat with n = 1 to the number of chars in x put (the number of chars in x) - n into p if char n of x = "1" then add (2^p) to r end repeat return r end b2d function disasmLine addr put addr into VirtualPC -- :) virtual program counter put decodeInstruction(d2h(mpeek(VirtualPC),2)) into theInst add 1 to VirtualPC put empty into operand if word 2 of theInst = "+/-M" then put mpeek(VirtualPC) into operand if operand > 127 then subtract 256 from operand if operand > -1 then put "+" before operand put operand into word 2 of theInst add 1 to VirtualPC else if "MM" is in word 2 of theInst then put offset("MM",word 2 of theInst) into f put mpeek(VirtualPC) + (256*mpeek(VirtualPC + 1)) into operand put ("$" & d2h(operand,4)) into char f to (f+1) of word 2 of theInst add 2 to VirtualPC else if "M" is in word 2 of theInst then put offset("M",word 2 of theInst) into f put mpeek(VirtualPC) into operand put ("$" & d2h(operand,2)) into char f of word 2 of theInst add 1 to VirtualPC else if word 2 of theInst = "#N" then put mpeek(VirtualPC) into operand put ("#$" & d2h(operand,2)) into char 2 of word 2 of theInst if char 2 of word 2 of theInst = "#" then delete char 2 of word 2 of theInst add 1 to VirtualPC else if word 2 of theInst = "N/A" then delete word 2 of theInst end if return theInst & return & VirtualPC end disasmLine -----= Posted via Newsfeeds.Com, Uncensored Usenet News =----- http://www.newsfeeds.com - The #1 Newsgroup Service in the World! -----== Over 80,000 Newsgroups - 16 Different Servers! =----- Update: I fixed some of the problems I was having (swapped parameters on the DecodeAddrMode function and checking for overflow _after_ checking for zero/negative instead of before). I now have it down to a smaller loop: $D511- C8 INY $D512- B1 5E LDA ($5E),Y $D514- D0 FB BNE -5 $D511- C8 INY In ApplePC, calling this address [$D511], at least after a complete startup, gets me an Applesoft prompt. In my emulator, it seems to be executing this loop over and over again and I don't even have 'Apple //c' across the screen yet. -----= Posted via Newsfeeds.Com, Uncensored Usenet News =----- http://www.newsfeeds.com - The #1 Newsgroup Service in the World! -----== Over 80,000 Newsgroups - 16 Different Servers! =-----