From e49226802530c8f9fd836c7b602b9c7f4e08ef1c Mon Sep 17 00:00:00 2001 From: byuu Date: Sun, 9 Jul 2006 05:32:10 +0000 Subject: [PATCH] Update to bsnes v016r27a release. Ok, I tried converting the switch/case table to a jump table for both CPU+APU cores. Results? EXE is 70kb larger, compile time is 5-10% slower, and speed is identical. Needless to say I reverted that change back. I then tried narrowing down the cause of the PGO error. Found out it was Dai Kaijuu Monogatari. If I don't run that, I can build with PGO. Unfortunately, this is the ROM I use to stress optimize color add/sub. So as a result, this game will run a little slowly now (sort of like how Chrono Trigger's OPT title screen effects were before). But, better one game than all, right? byuu.org/files/bsnes_v016_wip27a.zip Once again, please do not submit news about this to an emulation site. The file will be removed if I notice anyone mentioning it anywhere. That will be 20-25% faster than wip27, but otherwise everything is identical. DSP1: there's either a bug in op02, op06, or in the getSr/getDr/setDr functions. We have so far been unable to spot the error and correct it. Help is always welcome, as always. Please consider DSP-1 support as not being there at all. I doubt any games will work right with it right now :( This is how interlace works : I call each frame a "field", meaning even or odd fields on your television / monitor. When interlace is off, I draw to the even fields every time, so you don't notice anything. However, when interlace is on, I alternate between which one I draw to each field. So depending on your frameskip, this can cause serious problems for interlace mode. I also only physically draw to "half" the resolution each field, much like a real TV would. This makes 512x448 mode just as fast as 512x224 mode. I can't think of an easy way to cheat the system with frameskipping. Luckily, very very few games use interlace at all. Most use hires 512x224 and that's it. --- bsnes.exe | Bin 0 -> 1142784 bytes src/apu/apu.h | 14 +- src/apu/apuregs.h | 38 +- src/apu/bapu/bapu.cpp | 8 +- src/apu/bapu/bapu.h | 2 +- src/apu/bapu/core/clean.bat | 7 - src/apu/bapu/core/op_mov.b | 7 +- src/apu/bapu/core/op_mov.cpp | 2 - src/apu/bapu/memory/memory.cpp | 8 - src/apu/bapu/memory/memory.h | 3 - src/apu/bapu/timing/timing.cpp | 8 +- src/apu/bapu/timing/timing.h | 2 +- src/apu/sapu/core/cc.bat | 3 + src/apu/sapu/core/clean.bat | 1 + src/apu/sapu/core/core.cpp | 27 + src/apu/sapu/core/core.h | 24 + src/apu/sapu/core/op_misc.b | 175 ++ src/apu/sapu/core/op_misc.cpp | 370 ++++ src/apu/sapu/core/op_mov.b | 212 +++ src/apu/sapu/core/op_mov.cpp | 381 ++++ src/apu/sapu/core/op_pc.b | 180 ++ src/apu/sapu/core/op_pc.cpp | 604 ++++++ src/apu/sapu/core/op_read.b | 199 ++ src/apu/sapu/core/op_read.cpp | 745 ++++++++ src/apu/sapu/core/op_rmw.b | 61 + src/apu/sapu/core/op_rmw.cpp | 236 +++ src/apu/sapu/core/opfn.cpp | 138 ++ src/apu/sapu/core/sapugen.cpp | 18 + src/apu/sapu/memory/memory.cpp | 197 ++ src/apu/sapu/memory/memory.h | 24 + src/apu/sapu/sapu.cpp | 73 + src/apu/sapu/sapu.h | 32 + src/apu/sapu/timing/timing.cpp | 35 + src/apu/sapu/timing/timing.h | 11 + src/base.h | 34 +- src/cart/cart.cpp | 29 +- src/cart/cart.h | 8 + src/chip/dsp1/_dsp1emu.cpp | 1617 ++++++++++++++++ src/chip/dsp1/_dsp1emu.h | 126 ++ src/chip/dsp1/dsp1.cpp | 54 + src/chip/dsp1/dsp1.h | 16 + src/chip/dsp1/dsp1emu.cpp | 1622 ++++++++++++++++ src/chip/dsp1/dsp1emu.h | 127 ++ src/chip/dsp2/dsp2.h | 13 +- src/config/config.cpp | 2 +- src/cpu/bcpu/bcpu.cpp | 11 +- src/cpu/bcpu/bcpu.h | 2 +- src/cpu/bcpu/bcpu_exec.cpp | 15 +- src/cpu/bcpu/bcpu_int.cpp | 5 +- src/cpu/bcpu/bcpu_mmio.cpp | 21 +- src/cpu/bcpu/core/clean.bat | 7 - src/cpu/bcpu/dma/dma.cpp | 85 +- src/cpu/bcpu/dma/dma.h | 7 +- src/cpu/bcpu/timing/timing.cpp | 61 +- src/cpu/cpu.h | 37 +- src/cpu/cpuregs.h | 99 +- src/cpu/dcpu.cpp | 694 +++---- src/cpu/scpu/core/cc.bat | 3 + src/cpu/scpu/core/clean.bat | 1 + src/cpu/scpu/core/core.cpp | 71 + src/cpu/scpu/core/core.h | 58 + src/cpu/scpu/core/op_misc.b | 276 +++ src/cpu/scpu/core/op_misc.cpp | 530 ++++++ src/cpu/scpu/core/op_pc.b | 160 ++ src/cpu/scpu/core/op_pc.cpp | 273 +++ src/cpu/scpu/core/op_read.b | 317 ++++ src/cpu/scpu/core/op_read.cpp | 1651 +++++++++++++++++ src/cpu/scpu/core/op_rmw.b | 181 ++ src/cpu/scpu/core/op_rmw.cpp | 570 ++++++ src/cpu/scpu/core/op_write.b | 181 ++ src/cpu/scpu/core/op_write.cpp | 290 +++ src/cpu/scpu/core/opfn.cpp | 377 ++++ src/cpu/scpu/core/scpugen.cpp | 18 + src/cpu/scpu/dma/dma.cpp | 252 +++ src/cpu/scpu/dma/dma.h | 67 + src/cpu/scpu/memory/memory.cpp | 38 + src/cpu/scpu/memory/memory.h | 33 + src/cpu/scpu/mmio/mmio.cpp | 669 +++++++ src/cpu/scpu/mmio/mmio.h | 65 + src/cpu/scpu/scpu.cpp | 64 + src/cpu/scpu/scpu.h | 84 + src/cpu/scpu/timing/irq.cpp | 162 ++ src/cpu/scpu/timing/timing.cpp | 206 ++ src/cpu/scpu/timing/timing.h | 30 + src/dsp/bdsp/bdsp.cpp | 230 +-- src/dsp/bdsp/bdsp.h | 23 +- src/interface.h | 7 +- src/lib/libbase.h | 172 +- src/lib/libco_win32.cpp | 68 + src/lib/libco_x86.asm | 215 +++ src/lib/libco_x86.h | 15 + src/lib/libconfig.h | 69 +- src/lib/libstring.cpp | 186 +- src/lib/libstring.h | 46 +- src/lib/libstring_replace.cpp | 14 +- src/lib/libstring_sprintf.cpp | 247 ++- src/lib/libwin32.cpp | 3 + src/lib/libwin32.h | 3 + src/lib/opgen_s.cpp | 135 ++ src/lib/opgen_so.cpp | 147 ++ src/memory/bmemory/bmemory.cpp | 25 +- src/memory/bmemory/bmemory.h | 3 + src/memory/bmemory/bmemory_mapper_generic.cpp | 52 +- src/memory/bmemory/bmemory_rw.cpp | 3 + src/memory/memory.h | 4 +- src/ppu/bppu/bppu_mmio.cpp | 12 +- src/ppu/bppu/bppu_render.h | 5 +- src/ppu/bppu/bppu_render_bg.cpp | 29 +- src/ppu/bppu/bppu_render_mode7.cpp | 21 +- src/ppu/bppu/bppu_render_oam.cpp | 93 +- src/sdl/Makefile | 13 +- src/sdl/Makefile.win32 | 2 +- src/sdl/bsnes_sdl.cfg | 98 + src/sdl/sdlmain.cpp | 4 +- src/snes/snes.cpp | 44 +- src/snes/snes.h | 24 +- src/snes/video/filter_ntsc.cpp | 15 +- src/snes/video/filter_ntsc_core.cpp | 1 - src/snes/video/filter_ntsc_core.h | 1 - src/snes/video/video_colortable.cpp | 14 +- src/win/Makefile | 91 +- src/win/audio/dsound.cpp | 2 +- src/win/bsnes.cpp | 8 + src/win/config.cpp | 49 +- src/win/debugger/ui_debugger.cpp | 67 +- src/win/debugger/ui_debugger.h | 21 +- src/win/event.cpp | 14 +- src/win/main.cpp | 17 +- src/win/settings/ui_videosettings.cpp | 40 +- src/win/settings/ui_videosettings.h | 5 - src/win/ui.h | 3 - src/win/ui_main.cpp | 55 +- src/win/video/d3d.cpp | 55 +- src/win/video/ddraw.cpp | 71 +- src/win/video/ddraw_present.cpp | 64 - src/win/video/video.cpp | 24 +- src/win/video/video.h | 5 +- 137 files changed, 16446 insertions(+), 1352 deletions(-) create mode 100644 bsnes.exe create mode 100644 src/apu/sapu/core/cc.bat create mode 100644 src/apu/sapu/core/clean.bat create mode 100644 src/apu/sapu/core/core.cpp create mode 100644 src/apu/sapu/core/core.h create mode 100644 src/apu/sapu/core/op_misc.b create mode 100644 src/apu/sapu/core/op_misc.cpp create mode 100644 src/apu/sapu/core/op_mov.b create mode 100644 src/apu/sapu/core/op_mov.cpp create mode 100644 src/apu/sapu/core/op_pc.b create mode 100644 src/apu/sapu/core/op_pc.cpp create mode 100644 src/apu/sapu/core/op_read.b create mode 100644 src/apu/sapu/core/op_read.cpp create mode 100644 src/apu/sapu/core/op_rmw.b create mode 100644 src/apu/sapu/core/op_rmw.cpp create mode 100644 src/apu/sapu/core/opfn.cpp create mode 100644 src/apu/sapu/core/sapugen.cpp create mode 100644 src/apu/sapu/memory/memory.cpp create mode 100644 src/apu/sapu/memory/memory.h create mode 100644 src/apu/sapu/sapu.cpp create mode 100644 src/apu/sapu/sapu.h create mode 100644 src/apu/sapu/timing/timing.cpp create mode 100644 src/apu/sapu/timing/timing.h create mode 100644 src/chip/dsp1/_dsp1emu.cpp create mode 100644 src/chip/dsp1/_dsp1emu.h create mode 100644 src/chip/dsp1/dsp1.cpp create mode 100644 src/chip/dsp1/dsp1.h create mode 100644 src/chip/dsp1/dsp1emu.cpp create mode 100644 src/chip/dsp1/dsp1emu.h create mode 100644 src/cpu/scpu/core/cc.bat create mode 100644 src/cpu/scpu/core/clean.bat create mode 100644 src/cpu/scpu/core/core.cpp create mode 100644 src/cpu/scpu/core/core.h create mode 100644 src/cpu/scpu/core/op_misc.b create mode 100644 src/cpu/scpu/core/op_misc.cpp create mode 100644 src/cpu/scpu/core/op_pc.b create mode 100644 src/cpu/scpu/core/op_pc.cpp create mode 100644 src/cpu/scpu/core/op_read.b create mode 100644 src/cpu/scpu/core/op_read.cpp create mode 100644 src/cpu/scpu/core/op_rmw.b create mode 100644 src/cpu/scpu/core/op_rmw.cpp create mode 100644 src/cpu/scpu/core/op_write.b create mode 100644 src/cpu/scpu/core/op_write.cpp create mode 100644 src/cpu/scpu/core/opfn.cpp create mode 100644 src/cpu/scpu/core/scpugen.cpp create mode 100644 src/cpu/scpu/dma/dma.cpp create mode 100644 src/cpu/scpu/dma/dma.h create mode 100644 src/cpu/scpu/memory/memory.cpp create mode 100644 src/cpu/scpu/memory/memory.h create mode 100644 src/cpu/scpu/mmio/mmio.cpp create mode 100644 src/cpu/scpu/mmio/mmio.h create mode 100644 src/cpu/scpu/scpu.cpp create mode 100644 src/cpu/scpu/scpu.h create mode 100644 src/cpu/scpu/timing/irq.cpp create mode 100644 src/cpu/scpu/timing/timing.cpp create mode 100644 src/cpu/scpu/timing/timing.h create mode 100644 src/lib/libco_win32.cpp create mode 100644 src/lib/libco_x86.asm create mode 100644 src/lib/libco_x86.h create mode 100644 src/lib/opgen_s.cpp create mode 100644 src/lib/opgen_so.cpp create mode 100644 src/sdl/bsnes_sdl.cfg delete mode 100644 src/win/video/ddraw_present.cpp diff --git a/bsnes.exe b/bsnes.exe new file mode 100644 index 0000000000000000000000000000000000000000..8298aff1b7108e3ffcbe7f3843f4224879989b09 GIT binary patch literal 1142784 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

4mHY~a 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

W{_#ME{jh~9& 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%0AD5H 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�j#Gte^VR=Y1(A zUCS2V>k=r=KlPhL78R55xb>xan(Tffhx!dd%8JR2`&<2&xU%;t_@8x9|C6yl;Jka5 zr@3Tc3$}i!U)8mynp`^a%&pB|?0r^F{aVF!)TGvp@7LW1vUzZ){=CCFYGPPtx?6{K z4Fw(r^{0$$q$a64Wj*fNvFEZx>Q5|gtR}_A!;RgqvURAU{@kb*YO-m5%;JZw%-Q;( z{>!!7sL9bqrw6%-_pw}KtUq*~v6@uud3aRQOq_q}H-FhtO_tmLX*6*mJ0IoLZ)Rnt zChI;vTS^+U_ak@ePmD2FlXFLX9cMNa-%qLk@+}KBdE?_zc zzQu_8X(lmp(f6AdOzMADArH? zX#+;9$*jlI63y4J_q9aoPii_|O{UL!rZZYRzf{z(`_4^GGTz>OSuuxQZ*!>M?3lZn zShpWKXW?T*psCSiiXXvh62GNXV}3dFCsIGRa+aEOSyEizcZ0Zo zs9)Y-u9|$9l5f*-AX{%a)bAcWUrqkd`uo+*SK{@v8P*?Nrcjd}NAi}(uV;QE>VM)9 zr6wa^ENHyy;Va>I$*Di|!ZI}(G0au_z(=;;+^Ijj*-ABeFt(Sb=R5KJl=^k1tyYuQ zT}-#F*r^tH5~<(r@LDyQxhn1A5G9*u74Q7j|LrvPptzLhj7rSn_ zQ@_iB-D)yvwQ^9qF>D?b)UPiKhz%)b4^VqgqR$RDQ5G=wZ!^$ z9j~j&L9b=^;>NK1IwR_Ltw>jsvxj$^cXAf*Td3dX=xsGA>9nTz;5702L;d5%-&K

K`>^Lh74^${Jyw&%=n?Bq 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 j~=jZreemAwT&*-}=XVeRO?Y-58GP<(2pR*$q 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

0k{_Ee%a*7$dr#p{*g#$->Idgy^bi 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%0A;|!=O zl`E`t1_$gxg)^e|1Qo860q3#YaU{1xo%B0S2V5bgJ38nI*1*cT*JIum4ITBt$&VN6 zOg$D+d4mHkz^>4M6F}^2a5%08jg~v9bEkD~5Y?w)u?XwML0dv)EgC`3FnkV|L3)sh zItp5QN#`gToWNpTSUeYIPt`PhY4HMB-NRJq7=Lh1-a98BVK9Umng2At@_BOYm$@2J z!IlsT1pbu|*W@h*LySc5I$hl%y1 zZUlzG+sVNB@LI||mohKpY-@#~wXk&JJ;l7w9zGF{2f<=RI1%re9)I2AeJNhU*(0*G z4d(cPa3Lh|pY-^51*@Cf`Azo37JYaFXR!SqXZmf2=OuodpjhpYOxN?h-_h3*{j2SL ztL?ozxWNO0eg~`F!D_(sVYywnjg`;7WzD{2&b?)fev6r@2O$=9pU`talmJX^qr^*1 z^pzIo{5$ew9e$>Pe8kioa!rRK806=!z}tK@aBZ4%e~SpQlo6gGBD7TuD`0+}RZQQS z*6+=M8{_I~ckgF+;6^v+{SI?Tkbf}Fr1;uHBK&4zUZmUYVx9|Cj|2MKUR9abU*Zm& z^OXQuX=Z<%EQ=C)gBa0aCpU!co%|LLr!g0O{xEIfl(u@t4MbUi7&{PQ1Ww2+rZR2TkYq+&N z*w_qN%U*S+@| zb@T?a|GFFejYExu{a0OqKeTK;?>K3|pElu(HSa7sh$V_723U+<&^cEOZkfc)qG=Tp zkW`{f7b}6FL7rd{!@nd;uBkm$g5Zh_U6!;;5LfZyYm)2|)O2|HEp_mYs=lYF9;vEZ zg1m|nRl4|>Sm7O6az_?_pi4iqdOy&FPh{Q`i3@mj52E^JTuKLGo19Bfo2aWY^SjD8?XiCmOYX7NIG=VYdV!#!wM(h475@~ zr8}bb234L@re(iFnrkSIOug8_BjvwoJTTuP%#oxjY0(#fLET7 zVmPAoL{;9iK@UI{C?fuU3B*^tf~{goW6$Yad7TrgpoIdwaujvWb0D&YhARM8pl=_l zFnTkNrGjA-!8=tK28?WzMM42|3zT=*yuq+Vn3+(Y$HrR{Xf|YIF{3hLZ z%%0rDnk@f@^P~IcTZN8qFw=GHl@`fbn`FJcXYL&n=DVe4uD?UPfs`z_@>UW2lH40% z8AhMuN1tOikb+~fd@I(90X z$>`Q^!Iw|&8~(QYjIFO(tiaW_YVpPrsA!gw;*n&}$gN=|E%ok^21lRc0tntATJ*k! zvIDl6IPSSf9i#M|3kUDy`iii(z!nr(JsI!{rixNj(HTJy#X||hSV0iOkCA1wF9-+S zgDLiOls>;F2Aip8VFEEmFHyqlCA1HlKblDwQ^pPR?kth4a6o1bUd`}mBq)BpZ zq?6~(_hfz*O@E{cZ%Di+ruZXU{KOJp;MnOl*fz5D03k!iZf|U2B2qgTl#h9bx7;qj zZ)9`Aw>hXDQK?2f-ffF{-EQBRnoPiQu#l})C3Rm--Ct%NFVYYB$VKcR7e6W#W7mLJ z7w~58Ln-r+Pu}j!K?`a;9vnK+4xQ>vL4)ycOJ@t}>|w+3sn&U-b{r|KyE5aRtj4R?2zIIANDdA&w$pywvCJG&*dxjs0R`4r z+kEX7UvnS*sOvz;p409Gdo&r$#Ify}ip2Yw#lYwT1pb}088^ttwXq3`m9l)j+C zcica6B=^GexF4S0WBKqYK-NI5;{wQnX6$Ux1VhykOD*@KRCVyp%x46Zc-6l_L6GkT9NiDx8xSx^Mk$r)V-nBOIJRnsa zdEzB@p^*yB(sB!P2P+M;v|+Y3AvDE!#uNJB2@QhXx$B*v$m-w2@!umE<1gCBo+0Mn z5|~ zH5tS&gb9ns-O~}=+$m}@h@ObzXTtc&Q>-sU7(b&@*6t8w7zj>@Zpx#%K;Z`VSGZlg>VW9X(J-J#OQt3H|YI zNfIqdqkGaQA$TCfI_RMm;zg7k?d|3H`B5``Zak}o{jN2cgATl@n@`j;NJOxrgI?>d z)Oy(OI)H|1z_TZJ@AkQNdm(dYps7^zb@2 zoJbc8p0aVIVgi`*Rn5LjD9iYT#dl?!xOdOqfLPQ$^91S7qw@e+pQl#8%tFZ5I!GG6 zEU*5svIZj|*t3H??A$T|(sxL>DA)sW?P^%QkkPKc=fY0GS~QP6j4i@)KQ{y}%>n4C z;`;fxVJ>G`Ik&Bs%&Rfk*fHO}idVj;8Fo4LZHDbV$vW~{yoq-Nh4WiXpX=Sg0@iuj zvmTWPj--JdAxwxf8`SA7(%cqdYPL=1e#xC{?pX%s0hG-50`Gf+*}{^|#pZ-*;`c$=T}xUZ~kAJ-Ycl_wL9~*%VT?gJ9MJS84(1^M3F&&$T=q=p`3FB z=??;-ECC`1C30v|2WUEn?foT(u|4+K9*@tNsX0?MRlYwL=i)5&H&eCht$%Cx-c|eN zSL>1UTWU>!kzm`|Oo>#Y$Q{~GlUCu0COwaeG zfr}L05uZN$IClES$Cl`X`Iz|GC()YkzMqYXhWV8zJ=2qxWlu_XrocyzGZ{4>mjFP6 zWoLV0<`Rmyo>#g7dIMaAD;>X>NnFh>@}v`7Ng$mnSHn?!1=nq>t$^_d|X$x97P6Mjn6Cl zjkB+m&~!80Esb2pm{!1^5prf_B8!ka!)Ke+3YS{$kxAfOQOP%eSC^-+PY&)5126n5 zXMyF@E!X~wxJ z=y~o6gTF-Mx<^^wF|KQb?HS{)Oo~?-63-~lImmJivRwllXCK?u&$0I~=Uc}t@W9tO z>4sLS2il}bC}#)5(FRb0lWu8*%|W`Yg=TM^fZLz5lVxpXxVw3-Zl0ry@95^+I(YLf ztobGY7Z=b38WX^V>wS@;|gKFhln>beZYmH1Rm0@jUI9ou?#arzYfEDvM zy##3H*#s+?^rb&LAk;LHf=K41>xYwsN?jBLyoz*wBGL?v08L!0T^Z5*~p~ zL*c;~TnS;35cUT(&p4_Jp60n&eyfiI~0(BV)n$#K^y);kbOx!6)P zX)hkvrq^*E6PK#SFD9lSN@ll>cQdYq+n=4->MH2+Rnk_fz-zt3O>DJf6wfB0SFuI2 zacR3H)oY}(C4BLELB%q@V3k<320`jMcuywQot|e+%(NtA*i*6`>Di{(WJ7eSAvVXD zSfGt9bzlaJDc!T_L&k)@*`y&$+Spv`m^p3Snaf!OK%v?8EaoDHzli0#a@lSS*MsA^ z@jx^Fda-h|M7>&|*e=yrvuM(vYLMhcM{c|PA$}^hNcj`qfub5?O6QZRXA>*tQ)-d; zDra^(5Ns~;OSvnP0&(^$x%IxB+AUl|fYjtC)^DK8Jt+k9lXU%e(V9PfsQuHQW*){^ zo+d2BB$^&RvBo7r2ep<9w(9A&gcR_$GDjyGAH^CULd6�mo8TKz0s`dj;UGQ0>bp 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

X#+IZmRSWt$t+bNLV}7 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%0Dh;^RXH zZSQDmZa7^7X}Vfl+8XPc>rb~dR(H0a>FH|dXl+2ULc|*7SFK&`ScT*#vX=a8Yvn{k zqzP~^7!>@9$a&7QUBqa05>AFw5_ybh3QoKUI6%ddOPq)>uK#-yKt>4J1>6T`;aae> z^9WstUh-{`SNbjz|4Q6Hks1B`p1peh+%@(H4V-1i4=jt1gAL+gdD(*)rlC)#(&azuvuO&eF|mZHxG3VL(hvNJ@`W@F^45 z0~S6N8zO2pgjU<(4{|y{NP{*u?ZwFkTIpshw;8R~BXJH}Bj&-#>< zOA%4+-T^f>4u@8(-u}hB`029~)>>CMc{cgS^vCTO&f5P~e%0-wy6-DGWfdK=%0Aig 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 Xfhh`1QDBM!Qxuq@z!U|3KnnaHCIn+g literal 0 HcmV?d00001 diff --git a/src/apu/apu.h b/src/apu/apu.h index 4071fe6d..177e2538 100644 --- a/src/apu/apu.h +++ b/src/apu/apu.h @@ -3,12 +3,11 @@ class APU { public: APURegs regs; +uint8 spcram[65536]; static const uint8 iplrom[64]; enum { - FLAG_N = 0x80, FLAG_V = 0x40, - FLAG_P = 0x20, FLAG_B = 0x10, - FLAG_H = 0x08, FLAG_I = 0x04, - FLAG_Z = 0x02, FLAG_C = 0x01 + FLAG_N = 0x80, FLAG_V = 0x40, FLAG_P = 0x20, FLAG_B = 0x10, + FLAG_H = 0x08, FLAG_I = 0x04, FLAG_Z = 0x02, FLAG_C = 0x01 }; virtual uint8 spcram_read (uint16 addr) = 0; @@ -17,9 +16,10 @@ static const uint8 iplrom[64]; virtual uint8 port_read (uint8 port) = 0; virtual void port_write(uint8 port, uint8 value) = 0; - virtual uint8 *get_spcram_handle() = 0; + virtual uint8 *get_spcram_handle() { return spcram; } + virtual void main() {} virtual void run() = 0; - virtual uint32 cycles_executed() = 0; + virtual uint32 clocks_executed() = 0; virtual void power() = 0; virtual void reset() = 0; @@ -28,6 +28,6 @@ static const uint8 iplrom[64]; void disassemble_opcode(char *output); inline uint16 __relb(int8 offset, int op_len); - APU() {} + APU() { memset(spcram, 0, 65536); } virtual ~APU() {} }; diff --git a/src/apu/apuregs.h b/src/apu/apuregs.h index 25d46793..95fec7dc 100644 --- a/src/apu/apuregs.h +++ b/src/apu/apuregs.h @@ -1,20 +1,18 @@ class APURegFlags { private: - template class bit { + template class bit { public: - uint8 _b; - inline operator bool() { return (_b & B); } - inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); } - inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); } - inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); } - inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); } - inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); } - inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); } - inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); } + uint data; + inline operator bool() { return bool(data & mask); } + inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); } + inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); } + inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); } + inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); } }; + public: union { - uint8 _b; + uint8 data; bit<0x80> n; bit<0x40> v; bit<0x20> p; @@ -25,12 +23,12 @@ union { bit<0x01> c; }; - APURegFlags() { _b = 0; } - inline operator uint8() { return _b; } - inline unsigned operator = (uint8 i) { _b = i; return _b; } - inline unsigned operator &= (uint8 i) { _b &= i; return _b; } - inline unsigned operator |= (uint8 i) { _b |= i; return _b; } - inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; } + APURegFlags() { data = 0; } + inline operator unsigned() { return data; } + inline unsigned operator = (const uint8 i) { data = i; return data; } + inline unsigned operator |= (const uint8 i) { data |= i; return data; } + inline unsigned operator ^= (const uint8 i) { data ^= i; return data; } + inline unsigned operator &= (const uint8 i) { data &= i; return data; } }; class APURegs { @@ -38,11 +36,7 @@ public: uint16 pc; union { uint16 ya; -#ifdef ARCH_LSB - struct { uint8 a, y; }; -#else - struct { uint8 y, a; }; -#endif + struct { uint8 order_lsb2(a, y); }; }; uint8 x, sp; APURegFlags p; diff --git a/src/apu/bapu/bapu.cpp b/src/apu/bapu/bapu.cpp index 96b20185..f352e8f0 100644 --- a/src/apu/bapu/bapu.cpp +++ b/src/apu/bapu/bapu.cpp @@ -22,7 +22,7 @@ void bAPU::reset() { regs.p = 0x02; status.cycle_pos = 0; - status.cycles_executed = 0; + status.clocks_executed = 0; //$f1 status.iplrom_enabled = true; @@ -47,8 +47,6 @@ void bAPU::reset() { bAPU::bAPU() { init_op_table(); - spcram = (uint8*)malloc(65536); - t0.cycle_frequency = 128; //1.024mhz / 8khz = 128 t1.cycle_frequency = 128; //1.024mhz / 8khz = 128 t2.cycle_frequency = 16; //1.024mhz / 64khz = 16 @@ -59,6 +57,4 @@ bAPU::bAPU() { t2.target = 0; } -bAPU::~bAPU() { - if(spcram)free(spcram); -} +bAPU::~bAPU() {} diff --git a/src/apu/bapu/bapu.h b/src/apu/bapu/bapu.h index c5199c40..5941a7e0 100644 --- a/src/apu/bapu/bapu.h +++ b/src/apu/bapu/bapu.h @@ -6,7 +6,7 @@ public: struct { uint8 cycle_pos, opcode; - uint32 cycles_executed; + uint32 clocks_executed; //$f1 bool iplrom_enabled; diff --git a/src/apu/bapu/core/clean.bat b/src/apu/bapu/core/clean.bat index be7babec..d807f14d 100644 --- a/src/apu/bapu/core/clean.bat +++ b/src/apu/bapu/core/clean.bat @@ -1,8 +1 @@ @del *.exe -@del op.h -@del optable.cpp -@del op_mov.cpp -@del op_pc.cpp -@del op_read.cpp -@del op_rmw.cpp -@del op_misc.cpp diff --git a/src/apu/bapu/core/op_mov.b b/src/apu/bapu/core/op_mov.b index 43b1d58d..bbf12c75 100644 --- a/src/apu/bapu/core/op_mov.b +++ b/src/apu/bapu/core/op_mov.b @@ -2,13 +2,16 @@ mov_a_x(0x7d, a, x), mov_a_y(0xdd, a, y), mov_x_a(0x5d, x, a), mov_y_a(0xfd, y, a), -mov_x_sp(0x9d, x, sp), -mov_sp_x(0xbd, sp, x) { +mov_x_sp(0x9d, x, sp) { 1:regs.$1 = regs.$2; regs.p.n = !!(regs.$1 & 0x80); regs.p.z = (regs.$1 == 0); } +mov_sp_x(0xbd, sp, x) { +1:regs.$1 = regs.$2; +} + mov_a_const(0xe8, a), mov_x_const(0xcd, x), mov_y_const(0x8d, y) { diff --git a/src/apu/bapu/core/op_mov.cpp b/src/apu/bapu/core/op_mov.cpp index a95750b8..a344f50f 100644 --- a/src/apu/bapu/core/op_mov.cpp +++ b/src/apu/bapu/core/op_mov.cpp @@ -57,8 +57,6 @@ void bAPU::op_mov_sp_x() { switch(status.cycle_pos++) { case 1: { regs.sp = regs.x; - regs.p.n = !!(regs.sp & 0x80); - regs.p.z = (regs.sp == 0); status.cycle_pos = 0; } break; } diff --git a/src/apu/bapu/memory/memory.cpp b/src/apu/bapu/memory/memory.cpp index 7c1873ed..b901e0b9 100644 --- a/src/apu/bapu/memory/memory.cpp +++ b/src/apu/bapu/memory/memory.cpp @@ -189,11 +189,3 @@ void bAPU::stack_write(uint8 value) { spcram_write(0x0100 | regs.sp, value); regs.sp--; } - -uint8 *bAPU::get_spcram_handle() { - if(!spcram) { - alert("bAPU::get_spcram_handle() -- spcram uninitialized"); - } - - return spcram; -} diff --git a/src/apu/bapu/memory/memory.h b/src/apu/bapu/memory/memory.h index 576dc2a7..f99b04ee 100644 --- a/src/apu/bapu/memory/memory.h +++ b/src/apu/bapu/memory/memory.h @@ -1,12 +1,9 @@ enum { OPMODE_ADDR, OPMODE_DP }; -uint8 *spcram; inline uint8 spcram_read (uint16 addr); inline void spcram_write(uint16 addr, uint8 value); inline uint8 port_read (uint8 port); inline void port_write(uint8 port, uint8 value); - inline uint8 *get_spcram_handle(); - inline uint8 op_read(); inline uint8 op_read (uint8 mode, uint16 addr); inline void op_write(uint8 mode, uint16 addr, uint8 value); diff --git a/src/apu/bapu/timing/timing.cpp b/src/apu/bapu/timing/timing.cpp index 97b5be55..b1dccc34 100644 --- a/src/apu/bapu/timing/timing.cpp +++ b/src/apu/bapu/timing/timing.cpp @@ -1,14 +1,14 @@ void bAPU::add_cycles(int cycles) { - status.cycles_executed += cycles; + status.clocks_executed += cycles; t0.add_cycles(cycles); t1.add_cycles(cycles); t2.add_cycles(cycles); } -uint32 bAPU::cycles_executed() { -uint32 r = status.cycles_executed; - status.cycles_executed = 0; +uint32 bAPU::clocks_executed() { +uint32 r = status.clocks_executed; + status.clocks_executed = 0; return (r << 4) + (r << 3); } diff --git a/src/apu/bapu/timing/timing.h b/src/apu/bapu/timing/timing.h index 03d0fa3a..f39ea5a2 100644 --- a/src/apu/bapu/timing/timing.h +++ b/src/apu/bapu/timing/timing.h @@ -6,4 +6,4 @@ bool enabled; inline void add_cycles(int cycles); } t0, t1, t2; inline void add_cycles(int cycles); - inline uint32 cycles_executed(); + inline uint32 clocks_executed(); diff --git a/src/apu/sapu/core/cc.bat b/src/apu/sapu/core/cc.bat new file mode 100644 index 00000000..e9482ab9 --- /dev/null +++ b/src/apu/sapu/core/cc.bat @@ -0,0 +1,3 @@ +cl /O2 /wd4996 sapugen.cpp +@pause +@del *.obj \ No newline at end of file diff --git a/src/apu/sapu/core/clean.bat b/src/apu/sapu/core/clean.bat new file mode 100644 index 00000000..d807f14d --- /dev/null +++ b/src/apu/sapu/core/clean.bat @@ -0,0 +1 @@ +@del *.exe diff --git a/src/apu/sapu/core/core.cpp b/src/apu/sapu/core/core.cpp new file mode 100644 index 00000000..8ab44f1b --- /dev/null +++ b/src/apu/sapu/core/core.cpp @@ -0,0 +1,27 @@ +#include "opfn.cpp" +//#include "op_mov.cpp" +//#include "op_pc.cpp" +//#include "op_read.cpp" +//#include "op_rmw.cpp" +//#include "op_misc.cpp" + +void sAPU::main() { + for(;;) { + status.in_opcode = true; + +// (this->*optbl[op_readpc()])(); + switch(op_readpc()) { + #include "op_mov.cpp" + #include "op_pc.cpp" + #include "op_read.cpp" + #include "op_rmw.cpp" + #include "op_misc.cpp" + } + + status.in_opcode = false; + + #ifdef FAVOR_SPEED + co_return(); + #endif + } +} diff --git a/src/apu/sapu/core/core.h b/src/apu/sapu/core/core.h new file mode 100644 index 00000000..51918136 --- /dev/null +++ b/src/apu/sapu/core/core.h @@ -0,0 +1,24 @@ +//void (sAPU::*optbl[256])(); + +uint16 dp, sp, rd, wr, bit, ya; + bool in_opcode() { return status.in_opcode; } + + uint8 op_adc (uint8 x, uint8 y); + uint16 op_addw(uint16 x, uint16 y); + uint8 op_and (uint8 x, uint8 y); + uint8 op_cmp (uint8 x, uint8 y); + uint16 op_cmpw(uint16 x, uint16 y); + uint8 op_eor (uint8 x, uint8 y); + uint8 op_inc (uint8 x); + uint16 op_incw(uint16 x); + uint8 op_dec (uint8 x); + uint16 op_decw(uint16 x); + uint8 op_or (uint8 x, uint8 y); + uint8 op_sbc (uint8 x, uint8 y); + uint16 op_subw(uint16 x, uint16 y); + uint8 op_asl (uint8 x); + uint8 op_lsr (uint8 x); + uint8 op_rol (uint8 x); + uint8 op_ror (uint8 x); + +//#include "op.h" diff --git a/src/apu/sapu/core/op_misc.b b/src/apu/sapu/core/op_misc.b new file mode 100644 index 00000000..500a380f --- /dev/null +++ b/src/apu/sapu/core/op_misc.b @@ -0,0 +1,175 @@ +nop(0x00) { +1:op_io(); +} + +sleep(0xef), +stop(0xff) { +1:op_io(); +2:op_io(); + regs.pc--; +} + +xcn(0x9f) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +daa(0xdf) { +1:op_io(); +2:op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +das(0xbe) { +1:op_io(); +2:op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +clrc(0x60, regs.p.c = 0), +clrp(0x20, regs.p.p = 0), +setc(0x80, regs.p.c = 1), +setp(0x40, regs.p.p = 1) { +1:op_io(); + $1; +} + +clrv(0xe0) { +1:op_io(); + regs.p.v = 0; + regs.p.h = 0; +} + +notc(0xed) { +1:op_io(); +2:op_io(); + regs.p.c ^= 1; +} + +ei(0xa0, 1), +di(0xc0, 0) { +1:op_io(); +2:op_io(); + regs.p.i = $1; +} + +set0_dp(0x02, rd |= 0x01), +clr0_dp(0x12, rd &= ~0x01), +set1_dp(0x22, rd |= 0x02), +clr1_dp(0x32, rd &= ~0x02), +set2_dp(0x42, rd |= 0x04), +clr2_dp(0x52, rd &= ~0x04), +set3_dp(0x62, rd |= 0x08), +clr3_dp(0x72, rd &= ~0x08), +set4_dp(0x82, rd |= 0x10), +clr4_dp(0x92, rd &= ~0x10), +set5_dp(0xa2, rd |= 0x20), +clr5_dp(0xb2, rd &= ~0x20), +set6_dp(0xc2, rd |= 0x40), +clr6_dp(0xd2, rd &= ~0x40), +set7_dp(0xe2, rd |= 0x80), +clr7_dp(0xf2, rd &= ~0x80) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:$1; + op_writedp(dp, rd); +} + +tset_addr_a(0x0e, |=), +tclr_addr_a(0x4e, &=~) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); +4:op_io(); + regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd $1 regs.a; +5:op_writeaddr(dp, rd); +} + +push_a(0x2d, a), +push_x(0x4d, x), +push_y(0x6d, y), +push_p(0x0d, p) { +1:op_io(); +2:op_io(); +3:op_writestack(regs.$1); +} + +pop_a(0xae, a), +pop_x(0xce, x), +pop_y(0xee, y), +pop_p(0x8e, p) { +1:op_io(); +2:op_io(); +3:regs.$1 = op_readstack(); +} + +mul_ya(0xcf) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; +//result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} + +div_ya_x(0x9e) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); +9:op_io(); +10:op_io(); +11:op_io(); + ya = regs.ya; +//overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the SPC700 in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } +//result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} diff --git a/src/apu/sapu/core/op_misc.cpp b/src/apu/sapu/core/op_misc.cpp new file mode 100644 index 00000000..f2538f09 --- /dev/null +++ b/src/apu/sapu/core/op_misc.cpp @@ -0,0 +1,370 @@ +//nop +case 0x00: { + op_io(); +} break; + +//sleep +case 0xef: { + op_io(); + op_io(); + regs.pc--; +} break; + +//stop +case 0xff: { + op_io(); + op_io(); + regs.pc--; +} break; + +//xcn +case 0x9f: { + op_io(); + op_io(); + op_io(); + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//daa +case 0xdf: { + op_io(); + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//das +case 0xbe: { + op_io(); + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//clrc +case 0x60: { + op_io(); + regs.p.c = 0; +} break; + +//clrp +case 0x20: { + op_io(); + regs.p.p = 0; +} break; + +//setc +case 0x80: { + op_io(); + regs.p.c = 1; +} break; + +//setp +case 0x40: { + op_io(); + regs.p.p = 1; +} break; + +//clrv +case 0xe0: { + op_io(); + regs.p.v = 0; + regs.p.h = 0; +} break; + +//notc +case 0xed: { + op_io(); + op_io(); + regs.p.c ^= 1; +} break; + +//ei +case 0xa0: { + op_io(); + op_io(); + regs.p.i = 1; +} break; + +//di +case 0xc0: { + op_io(); + op_io(); + regs.p.i = 0; +} break; + +//set0_dp +case 0x02: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); +} break; + +//clr0_dp +case 0x12: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); +} break; + +//set1_dp +case 0x22: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); +} break; + +//clr1_dp +case 0x32: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); +} break; + +//set2_dp +case 0x42: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); +} break; + +//clr2_dp +case 0x52: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); +} break; + +//set3_dp +case 0x62: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); +} break; + +//clr3_dp +case 0x72: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); +} break; + +//set4_dp +case 0x82: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); +} break; + +//clr4_dp +case 0x92: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); +} break; + +//set5_dp +case 0xa2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); +} break; + +//clr5_dp +case 0xb2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); +} break; + +//set6_dp +case 0xc2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); +} break; + +//clr6_dp +case 0xd2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); +} break; + +//set7_dp +case 0xe2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); +} break; + +//clr7_dp +case 0xf2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); +} break; + +//tset_addr_a +case 0x0e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + op_io(); + regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd |= regs.a; + op_writeaddr(dp, rd); +} break; + +//tclr_addr_a +case 0x4e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + op_io(); + regs.p.n = !!((rd & regs.a) & 0x80); + regs.p.z = ((rd & regs.a) == 0); + rd &=~ regs.a; + op_writeaddr(dp, rd); +} break; + +//push_a +case 0x2d: { + op_io(); + op_io(); + op_writestack(regs.a); +} break; + +//push_x +case 0x4d: { + op_io(); + op_io(); + op_writestack(regs.x); +} break; + +//push_y +case 0x6d: { + op_io(); + op_io(); + op_writestack(regs.y); +} break; + +//push_p +case 0x0d: { + op_io(); + op_io(); + op_writestack(regs.p); +} break; + +//pop_a +case 0xae: { + op_io(); + op_io(); + regs.a = op_readstack(); +} break; + +//pop_x +case 0xce: { + op_io(); + op_io(); + regs.x = op_readstack(); +} break; + +//pop_y +case 0xee: { + op_io(); + op_io(); + regs.y = op_readstack(); +} break; + +//pop_p +case 0x8e: { + op_io(); + op_io(); + regs.p = op_readstack(); +} break; + +//mul_ya +case 0xcf: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; +//result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//div_ya_x +case 0x9e: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.ya; +//overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the SPC700 in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } +//result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + diff --git a/src/apu/sapu/core/op_mov.b b/src/apu/sapu/core/op_mov.b new file mode 100644 index 00000000..19fda37a --- /dev/null +++ b/src/apu/sapu/core/op_mov.b @@ -0,0 +1,212 @@ +mov_a_x(0x7d, a, x), +mov_a_y(0xdd, a, y), +mov_x_a(0x5d, x, a), +mov_y_a(0xfd, y, a), +mov_x_sp(0x9d, x, sp) { +1:op_io(); + regs.$1 = regs.$2; + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_sp_x(0xbd, sp, x) { +1:op_io(); + regs.$1 = regs.$2; +} + +mov_a_const(0xe8, a), +mov_x_const(0xcd, x), +mov_y_const(0x8d, y) { +1:regs.$1 = op_readpc(); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_ix(0xe6) { +1:op_io(); +2:regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_ixinc(0xbf) { +1:op_io(); +2:op_io(); +3:regs.a = op_readdp(regs.x++); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_dp(0xe4, a), +mov_x_dp(0xf8, x), +mov_y_dp(0xeb, y) { +1:sp = op_readpc(); +2:regs.$1 = op_readdp(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_dpx(0xf4, a, x), +mov_x_dpy(0xf9, x, y), +mov_y_dpx(0xfb, y, x) { +1:sp = op_readpc(); +2:op_io(); +3:regs.$1 = op_readdp(sp + regs.$2); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addr(0xe5, a), +mov_x_addr(0xe9, x), +mov_y_addr(0xec, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:regs.$1 = op_readaddr(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addrx(0xf5, x), +mov_a_addry(0xf6, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:op_io(); +4:regs.a = op_readaddr(sp + regs.$1); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpx(0xe7) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpy(0xf7) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_dp_dp(0xfa) { +1:sp = op_readpc(); +2:dp = op_readpc(); +3:rd = op_readdp(sp); +4:op_writedp(dp, rd); +} + +mov_dp_const(0x8f) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:op_io(); +4:op_writedp(dp, rd); +} + +mov_ix_a(0xc6) { +1:op_io(); +2:op_io(); +3:op_writedp(regs.x, regs.a); +} + +mov_ixinc_a(0xaf) { +1:op_io(); +2:op_io(); +3:op_writedp(regs.x++, regs.a); +} + +mov_dp_a(0xc4, a), +mov_dp_x(0xd8, x), +mov_dp_y(0xcb, y) { +1:dp = op_readpc(); +2:op_io(); +3:op_writedp(dp, regs.$1); +} + +mov_dpx_a(0xd4, x, a), +mov_dpy_x(0xd9, y, x), +mov_dpx_y(0xdb, x, y) { +1:dp = op_readpc(); +2:op_io(); +3:op_io(); +4:op_writedp(dp + regs.$1, regs.$2); +} + +mov_addr_a(0xc5, a), +mov_addr_x(0xc9, x), +mov_addr_y(0xcc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); +4:op_writeaddr(dp, regs.$1); +} + +mov_addrx_a(0xd5, x), +mov_addry_a(0xd6, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); +4:op_io(); +5:op_writeaddr(dp + regs.$1, regs.a); +} + +mov_idpx_a(0xc7) { +1:sp = op_readpc() + regs.x; +2:op_io(); +3:dp = op_readdp(sp); +4:dp |= op_readdp(sp + 1) << 8; +5:op_io(); +6:op_writeaddr(dp, regs.a); +} + +mov_idpy_a(0xd7) { +1:sp = op_readpc(); +2:op_io(); +3:dp = op_readdp(sp); +4:dp |= op_readdp(sp + 1) << 8; +5:op_io(); +6:op_writeaddr(dp + regs.y, regs.a); +} + +movw_ya_dp(0xba) { +1:sp = op_readpc(); +2:op_io(); +3:regs.a = op_readdp(sp); +4:regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); +} + +movw_dp_ya(0xda) { +1:dp = op_readpc(); +2:op_io(); +3:op_writedp(dp, regs.a); +4:op_writedp(dp + 1, regs.y); +} + +mov1_c_bit(0xaa) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); +} + +mov1_bit_c(0xca) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); +4:op_writeaddr(dp, rd); +} diff --git a/src/apu/sapu/core/op_mov.cpp b/src/apu/sapu/core/op_mov.cpp new file mode 100644 index 00000000..45a4165b --- /dev/null +++ b/src/apu/sapu/core/op_mov.cpp @@ -0,0 +1,381 @@ +//mov_a_x +case 0x7d: { + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_y +case 0xdd: { + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_x_a +case 0x5d: { + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_y_a +case 0xfd: { + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//mov_x_sp +case 0x9d: { + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_sp_x +case 0xbd: { + op_io(); + regs.sp = regs.x; +} break; + +//mov_a_const +case 0xe8: { + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_x_const +case 0xcd: { + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_y_const +case 0x8d: { + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//mov_a_ix +case 0xe6: { + op_io(); + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_ixinc +case 0xbf: { + op_io(); + op_io(); + regs.a = op_readdp(regs.x++); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_dp +case 0xe4: { + sp = op_readpc(); + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_x_dp +case 0xf8: { + sp = op_readpc(); + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_y_dp +case 0xeb: { + sp = op_readpc(); + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//mov_a_dpx +case 0xf4: { + sp = op_readpc(); + op_io(); + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_x_dpy +case 0xf9: { + sp = op_readpc(); + op_io(); + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_y_dpx +case 0xfb: { + sp = op_readpc(); + op_io(); + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//mov_a_addr +case 0xe5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_x_addr +case 0xe9: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); +} break; + +//mov_y_addr +case 0xec: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} break; + +//mov_a_addrx +case 0xf5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_addry +case 0xf6: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_idpx +case 0xe7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_a_idpy +case 0xf7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} break; + +//mov_dp_dp +case 0xfa: { + sp = op_readpc(); + dp = op_readpc(); + rd = op_readdp(sp); + op_writedp(dp, rd); +} break; + +//mov_dp_const +case 0x8f: { + rd = op_readpc(); + dp = op_readpc(); + op_io(); + op_writedp(dp, rd); +} break; + +//mov_ix_a +case 0xc6: { + op_io(); + op_io(); + op_writedp(regs.x, regs.a); +} break; + +//mov_ixinc_a +case 0xaf: { + op_io(); + op_io(); + op_writedp(regs.x++, regs.a); +} break; + +//mov_dp_a +case 0xc4: { + dp = op_readpc(); + op_io(); + op_writedp(dp, regs.a); +} break; + +//mov_dp_x +case 0xd8: { + dp = op_readpc(); + op_io(); + op_writedp(dp, regs.x); +} break; + +//mov_dp_y +case 0xcb: { + dp = op_readpc(); + op_io(); + op_writedp(dp, regs.y); +} break; + +//mov_dpx_a +case 0xd4: { + dp = op_readpc(); + op_io(); + op_io(); + op_writedp(dp + regs.x, regs.a); +} break; + +//mov_dpy_x +case 0xd9: { + dp = op_readpc(); + op_io(); + op_io(); + op_writedp(dp + regs.y, regs.x); +} break; + +//mov_dpx_y +case 0xdb: { + dp = op_readpc(); + op_io(); + op_io(); + op_writedp(dp + regs.x, regs.y); +} break; + +//mov_addr_a +case 0xc5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + op_writeaddr(dp, regs.a); +} break; + +//mov_addr_x +case 0xc9: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + op_writeaddr(dp, regs.x); +} break; + +//mov_addr_y +case 0xcc: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + op_writeaddr(dp, regs.y); +} break; + +//mov_addrx_a +case 0xd5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + op_io(); + op_writeaddr(dp + regs.x, regs.a); +} break; + +//mov_addry_a +case 0xd6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + op_io(); + op_writeaddr(dp + regs.y, regs.a); +} break; + +//mov_idpx_a +case 0xc7: { + sp = op_readpc() + regs.x; + op_io(); + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_io(); + op_writeaddr(dp, regs.a); +} break; + +//mov_idpy_a +case 0xd7: { + sp = op_readpc(); + op_io(); + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_io(); + op_writeaddr(dp + regs.y, regs.a); +} break; + +//movw_ya_dp +case 0xba: { + sp = op_readpc(); + op_io(); + regs.a = op_readdp(sp); + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); +} break; + +//movw_dp_ya +case 0xda: { + dp = op_readpc(); + op_io(); + op_writedp(dp, regs.a); + op_writedp(dp + 1, regs.y); +} break; + +//mov1_c_bit +case 0xaa: { + sp = op_readpc(); + sp |= op_readpc() << 8; + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); +} break; + +//mov1_bit_c +case 0xca: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + op_writeaddr(dp, rd); +} break; + diff --git a/src/apu/sapu/core/op_pc.b b/src/apu/sapu/core/op_pc.b new file mode 100644 index 00000000..49cf41ab --- /dev/null +++ b/src/apu/sapu/core/op_pc.b @@ -0,0 +1,180 @@ +bra(0x2f, 0), +beq(0xf0, !regs.p.z), +bne(0xd0, regs.p.z), +bcs(0xb0, !regs.p.c), +bcc(0x90, regs.p.c), +bvs(0x70, !regs.p.v), +bvc(0x50, regs.p.v), +bmi(0x30, !regs.p.n), +bpl(0x10, regs.p.n) { +1:rd = op_readpc(); + if($1)end; +2:op_io(); +3:op_io(); + regs.pc += (int8)rd; +} + +bbs0(0x03, 0x01, !=), +bbc0(0x13, 0x01, ==), +bbs1(0x23, 0x02, !=), +bbc1(0x33, 0x02, ==), +bbs2(0x43, 0x04, !=), +bbc2(0x53, 0x04, ==), +bbs3(0x63, 0x08, !=), +bbc3(0x73, 0x08, ==), +bbs4(0x83, 0x10, !=), +bbc4(0x93, 0x10, ==), +bbs5(0xa3, 0x20, !=), +bbc5(0xb3, 0x20, ==), +bbs6(0xc3, 0x40, !=), +bbc6(0xd3, 0x40, ==), +bbs7(0xe3, 0x80, !=), +bbc7(0xf3, 0x80, ==) { +1:dp = op_readpc(); +2:rd = op_readpc(); +3:sp = op_readdp(dp); +4:op_io(); + if((sp & $1) $2 $1)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dp(0x2e) { +1:dp = op_readpc(); +2:rd = op_readpc(); +3:sp = op_readdp(dp); +4:op_io(); + if(regs.a == sp)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dpx(0xde) { +1:dp = op_readpc(); +2:rd = op_readpc(); +3:op_io(); +4:sp = op_readdp(dp + regs.x); +5:op_io(); + if(regs.a == sp)end; +6:op_io(); +7:op_io(); + regs.pc += (int8)rd; +} + +dbnz_dp(0x6e) { +1:dp = op_readpc(); +2:rd = op_readpc(); +3:wr = op_readdp(dp); + wr--; +4:op_writedp(dp, wr); + if(wr == 0x00)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +dbnz_y(0xfe) { +1:rd = op_readpc(); +2:op_io(); + regs.y--; +3:op_io(); + if(regs.y == 0x00)end; +4:op_io(); +5:op_io(); + regs.pc += (int8)rd; +} + +jmp_addr(0x5f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; + regs.pc = rd; +} + +jmp_iaddrx(0x1f) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); + dp += regs.x; +4:rd = op_readaddr(dp); +5:rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; +} + +call(0x3f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +pcall(0x4f) { +1:rd = op_readpc(); +2:op_io(); +3:op_io(); +4:op_writestack(regs.pc >> 8); +5:op_writestack(regs.pc); + regs.pc = 0xff00 | rd; +} + +tcall_0(0x01, 0), +tcall_1(0x11, 1), +tcall_2(0x21, 2), +tcall_3(0x31, 3), +tcall_4(0x41, 4), +tcall_5(0x51, 5), +tcall_6(0x61, 6), +tcall_7(0x71, 7), +tcall_8(0x81, 8), +tcall_9(0x91, 9), +tcall_10(0xa1, 10), +tcall_11(0xb1, 11), +tcall_12(0xc1, 12), +tcall_13(0xd1, 13), +tcall_14(0xe1, 14), +tcall_15(0xf1, 15) { +1:dp = 0xffde - ($1 << 1); + rd = op_readaddr(dp); +2:rd |= op_readaddr(dp + 1) << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +brk(0x0f) { +1:rd = op_readaddr(0xffde); +2:rd |= op_readaddr(0xffdf) << 8; +3:op_io(); +4:op_io(); +5:op_writestack(regs.pc >> 8); +6:op_writestack(regs.pc); +7:op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} + +ret(0x6f) { +1:rd = op_readstack(); +2:rd |= op_readstack() << 8; +3:op_io(); +4:op_io(); + regs.pc = rd; +} + +reti(0x7f) { +1:regs.p = op_readstack(); +2:rd = op_readstack(); +3:rd |= op_readstack() << 8; +4:op_io(); +5:op_io(); + regs.pc = rd; +} diff --git a/src/apu/sapu/core/op_pc.cpp b/src/apu/sapu/core/op_pc.cpp new file mode 100644 index 00000000..e5bb27db --- /dev/null +++ b/src/apu/sapu/core/op_pc.cpp @@ -0,0 +1,604 @@ +//bra +case 0x2f: { + rd = op_readpc(); + if(0)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//beq +case 0xf0: { + rd = op_readpc(); + if(!regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bne +case 0xd0: { + rd = op_readpc(); + if(regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bcs +case 0xb0: { + rd = op_readpc(); + if(!regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bcc +case 0x90: { + rd = op_readpc(); + if(regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bvs +case 0x70: { + rd = op_readpc(); + if(!regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bvc +case 0x50: { + rd = op_readpc(); + if(regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bmi +case 0x30: { + rd = op_readpc(); + if(!regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bpl +case 0x10: { + rd = op_readpc(); + if(regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs0 +case 0x03: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x01) != 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc0 +case 0x13: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x01) == 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs1 +case 0x23: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x02) != 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc1 +case 0x33: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x02) == 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs2 +case 0x43: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x04) != 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc2 +case 0x53: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x04) == 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs3 +case 0x63: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x08) != 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc3 +case 0x73: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x08) == 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs4 +case 0x83: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x10) != 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc4 +case 0x93: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x10) == 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs5 +case 0xa3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x20) != 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc5 +case 0xb3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x20) == 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs6 +case 0xc3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x40) != 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc6 +case 0xd3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x40) == 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbs7 +case 0xe3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x80) != 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//bbc7 +case 0xf3: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if((sp & 0x80) == 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//cbne_dp +case 0x2e: { + dp = op_readpc(); + rd = op_readpc(); + sp = op_readdp(dp); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//cbne_dpx +case 0xde: { + dp = op_readpc(); + rd = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//dbnz_dp +case 0x6e: { + dp = op_readpc(); + rd = op_readpc(); + wr = op_readdp(dp); + wr--; + op_writedp(dp, wr); + if(wr == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//dbnz_y +case 0xfe: { + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; +} break; + +//jmp_addr +case 0x5f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; +} break; + +//jmp_iaddrx +case 0x1f: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; +} break; + +//call +case 0x3f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//pcall +case 0x4f: { + rd = op_readpc(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; +} break; + +//tcall_0 +case 0x01: { + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_1 +case 0x11: { + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_2 +case 0x21: { + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_3 +case 0x31: { + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_4 +case 0x41: { + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_5 +case 0x51: { + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_6 +case 0x61: { + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_7 +case 0x71: { + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_8 +case 0x81: { + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_9 +case 0x91: { + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_10 +case 0xa1: { + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_11 +case 0xb1: { + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_12 +case 0xc1: { + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_13 +case 0xd1: { + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_14 +case 0xe1: { + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//tcall_15 +case 0xf1: { + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; +} break; + +//brk +case 0x0f: { + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} break; + +//ret +case 0x6f: { + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; +} break; + +//reti +case 0x7f: { + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; +} break; + diff --git a/src/apu/sapu/core/op_read.b b/src/apu/sapu/core/op_read.b new file mode 100644 index 00000000..f5ebff01 --- /dev/null +++ b/src/apu/sapu/core/op_read.b @@ -0,0 +1,199 @@ +adc_a_const(0x88, adc, a), +and_a_const(0x28, and, a), +cmp_a_const(0x68, cmp, a), +cmp_x_const(0xc8, cmp, x), +cmp_y_const(0xad, cmp, y), +eor_a_const(0x48, eor, a), +or_a_const(0x08, or, a), +sbc_a_const(0xa8, sbc, a) { +1:rd = op_readpc(); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_ix(0x86, adc), +and_a_ix(0x26, and), +cmp_a_ix(0x66, cmp), +eor_a_ix(0x46, eor), +or_a_ix(0x06, or), +sbc_a_ix(0xa6, sbc) { +1:rd = op_readdp(regs.x); +2:op_io(); + regs.a = op_$1(regs.a, rd); +} + +adc_a_dp(0x84, adc, a), +and_a_dp(0x24, and, a), +cmp_a_dp(0x64, cmp, a), +cmp_x_dp(0x3e, cmp, x), +cmp_y_dp(0x7e, cmp, y), +eor_a_dp(0x44, eor, a), +or_a_dp(0x04, or, a), +sbc_a_dp(0xa4, sbc, a) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_dpx(0x94, adc), +and_a_dpx(0x34, and), +cmp_a_dpx(0x74, cmp), +eor_a_dpx(0x54, eor), +or_a_dpx(0x14, or), +sbc_a_dpx(0xb4, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); + regs.a = op_$1(regs.a, rd); +} + +adc_a_addr(0x85, adc, a), +and_a_addr(0x25, and, a), +cmp_a_addr(0x65, cmp, a), +cmp_x_addr(0x1e, cmp, x), +cmp_y_addr(0x5e, cmp, y), +eor_a_addr(0x45, eor, a), +or_a_addr(0x05, or, a), +sbc_a_addr(0xa5, sbc, a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_addrx(0x95, adc, x), +adc_a_addry(0x96, adc, y), +and_a_addrx(0x35, and, x), +and_a_addry(0x36, and, y), +cmp_a_addrx(0x75, cmp, x), +cmp_a_addry(0x76, cmp, y), +eor_a_addrx(0x55, eor, x), +eor_a_addry(0x56, eor, y), +or_a_addrx(0x15, or, x), +or_a_addry(0x16, or, y), +sbc_a_addrx(0xb5, sbc, x), +sbc_a_addry(0xb6, sbc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); +4:rd = op_readaddr(dp + regs.$2); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpx(0x87, adc), +and_a_idpx(0x27, and), +cmp_a_idpx(0x67, cmp), +eor_a_idpx(0x47, eor), +or_a_idpx(0x07, or), +sbc_a_idpx(0xa7, sbc) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpy(0x97, adc), +and_a_idpy(0x37, and), +cmp_a_idpy(0x77, cmp), +eor_a_idpy(0x57, eor), +or_a_idpy(0x17, or), +sbc_a_idpy(0xb7, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp + regs.y); + regs.a = op_$1(regs.a, rd); +} + +adc_ix_iy(0x99, adc, 1), +and_ix_iy(0x39, and, 1), +cmp_ix_iy(0x79, cmp, 0), +eor_ix_iy(0x59, eor, 1), +or_ix_iy(0x19, or, 1), +sbc_ix_iy(0xb9, sbc, 1) { +1:wr = op_readdp(regs.x); +2:rd = op_readdp(regs.y); +3:op_io(); + wr = op_$1(wr, rd); +4:($2) ? op_writedp(regs.x, wr) : op_io(); +} + +adc_dp_dp(0x89, adc, 1), +and_dp_dp(0x29, and, 1), +cmp_dp_dp(0x69, cmp, 0), +eor_dp_dp(0x49, eor, 1), +or_dp_dp(0x09, or, 1), +sbc_dp_dp(0xa9, sbc, 1) { +1:sp = op_readpc(); +2:dp = op_readpc(); +3:wr = op_readdp(dp); +4:rd = op_readdp(sp); +5:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +adc_dp_const(0x98, adc, 1), +and_dp_const(0x38, and, 1), +cmp_dp_const(0x78, cmp, 0), +eor_dp_const(0x58, eor, 1), +or_dp_const(0x18, or, 1), +sbc_dp_const(0xb8, sbc, 1) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:wr = op_readdp(dp); +4:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +addw_ya_dp(0x7a, addw), +cmpw_ya_dp(0x5a, cmpw), +subw_ya_dp(0x9a, subw) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd |= op_readdp(dp + 1) << 8; +4:op_io(); + regs.ya = op_$1(regs.ya, rd); +} + +and1_bit(0x4a, !!), +and1_notbit(0x6a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & $1(rd & (1 << bit)); +} + +eor1_bit(0x8a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); +} + +not1_bit(0xea) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); +4:op_writeaddr(dp, rd); +} + +or1_bit(0x0a, !!), +or1_notbit(0x2a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c | $1(rd & (1 << bit)); +} diff --git a/src/apu/sapu/core/op_read.cpp b/src/apu/sapu/core/op_read.cpp new file mode 100644 index 00000000..ec14a189 --- /dev/null +++ b/src/apu/sapu/core/op_read.cpp @@ -0,0 +1,745 @@ +//adc_a_const +case 0x88: { + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_const +case 0x28: { + rd = op_readpc(); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_const +case 0x68: { + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); +} break; + +//cmp_x_const +case 0xc8: { + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); +} break; + +//cmp_y_const +case 0xad: { + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); +} break; + +//eor_a_const +case 0x48: { + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_const +case 0x08: { + rd = op_readpc(); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_const +case 0xa8: { + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_ix +case 0x86: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_ix +case 0x26: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_ix +case 0x66: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_cmp(regs.a, rd); +} break; + +//eor_a_ix +case 0x46: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_ix +case 0x06: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_ix +case 0xa6: { + rd = op_readdp(regs.x); + op_io(); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_dp +case 0x84: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_dp +case 0x24: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_dp +case 0x64: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); +} break; + +//cmp_x_dp +case 0x3e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); +} break; + +//cmp_y_dp +case 0x7e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); +} break; + +//eor_a_dp +case 0x44: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_dp +case 0x04: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_dp +case 0xa4: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_dpx +case 0x94: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_dpx +case 0x34: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_dpx +case 0x74: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); +} break; + +//eor_a_dpx +case 0x54: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_dpx +case 0x14: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_dpx +case 0xb4: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_addr +case 0x85: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_addr +case 0x25: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_addr +case 0x65: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); +} break; + +//cmp_x_addr +case 0x1e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); +} break; + +//cmp_y_addr +case 0x5e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); +} break; + +//eor_a_addr +case 0x45: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_addr +case 0x05: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_addr +case 0xa5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_addrx +case 0x95: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); +} break; + +//adc_a_addry +case 0x96: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_addrx +case 0x35: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); +} break; + +//and_a_addry +case 0x36: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_addrx +case 0x75: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); +} break; + +//cmp_a_addry +case 0x76: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); +} break; + +//eor_a_addrx +case 0x55: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); +} break; + +//eor_a_addry +case 0x56: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_addrx +case 0x15: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); +} break; + +//or_a_addry +case 0x16: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_addrx +case 0xb5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); +} break; + +//sbc_a_addry +case 0xb6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_idpx +case 0x87: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_idpx +case 0x27: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_idpx +case 0x67: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); +} break; + +//eor_a_idpx +case 0x47: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_idpx +case 0x07: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_idpx +case 0xa7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_a_idpy +case 0x97: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); +} break; + +//and_a_idpy +case 0x37: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); +} break; + +//cmp_a_idpy +case 0x77: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); +} break; + +//eor_a_idpy +case 0x57: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); +} break; + +//or_a_idpy +case 0x17: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); +} break; + +//sbc_a_idpy +case 0xb7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); +} break; + +//adc_ix_iy +case 0x99: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//and_ix_iy +case 0x39: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//cmp_ix_iy +case 0x79: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//eor_ix_iy +case 0x59: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//or_ix_iy +case 0x19: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//sbc_ix_iy +case 0xb9: { + wr = op_readdp(regs.x); + rd = op_readdp(regs.y); + op_io(); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); +} break; + +//adc_dp_dp +case 0x89: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//and_dp_dp +case 0x29: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//cmp_dp_dp +case 0x69: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); +} break; + +//eor_dp_dp +case 0x49: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//or_dp_dp +case 0x09: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//sbc_dp_dp +case 0xa9: { + sp = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + rd = op_readdp(sp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//adc_dp_const +case 0x98: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//and_dp_const +case 0x38: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//cmp_dp_const +case 0x78: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); +} break; + +//eor_dp_const +case 0x58: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//or_dp_const +case 0x18: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//sbc_dp_const +case 0xb8: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); +} break; + +//addw_ya_dp +case 0x7a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_io(); + regs.ya = op_addw(regs.ya, rd); +} break; + +//cmpw_ya_dp +case 0x5a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_io(); + regs.ya = op_cmpw(regs.ya, rd); +} break; + +//subw_ya_dp +case 0x9a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_io(); + regs.ya = op_subw(regs.ya, rd); +} break; + +//and1_bit +case 0x4a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); +} break; + +//and1_notbit +case 0x6a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); +} break; + +//eor1_bit +case 0x8a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); +} break; + +//not1_bit +case 0xea: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); +} break; + +//or1_bit +case 0x0a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); +} break; + +//or1_notbit +case 0x2a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); +} break; + diff --git a/src/apu/sapu/core/op_rmw.b b/src/apu/sapu/core/op_rmw.b new file mode 100644 index 00000000..e412ad93 --- /dev/null +++ b/src/apu/sapu/core/op_rmw.b @@ -0,0 +1,61 @@ +inc_a(0xbc, inc, a), +inc_x(0x3d, inc, x), +inc_y(0xfc, inc, y), +dec_a(0x9c, dec, a), +dec_x(0x1d, dec, x), +dec_y(0xdc, dec, y), +asl_a(0x1c, asl, a), +lsr_a(0x5c, lsr, a), +rol_a(0x3c, rol, a), +ror_a(0x7c, ror, a) { +1:op_io(); + regs.$2 = op_$1(regs.$2); +} + +inc_dp(0xab, inc), +dec_dp(0x8b, dec), +asl_dp(0x0b, asl), +lsr_dp(0x4b, lsr), +rol_dp(0x2b, rol), +ror_dp(0x6b, ror) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd = op_$1(rd); + op_writedp(dp, rd); +} + +inc_dpx(0xbb, inc), +dec_dpx(0x9b, dec), +asl_dpx(0x1b, asl), +lsr_dpx(0x5b, lsr), +rol_dpx(0x3b, rol), +ror_dpx(0x7b, ror) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); +4:rd = op_$1(rd); + op_writedp(dp + regs.x, rd); +} + +inc_addr(0xac, inc), +dec_addr(0x8c, dec), +asl_addr(0x0c, asl), +lsr_addr(0x4c, lsr), +rol_addr(0x2c, rol), +ror_addr(0x6c, ror) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); +4:rd = op_$1(rd); + op_writeaddr(dp, rd); +} + +incw_dp(0x3a, incw), +decw_dp(0x1a, decw) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd |= op_readdp(dp + 1) << 8; +4:rd = op_$1(rd); + op_writedp(dp + 1, rd >> 8); +5:op_writedp(dp, rd); +} diff --git a/src/apu/sapu/core/op_rmw.cpp b/src/apu/sapu/core/op_rmw.cpp new file mode 100644 index 00000000..832e0ec8 --- /dev/null +++ b/src/apu/sapu/core/op_rmw.cpp @@ -0,0 +1,236 @@ +//inc_a +case 0xbc: { + op_io(); + regs.a = op_inc(regs.a); +} break; + +//inc_x +case 0x3d: { + op_io(); + regs.x = op_inc(regs.x); +} break; + +//inc_y +case 0xfc: { + op_io(); + regs.y = op_inc(regs.y); +} break; + +//dec_a +case 0x9c: { + op_io(); + regs.a = op_dec(regs.a); +} break; + +//dec_x +case 0x1d: { + op_io(); + regs.x = op_dec(regs.x); +} break; + +//dec_y +case 0xdc: { + op_io(); + regs.y = op_dec(regs.y); +} break; + +//asl_a +case 0x1c: { + op_io(); + regs.a = op_asl(regs.a); +} break; + +//lsr_a +case 0x5c: { + op_io(); + regs.a = op_lsr(regs.a); +} break; + +//rol_a +case 0x3c: { + op_io(); + regs.a = op_rol(regs.a); +} break; + +//ror_a +case 0x7c: { + op_io(); + regs.a = op_ror(regs.a); +} break; + +//inc_dp +case 0xab: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); +} break; + +//dec_dp +case 0x8b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); +} break; + +//asl_dp +case 0x0b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); +} break; + +//lsr_dp +case 0x4b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); +} break; + +//rol_dp +case 0x2b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); +} break; + +//ror_dp +case 0x6b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); +} break; + +//inc_dpx +case 0xbb: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); +} break; + +//dec_dpx +case 0x9b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); +} break; + +//asl_dpx +case 0x1b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); +} break; + +//lsr_dpx +case 0x5b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); +} break; + +//rol_dpx +case 0x3b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); +} break; + +//ror_dpx +case 0x7b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); +} break; + +//inc_addr +case 0xac: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); +} break; + +//dec_addr +case 0x8c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); +} break; + +//asl_addr +case 0x0c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); +} break; + +//lsr_addr +case 0x4c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); +} break; + +//rol_addr +case 0x2c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); +} break; + +//ror_addr +case 0x6c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); +} break; + +//incw_dp +case 0x3a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + rd = op_incw(rd); + op_writedp(dp + 1, rd >> 8); + op_writedp(dp, rd); +} break; + +//decw_dp +case 0x1a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + rd = op_decw(rd); + op_writedp(dp + 1, rd >> 8); + op_writedp(dp, rd); +} break; + diff --git a/src/apu/sapu/core/opfn.cpp b/src/apu/sapu/core/opfn.cpp new file mode 100644 index 00000000..abe7c0a7 --- /dev/null +++ b/src/apu/sapu/core/opfn.cpp @@ -0,0 +1,138 @@ +uint8 sAPU::op_adc(uint8 x, uint8 y) { +int16 r = x + y + regs.p.c; + regs.p.n = !!(r & 0x80); + regs.p.v = !!(~(x ^ y) & (y ^ (uint8)r) & 0x80); + regs.p.h = !!((x ^ y ^ (uint8)r) & 0x10); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r > 0xff); + return r; +} + +uint16 sAPU::op_addw(uint16 x, uint16 y) { +int16 r; + regs.p.c = 0; + r = op_adc(x, y); + r |= op_adc(x >> 8, y >> 8) << 8; + regs.p.z = ((uint16)r == 0); + return r; +} + +uint8 sAPU::op_and(uint8 x, uint8 y) { + x &= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_cmp(uint8 x, uint8 y) { +int16 r = x - y; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); + return x; +} + +uint16 sAPU::op_cmpw(uint16 x, uint16 y) { +int32 r = x - y; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); + return x; +} + +uint8 sAPU::op_eor(uint8 x, uint8 y) { + x ^= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_or(uint8 x, uint8 y) { + x |= y; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_sbc(uint8 x, uint8 y) { +int16 r = x - y - !regs.p.c; + regs.p.n = !!(r & 0x80); + regs.p.v = !!((x ^ y) & (x ^ (uint8)r) & 0x80); + regs.p.h = !((x ^ y ^ (uint8)r) & 0x10); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); + return r; +} + +uint16 sAPU::op_subw(uint16 x, uint16 y) { +int16 r; + regs.p.c = 1; + r = op_sbc(x, y); + r |= op_sbc(x >> 8, y >> 8) << 8; + regs.p.z = ((uint16)r == 0); + return r; +} + +uint8 sAPU::op_inc(uint8 x) { + x++; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint16 sAPU::op_incw(uint16 x) { + x++; + regs.p.n = !!(x & 0x8000); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_dec(uint8 x) { + x--; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint16 sAPU::op_decw(uint16 x) { + x--; + regs.p.n = !!(x & 0x8000); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_asl(uint8 x) { + regs.p.c = !!(x & 0x80); + x <<= 1; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_lsr(uint8 x) { + regs.p.c = !!(x & 0x01); + x >>= 1; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_rol(uint8 x) { +uint8 c = regs.p.c; + regs.p.c = !!(x & 0x80); + x <<= 1; + x |= c; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} + +uint8 sAPU::op_ror(uint8 x) { +uint8 c = (regs.p.c)?0x80:0x00; + regs.p.c = !!(x & 0x01); + x >>= 1; + x |= c; + regs.p.n = !!(x & 0x80); + regs.p.z = (x == 0); + return x; +} diff --git a/src/apu/sapu/core/sapugen.cpp b/src/apu/sapu/core/sapugen.cpp new file mode 100644 index 00000000..d8d49606 --- /dev/null +++ b/src/apu/sapu/core/sapugen.cpp @@ -0,0 +1,18 @@ +#define CLASS_NAME "sAPU" +#include "../../../lib/opgen_s.cpp" + +int main() { +//fph = fopen("op.h", "wb"); +//fpt = fopen("optable.cpp", "wb"); + + generate("op_mov.cpp", "op_mov.b"); + generate("op_pc.cpp", "op_pc.b"); + generate("op_read.cpp", "op_read.b"); + generate("op_rmw.cpp", "op_rmw.b"); + generate("op_misc.cpp", "op_misc.b"); + +//fclose(fph); +//fclose(fpt); + + return 0; +} diff --git a/src/apu/sapu/memory/memory.cpp b/src/apu/sapu/memory/memory.cpp new file mode 100644 index 00000000..e1e6a019 --- /dev/null +++ b/src/apu/sapu/memory/memory.cpp @@ -0,0 +1,197 @@ +uint8 sAPU::spcram_read(uint16 addr) { +uint8 r; + if((addr & 0xfff0) == 0x00f0) { + //addr >= 0x00f0 && addr <= 0x00ff + switch(addr) { + case 0xf0: //TEST -- operation unknown, supposedly returns 0x00 + r = 0x00; + break; + case 0xf1: //CONTROL -- write-only register, always returns 0x00 + r = 0x00; + break; + case 0xf2: //DSPADDR + r = status.dsp_addr; + break; + case 0xf3: //DSPDATA + //0x80-0xff is a read-only mirror of 0x00-0x7f + r = r_dsp->read(status.dsp_addr & 0x7f); + break; + case 0xf4: //CPUIO0 + case 0xf5: //CPUIO1 + case 0xf6: //CPUIO2 + case 0xf7: //CPUIO3 + #ifdef FAVOR_SPEED + co_return(); + #endif + r = r_cpu->port_read(addr & 3); + break; + case 0xf8: //??? + case 0xf9: //??? -- Mapped to SPCRAM + r = spcram[addr]; + break; + case 0xfa: //T0TARGET + case 0xfb: //T1TARGET + case 0xfc: //T2TARGET -- write-only registers, always return 0x00 + r = 0x00; + break; + case 0xfd: //T0OUT -- 4-bit counter value + r = t0.stage3_ticks & 15; + t0.stage3_ticks = 0; + break; + case 0xfe: //T1OUT -- 4-bit counter value + r = t1.stage3_ticks & 15; + t1.stage3_ticks = 0; + break; + case 0xff: //T2OUT -- 4-bit counter value + r = t2.stage3_ticks & 15; + t2.stage3_ticks = 0; + break; + } + } else if(addr < 0xffc0) { + r = spcram[addr]; + } else { + if(status.iplrom_enabled == true) { + r = iplrom[addr & 0x3f]; + } else { + r = spcram[addr]; + } + } + +#ifdef DEBUGGER + snes->notify(SNES::SPCRAM_READ, addr, r); +#endif + return r; +} + +void sAPU::spcram_write(uint16 addr, uint8 data) { + if((addr & 0xfff0) == 0x00f0) { + //addr >= 0x00f0 && addr >= 0x00ff + switch(addr) { + case 0xf0: //TEST -- operation unknown + break; + case 0xf1: //CONTROL + status.iplrom_enabled = !!(data & 0x80); + + //one-time clearing of APU port read registers, + //emulated by simulating CPU writes of 0x00 + if(data & 0x20) { + r_cpu->port_write(2, 0x00); + r_cpu->port_write(3, 0x00); + } + if(data & 0x10) { + r_cpu->port_write(0, 0x00); + r_cpu->port_write(1, 0x00); + } + + //0->1 transistion resets timers + if(t2.enabled == false && (data & 0x04)) { + t2.stage2_ticks = 0; + t2.stage3_ticks = 0; + } + t2.enabled = !!(data & 0x04); + + if(t1.enabled == false && (data & 0x02)) { + t1.stage2_ticks = 0; + t1.stage3_ticks = 0; + } + t1.enabled = !!(data & 0x02); + + if(t0.enabled == false && (data & 0x01)) { + t0.stage2_ticks = 0; + t0.stage3_ticks = 0; + } + t0.enabled = !!(data & 0x01); + break; + case 0xf2: //DSPADDR + status.dsp_addr = data; + break; + case 0xf3: //DSPDATA + //0x80-0xff is a read-only mirror of 0x00-0x7f + if(status.dsp_addr < 0x80) { + r_dsp->write(status.dsp_addr & 0x7f, data); + } + break; + case 0xf4: //CPUIO0 + case 0xf5: //CPUIO1 + case 0xf6: //CPUIO2 + case 0xf7: //CPUIO3 + #ifdef FAVOR_SPEED + co_return(); + #endif + port_write(addr & 3, data); + break; + case 0xf8: //??? + case 0xf9: //??? - Mapped to SPCRAM + spcram[addr] = data; + break; + case 0xfa: //T0TARGET + t0.target = data; + break; + case 0xfb: //T1TARGET + t1.target = data; + break; + case 0xfc: //T2TARGET + t2.target = data; + break; + case 0xfd: //T0OUT + case 0xfe: //T1OUT + case 0xff: //T2OUT -- read-only registers + break; + } + } else { + //writes to $ffc0-$ffff always go to spcram, + //even if the iplrom is enabled. + spcram[addr] = data; + } + +#ifdef DEBUGGER + snes->notify(SNES::SPCRAM_WRITE, addr, data); +#endif +} + +uint8 sAPU::port_read(uint8 port) { + return spcram[0xf4 + (port & 3)]; +} + +void sAPU::port_write(uint8 port, uint8 data) { + spcram[0xf4 + (port & 3)] = data; +} + +// + +void sAPU::op_io() { + add_clocks(24); + tick_timers(); +//co_return(); +} + +uint8 sAPU::op_read(uint16 addr) { + add_clocks(8); +#ifdef FAVOR_ACCURACY + co_return(); +#endif +uint8 r = spcram_read(addr); + add_clocks(16); + tick_timers(); + return r; +} + +void sAPU::op_write(uint16 addr, uint8 data) { + add_clocks(24); + tick_timers(); +#ifdef FAVOR_ACCURACY + co_return(); +#endif + spcram_write(addr, data); +} + +// + +uint8 sAPU::op_readpc () { return op_read(regs.pc++); } +uint8 sAPU::op_readstack () { return op_read(0x0100 | ++regs.sp); } +void sAPU::op_writestack(uint8 data) { op_write(0x0100 | regs.sp--, data); } +uint8 sAPU::op_readaddr (uint16 addr) { return op_read(addr); } + +void sAPU::op_writeaddr (uint16 addr, uint8 data) { op_write(addr, data); } +uint8 sAPU::op_readdp (uint8 addr) { return op_read((uint(regs.p.p) << 8) + addr); } +void sAPU::op_writedp (uint8 addr, uint8 data) { op_write((uint(regs.p.p) << 8) + addr, data); } diff --git a/src/apu/sapu/memory/memory.h b/src/apu/sapu/memory/memory.h new file mode 100644 index 00000000..aa2298a3 --- /dev/null +++ b/src/apu/sapu/memory/memory.h @@ -0,0 +1,24 @@ + uint8 spcram_read (uint16 addr); + void spcram_write(uint16 addr, uint8 data); + + inline uint8 port_read (uint8 port); + inline void port_write(uint8 port, uint8 data); + +/***** + * core APU bus functions + *****/ + inline void op_io (); + inline uint8 op_read (uint16 addr); + inline void op_write(uint16 addr, uint8 data); + +/***** + * helper memory addressing functions used by APU core + *****/ + inline uint8 op_readpc (); + inline uint8 op_readstack (); + inline void op_writestack(uint8 data); + inline uint8 op_readaddr (uint16 addr); + + inline void op_writeaddr (uint16 addr, uint8 data); + inline uint8 op_readdp (uint8 addr); + inline void op_writedp (uint8 addr, uint8 data); diff --git a/src/apu/sapu/sapu.cpp b/src/apu/sapu/sapu.cpp new file mode 100644 index 00000000..ba22ce6c --- /dev/null +++ b/src/apu/sapu/sapu.cpp @@ -0,0 +1,73 @@ +#include "../../base.h" + +#include "core/core.cpp" +#include "memory/memory.cpp" +#include "timing/timing.cpp" + +void sapu_entry_point() { + r_apu->main(); +} + +void sAPU::run() { + co_call(thread); +} + +void sAPU::power() { + memset(spcram, 0x00, 65536); + reset(); +} + +void sAPU::reset() { + if(thread)co_delete(thread); + thread = co_create(sapu_entry_point, 65536); + + regs.pc = 0xffc0; + regs.a = 0x00; + regs.x = 0x00; + regs.y = 0x00; + regs.sp = 0xef; + regs.p = 0x02; + + status.clocks_executed = 0; + +//$f1 + status.iplrom_enabled = true; + +//$f2 + status.dsp_addr = 0x00; + + t0.enabled = false; + t1.enabled = false; + t2.enabled = false; + + t0.stage1_ticks = 0; + t1.stage1_ticks = 0; + t2.stage1_ticks = 0; + + t0.stage2_ticks = 0; + t1.stage2_ticks = 0; + t2.stage2_ticks = 0; + + t0.stage3_ticks = 0; + t1.stage3_ticks = 0; + t2.stage3_ticks = 0; +} + +sAPU::sAPU() { +//#include "core/optable.cpp" + + thread = 0; + + t0.cycle_frequency = 128; //1.024mhz / 8khz = 128 + t1.cycle_frequency = 128; //1.024mhz / 8khz = 128 + t2.cycle_frequency = 16; //1.024mhz / 64khz = 16 + +//targets not initialized/changed upon reset + t0.target = 0; + t1.target = 0; + t2.target = 0; +} + +sAPU::~sAPU() { + if(thread)co_delete(thread); +} diff --git a/src/apu/sapu/sapu.h b/src/apu/sapu/sapu.h new file mode 100644 index 00000000..d191ea00 --- /dev/null +++ b/src/apu/sapu/sapu.h @@ -0,0 +1,32 @@ +class sAPU : public APU { +public: +#include "core/core.h" +#include "memory/memory.h" +#include "timing/timing.h" + +thread_t thread; + +struct { + uint8 opcode; + bool in_opcode; + +//timing + uint32 clocks_executed; + +//$f1 + bool iplrom_enabled; + +//$f2 + uint8 dsp_addr; +} status; + +//sapu.cpp + void main(); + + void run(); + void power(); + void reset(); + + sAPU(); + ~sAPU(); +}; diff --git a/src/apu/sapu/timing/timing.cpp b/src/apu/sapu/timing/timing.cpp new file mode 100644 index 00000000..ebc696c8 --- /dev/null +++ b/src/apu/sapu/timing/timing.cpp @@ -0,0 +1,35 @@ +void sAPU::add_clocks(int clocks) { + status.clocks_executed += clocks; +} + +uint32 sAPU::clocks_executed() { +uint32 r = status.clocks_executed; + status.clocks_executed = 0; + return r; +} + +//occurs once every 24 clocks (once every APU opcode cycle) +void sAPU::tick_timers() { + t0.tick(); + t1.tick(); + t2.tick(); +} + +void sAPU::sAPUTimer::tick() { +//stage 1 increment + stage1_ticks++; + if(stage1_ticks < cycle_frequency)return; + + stage1_ticks -= cycle_frequency; + if(enabled == false)return; + +//stage 2 increment + stage2_ticks++; + + if(stage2_ticks != target)return; + +//stage 3 increment + stage2_ticks = 0; + stage3_ticks++; + stage3_ticks &= 15; +} diff --git a/src/apu/sapu/timing/timing.h b/src/apu/sapu/timing/timing.h new file mode 100644 index 00000000..d7a06e83 --- /dev/null +++ b/src/apu/sapu/timing/timing.h @@ -0,0 +1,11 @@ +class sAPUTimer { +public: +uint8 cycle_frequency, target; +uint8 stage1_ticks, stage2_ticks, stage3_ticks; +bool enabled; + inline void tick(); +} t0, t1, t2; + + inline void add_clocks(int clocks); + inline void tick_timers(); + inline uint32 clocks_executed(); diff --git a/src/base.h b/src/base.h index 080a24d2..50d2e473 100644 --- a/src/base.h +++ b/src/base.h @@ -1,29 +1,32 @@ -#define BSNES_VERSION "0.016" -#define BSNES_TITLE "bsnes v" BSNES_VERSION +#define BSNES_VERSION "0.016.27a" +#define BSNES_TITLE "bsnes v" BSNES_VERSION #define MEMCORE bMemBus -#define CPUCORE bCPU -#define APUCORE bAPU +#define CPUCORE sCPU +#define APUCORE sAPU #define DSPCORE bDSP #define PPUCORE bPPU +//#define FAVOR_ACCURACY +#define FAVOR_SPEED + //game genie + pro action replay code support (~1-3% speed hit) #define CHEAT_SYSTEM //enable GZ, ZIP format support -//#define GZIP_SUPPORT +#define GZIP_SUPPORT //enable JMA support -//#define JMA_SUPPORT +#define JMA_SUPPORT //debugging extensions (~10% speed hit) -#define DEBUGGER +//#define DEBUGGER //snes core polymorphism //(allow mem/cpu/apu/ppu overriding, ~10% speed hit) //#define POLYMORPHISM -//this should be declared in the port-specific makefiles +//this should be declared in the port-specific makefile //#define ARCH_LSB //#define ARCH_MSB @@ -43,6 +46,7 @@ #error "unknown architecture" #endif +#include "lib/libco_x86.h" #include "lib/libbase.h" #include "lib/libvector.h" #include "lib/libstring.h" @@ -58,8 +62,18 @@ inline uint16 read16(uint8 *addr, uint pos) { } //platform-specific global functions -void alert(char *s, ...); -void dprintf(char *s, ...); +void alert(char *, ...); +void dprintf(char *, ...); +void dprintf(uint, char *, ...); + +namespace source { + enum { + none = 0, + debug, + cpu, + apu, + }; +}; //various class interfaces #include "interface.h" diff --git a/src/cart/cart.cpp b/src/cart/cart.cpp index f2dcd936..f8f5d7ad 100644 --- a/src/cart/cart.cpp +++ b/src/cart/cart.cpp @@ -4,9 +4,12 @@ void Cartridge::read_header() { cart.srtc = false; cart.sdd1 = false; cart.c4 = false; + cart.dsp1 = false; cart.dsp2 = false; cart.obc1 = false; + cart.dsp1_mapper = 0; + if(cart.header_index == 0x7fc0 && cart.rom_size >= 0x401000) { cart.mapper = EXLOROM; } else if(cart.header_index == 0x7fc0 && rom[cart.header_index + MAPPER] == 0x32) { @@ -33,6 +36,28 @@ uint8 rom_type = rom[cart.header_index + ROM_TYPE]; cart.c4 = true; } + if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) { + cart.dsp1 = true; + } + + if(mapper == 0x30 && rom_type == 0x05) { + cart.dsp1 = true; + } + + if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) { + cart.dsp1 = true; + } + + if(cart.dsp1 == true) { + if((mapper & 0x2f) == 0x20 && rom_size <= 0x100000) { + cart.dsp1_mapper = DSP1_LOROM_1MB; + } else if((mapper & 0x2f) == 0x20) { + cart.dsp1_mapper = DSP1_LOROM_2MB; + } else if((mapper & 0x2f) == 0x21) { + cart.dsp1_mapper = DSP1_HIROM; + } + } + if(mapper == 0x20 && rom_type == 0x05) { cart.dsp2 = true; } @@ -41,7 +66,7 @@ uint8 rom_type = rom[cart.header_index + ROM_TYPE]; cart.obc1 = true; } - cart.cart_mmio = cart.c4 | cart.dsp2 | cart.obc1; + cart.cart_mmio = cart.c4 | cart.dsp1 | cart.dsp2 | cart.obc1; if(rom[cart.header_index + SRAM_SIZE] & 7) { cart.sram_size = 1024 << (rom[cart.header_index + SRAM_SIZE] & 7); @@ -67,7 +92,7 @@ int32 score_lo = 0, score_ex = 0; if(rom_size < 0x010000) { - //cart too small to be anything else + //cart too small to be anything but lorom cart.header_index = 0x007fc0; return; } diff --git a/src/cart/cart.h b/src/cart/cart.h index e0df6e40..3daaa463 100644 --- a/src/cart/cart.h +++ b/src/cart/cart.h @@ -28,6 +28,11 @@ enum { HIROM = 0x21, EXLOROM = 0x22, EXHIROM = 0x25, + +//special chip memory mappers + DSP1_LOROM_1MB = 1, + DSP1_LOROM_2MB = 2, + DSP1_HIROM = 3, }; struct { @@ -47,8 +52,11 @@ struct { bool srtc; bool sdd1; bool c4; + bool dsp1; bool dsp2; bool obc1; + + uint dsp1_mapper; } cart; void load_rom(Reader *rf); diff --git a/src/chip/dsp1/_dsp1emu.cpp b/src/chip/dsp1/_dsp1emu.cpp new file mode 100644 index 00000000..637a65ed --- /dev/null +++ b/src/chip/dsp1/_dsp1emu.cpp @@ -0,0 +1,1617 @@ +// DSP-1's emulation code +// +// Based on research by Overload, The Dumper, Neviksti and Andreas Naive +// Date: June 2006 + +////////////////////////////////////////////////////////////////// + +Dsp1::Dsp1() +{ + reset(); +} + +////////////////////////////////////////////////////////////////// + +uint8 Dsp1::getSr() const +{ + return mSr; +} + +////////////////////////////////////////////////////////////////// + +uint8 Dsp1::getDr() +{ + uint8 oDr; + + fsmStep(true, oDr); + return oDr; +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::setDr(uint8 iDr) +{ + fsmStep(false, iDr); +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::reset() +{ + mSr = DRC|RQM; + mDr = 0x0080; // Only a supposition. Is this correct? + mFreeze = false; + mFsmMajorState = WAIT_COMMAND; + memset(&shared, 0, sizeof(SharedData)); // another supposition +} + +////////////////////////////////////////////////////////////////// + +// Though the DSP-1 is unaware of the type of operation (read or write) +// we need to know what is being done by the program, as the class +// is responsible for maintaining the binding between the +// "external" and "internal" representations of the DR (data register). + +void Dsp1::fsmStep(bool read, uint8 &data) +{ + if (0 == (mSr&RQM)) return; + // Now RQM would be cleared; however, as this code is not to be used in + // a multithread environment, we will simply fake RQM operation. + // (The only exception would be Op1A's freeze.) + + // binding + if (read) + { + if (mSr&DRS) + data = static_cast(mDr>>8); + else + data = static_cast(mDr); + } + else + { + if (mSr&DRS) + { + mDr &= 0x00ff; + mDr |= data<<8; + } + else + { + mDr &= 0xff00; + mDr |= data; + } + } + + + switch (mFsmMajorState) + { + case WAIT_COMMAND: + mCommand = static_cast(mDr); + if (!(mCommand & 0xc0)) // valid command? + { + switch(mCommand) + { + // freeze cases + case 0x1a: + case 0x2a: + case 0x3a: + mFreeze = true; + break; + // normal cases + default: + mDataCounter=0; + mFsmMajorState = READ_DATA; + mSr &= ~DRC; + break; + } + } + break; + case READ_DATA: + mSr ^= DRS; + if (!(mSr&DRS)) + { + mReadBuffer[mDataCounter++] = static_cast(mDr); + if (mDataCounter >= mCommandTable[mCommand].reads) + { + (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); + if (0 != mCommandTable[mCommand].writes) // any output? + { + mDataCounter = 0; + mDr = static_cast(mWriteBuffer[mDataCounter]); + mFsmMajorState = WRITE_DATA; + } + else + { + mDr = 0x0080; // valid command completion + mFsmMajorState = WAIT_COMMAND; + mSr |= DRC; + } + } + } + break; + case WRITE_DATA: + mSr ^= DRS; + if (!(mSr&DRS)) + { + ++mDataCounter; + if (mDataCounter >= mCommandTable[mCommand].writes) + { + if ((mCommand == 0x0a)&&(mDr != 0x8000)) + { + // works in continuous mode + mReadBuffer[0]++; // next raster line + (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); + mDataCounter = 0; + mDr = static_cast(mWriteBuffer[mDataCounter]); + } + else + { + mDr = 0x0080; // valid command completion + mFsmMajorState = WAIT_COMMAND; + mSr |= DRC; + } + } + else + { + mDr = static_cast(mWriteBuffer[mDataCounter]); + } + } + break; + } + + + + // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-). + if (mFreeze) + mSr &= ~RQM; +} + +////////////////////////////////////////////////////////////////// + +// The info on this table follows Overload's docs. + +const Dsp1::Command Dsp1::mCommandTable[0x40] = { + {&Dsp1::multiply, 2, 1}, //0x00 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveA, 3, 3}, //0x03 + {&Dsp1::triangle, 2, 2}, //0x04 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryTest, 1, 1}, //0x0f + {&Dsp1::radius, 3, 2}, //0x08 + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::raster, 1, 4}, // 0x0a. This will normally work in continuous mode + {&Dsp1::scalarA, 3, 1}, //0x0b + {&Dsp1::rotate, 3, 2}, //0x0c + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryTest, 1, 1}, //0x0f + + {&Dsp1::inverse, 2, 2}, //0x10 + {&Dsp1::attitudeB, 4, 0}, //0x11 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveB, 3, 3}, //0x13 + {&Dsp1::gyrate, 6, 3}, //0x14 + {&Dsp1::attitudeB, 4, 0}, //0x11 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryDump, 1, 1024}, //0x1f + {&Dsp1::range, 4, 1}, //0x18 + {&Dsp1::objectiveB, 3, 3}, //0x1d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarB, 3, 1}, //0x1b + {&Dsp1::polar, 6, 3}, //0x1c + {&Dsp1::objectiveB, 3, 3}, //0x1d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryDump, 1, 1024}, //0x1f + + {&Dsp1::multiply2, 2, 1}, //0x20 + {&Dsp1::attitudeC, 4, 0}, //0x21 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveC, 3, 3}, //0x23 + {&Dsp1::triangle, 2, 2}, //0x04 + {&Dsp1::attitudeC, 4, 0}, //0x21 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memorySize, 1, 1}, //0x2f + {&Dsp1::distance, 3, 1}, //0x28 + {&Dsp1::objectiveC, 3, 3}, //0x2d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarC, 3, 1}, //0x2b + {&Dsp1::rotate, 3, 2}, //0x0c + {&Dsp1::objectiveC, 3, 3}, //0x2d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memorySize, 1, 1}, //0x2f + + {&Dsp1::inverse, 2, 2}, //0x10 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveA, 3, 3}, //0x03 + {&Dsp1::gyrate, 6, 3}, //0x14 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryDump, 1, 1024}, //0x1f + {&Dsp1::range2, 4, 1}, //0x38 + {&Dsp1::objectiveA, 3, 3}, //0x0d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarA, 3, 1}, //0x0b + {&Dsp1::polar, 6, 3}, //0x1c + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryDump, 1, 1024}, //0x1f +}; + +////////////////////////////////////////////////////////////////// + +void Dsp1::memoryTest(int16 *input, int16 *output) +{ + int16& Size = input[0]; + int16& Result = output[0]; + + Result = 0x0000; +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::memoryDump(int16 *input, int16 *output) +{ + memcpy(output, DataRom, 1024); +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::memorySize(int16 *input, int16 *output) +{ + int16& Size = output[0]; + + Size = 0x0100; +} + +////////////////////////////////////////////////////////////////// + +// 16-bit multiplication + +void Dsp1::multiply(int16 *input, int16 *output) +{ + int16& Multiplicand = input[0]; + int16& Multiplier = input[1]; + int16& Product = output[0]; + + Product = Multiplicand * Multiplier >> 15; +} + +////////////////////////////////////////////////////////////////// + +// 16-bit multiplication. 'Alternative' method. Can anyone check this carefully? + +void Dsp1::multiply2(int16 *input, int16 *output) +{ + int16& Multiplicand = input[0]; + int16& Multiplier = input[1]; + int16& Product = output[0]; + + Product = (Multiplicand * Multiplier >> 15)+1; +} + +////////////////////////////////////////////////////////////////// + +// This command determines the inverse of a floating point decimal number. + +void Dsp1::inverse(int16 *input, int16 *output) +{ + int16& Coefficient = input[0]; + int16& Exponent = input[1]; + int16& iCoefficient = output[0]; + int16& iExponent = output[1]; + + inverse(Coefficient, Exponent, iCoefficient, iExponent); +} + +////////////////////////////////////////////////////////////////// + +// Vector component calculation. Determines the X and Y components for a +// two-dimensional vector whose size and direction is known. +// Y = Radius * sin(Angle) +// X = Radius * cos(Angle) + +void Dsp1::triangle(int16 *input, int16 *output) +{ + int16& Angle = input[0]; + int16& Radius = input[1]; + int16& Y = output[0]; + int16& X = output[1]; + + Y = sin(Angle) * Radius >> 15; + X = cos(Angle) * Radius >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Determines the squared norm of a vector (X,Y,Z) +// The output is Radius = X^2+Y^2+Z^2 (double integer) + +void Dsp1::radius(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& RadiusLow = output[0]; + int16& RadiusHigh = output[1]; + + int32 Radius; + + Radius = (X * X + Y * Y + Z * Z) << 1; + RadiusLow = static_cast(Radius); + RadiusHigh = static_cast(Radius>>16); +} + +////////////////////////////////////////////////////////////////// + +// Vector size comparison. This command compares the size of the vector (X,Y,Z) and the distance (R) +// from a particular point, and so may be used to determine if a point is within the sphere or radius R. +// The output is D = X^2+Y^2+Z^2-R^2 + +void Dsp1::range(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Radius = input[3]; + int16& Range = output[0]; + + Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Vector size comparison. 'Alternative' method. + +void Dsp1::range2(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Radius = input[3]; + int16& Range = output[0]; + + Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1; +} + +////////////////////////////////////////////////////////////////// + +// This command calculates the norm of a (X,Y,Z) vector, or the distance from +// the point (X,Y,Z) to (0,0,0), as you prefer to see it. +// Distance = sqrt(X^2+Y^2+Z^2) +// The square root of a number 'a' is calculated by doing this: you +// write 'a' as b*2^2n, with 'b' between 1/4 and 1; then, you calculate +// c=sqrt(b) by using lineal interpolation between points of a +// look-up table and, finally, you output the result as c*2^n. + +void Dsp1::distance(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Distance = output[0]; + + int32 Radius = X * X + Y * Y + Z * Z; + + if (Radius == 0) Distance = 0; + else + { + int16 C, E; + normalizeDouble(Radius, C, E); + if (E & 1) C = C * 0x4000 >> 15; + + int16 Pos = C * 0x0040 >> 15; + + int16 Node1 = DataRom[0x00d5 + Pos]; + int16 Node2 = DataRom[0x00d6 + Pos]; + + Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + +#if DSP1_VERSION < 0x0102 + if (Pos & 1) Distance -= (Node2 - Node1); +#endif + Distance >>= (E >> 1); + } +} + +////////////////////////////////////////////////////////////////// + +// Determines the (X2, Y2) coordinates obtained by rotating (X1, Y1) +// clockwise for an angle 'Angle'. The official documentation says +// 'counterclockwise', but it's obviously wrong (surprise! :P) +// +// In matrix notation: +// |X2| |cos(Angle) sin(Angle)| |X1| +// | | = | | | | +// |Y2| |-sin(Angle cos(Angle)| |Y1| + +void Dsp1::rotate(int16 *input, int16 *output) +{ + int16& Angle = input[0]; + int16& X1 = input[1]; + int16& Y1 = input[2]; + int16& X2 = output[0]; + int16& Y2 = output[1]; + + X2 = (Y1 * sin(Angle) >> 15) + (X1 * cos(Angle) >> 15); + Y2 = (Y1 * cos(Angle) >> 15) - (X1 * sin(Angle) >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Calculate the coordinates (X2, Y2, Z2) obtained when rotating (X1, Y1, Z1) +// three-dimensionally. Rotation is done in the order of Az around the Z axis, +// Ay around the Y axis and Ax around the X axis. As occur with the "attitude" commands +// (see comments in the "gyrate" command), this doesn't match what explained in +// the official documentation, but it's coherent with what it is done in the "attitude" +// command (but not with the "gyrate" command). +// +// In matrix notation: +// |X2| |1 0 0 | |cosRy 0 -sinRy| | cosRz sinRz 0| |X1| +// |Y2| = |0 cosRx sinRx| | 0 1 0 | |-sinRz cosRz 0| |Y1| +// |Z2| |0 -sinRx cosRx| |sinRy 0 cosRy| | 0 0 1| |Z1| + +void Dsp1::polar(int16 *input, int16 *output) +{ + int16& Az = input[0]; + int16& Ay = input[1]; + int16& Ax = input[2]; + int16& X1 = input[3]; + int16& Y1 = input[4]; + int16& Z1 = input[5]; + int16& X2 = output[0]; + int16& Y2 = output[1]; + int16& Z2 = output[2]; + + int16 X, Y, Z; + + // Rotate Around Z + X = (Y1 * sin(Az) >> 15) + (X1 * cos(Az) >> 15); + Y = (Y1 * cos(Az) >> 15) - (X1 * sin(Az) >> 15); + X1 = X; Y1 = Y; + + // Rotate Around Y + Z = (X1 * sin(Ay) >> 15) + (Z1 * cos(Ay) >> 15); + X = (X1 * cos(Ay) >> 15) - (Z1 * sin(Ay) >> 15); + X2 = X; Z1 = Z; + + // Rotate Around X + Y = (Z1 * sin(Ax) >> 15) + (Y1 * cos(Ax) >> 15); + Z = (Z1 * cos(Ax) >> 15) - (Y1 * sin(Ax) >> 15); + Y2 = Y; Z2 = Z; +} + +////////////////////////////////////////////////////////////////// + +// Set up the elements of an "attitude matrix" (there are other ones): +// S | cosRz sinRz 0| |cosRy 0 -sinRy| |1 0 0 | +// MatrixA = - |-sinRz cosRz 0| | 0 1 0 | |0 cosRx sinRx| +// 2 | 0 0 1| |sinRy 0 cosRy| |0 -sinRx cosRx| +// This matrix is thought to be used within the following framework: +// let's suppose we define positive rotations around a system of orthogonal axes in this manner: +// a rotation of +90 degrees around axis3 converts axis2 into axis1 +// a rotation of +90 degrees around axis2 converts axis1 into axis3 +// a rotation of +90 degrees around axis1 converts axis3 into axis2 +// and let's suppose that we have defined a new orthonormal axes system (FLU) +// by doing the following operations about the standard one (XYZ): +// first rotating the XYZ system around Z by an angle Rz (obtaining X'Y'Z'), +// then rotating the resulting system around Y by an angle Ry (obtaining X''Y''Z'') +// and, finally, rotating the resulting system around X by an angle Rx (obtaining FLU) +// This FLU (forward/left/up) system represents an "attitude" and, then, the matrix here defined +// is the change of coordinates matrix that transform coordinates in the FLU +// system (the "object coordinates") into the standard XYZ system (the "global coordinates"), +// multiplied by a scale factor S/2, that is: +// |x| S |f| +// |y| * - = MatrixA * |l| +// |z| 2 |u| +// In a similar way, if we use the transpose of the matrix, we can transform global coordinates +// into object coordinates: +// |f| S |x| +// |l| * - = MatrixA_transposed * |y| +// |u| 2 |z| +// +// input[0]: S +// input[1]: Rz +// input[2]: Ry +// input[3]: Rx + +void Dsp1::attitudeA(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixA[2][0] = S * SinRy >> 15; + shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'attitudeA', but with a difference attitude matrix (matrixB) + +void Dsp1::attitudeB(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixB[2][0] = S * SinRy >> 15; + shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'attitudeA', but with a difference attitude matrix (matrixC) + +void Dsp1::attitudeC(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixC[2][0] = S * SinRy >> 15; + shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Convert global coordinates (X,Y,Z) to object coordinates (F,L,U) +// See the comment in "attitudeA" for a explanation about the calculation. +// +// input[0]: X ; input[1]: Y ; input[2]: Z +// output[0]: F ; output[1]: L ; output[2]: U + +void Dsp1::objectiveA(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixA[0][0] * X >> 15) + (shared.MatrixA[1][0] * Y >> 15) + (shared.MatrixA[2][0] * Z >> 15); + L = (shared.MatrixA[0][1] * X >> 15) + (shared.MatrixA[1][1] * Y >> 15) + (shared.MatrixA[2][1] * Z >> 15); + U = (shared.MatrixA[0][2] * X >> 15) + (shared.MatrixA[1][2] * Y >> 15) + (shared.MatrixA[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'objectiveA', but for the 'B' attitude + +void Dsp1::objectiveB(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixB[0][0] * X >> 15) + (shared.MatrixB[1][0] * Y >> 15) + (shared.MatrixB[2][0] * Z >> 15); + L = (shared.MatrixB[0][1] * X >> 15) + (shared.MatrixB[1][1] * Y >> 15) + (shared.MatrixB[2][1] * Z >> 15); + U = (shared.MatrixB[0][2] * X >> 15) + (shared.MatrixB[1][2] * Y >> 15) + (shared.MatrixB[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'objectiveA', but for the 'C' attitude + +void Dsp1::objectiveC(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixC[0][0] * X >> 15) + (shared.MatrixC[1][0] * Y >> 15) + (shared.MatrixC[2][0] * Z >> 15); + L = (shared.MatrixC[0][1] * X >> 15) + (shared.MatrixC[1][1] * Y >> 15) + (shared.MatrixC[2][1] * Z >> 15); + U = (shared.MatrixC[0][2] * X >> 15) + (shared.MatrixC[1][2] * Y >> 15) + (shared.MatrixC[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Convert object coordinates (F,L,U) to object coordinates (X,Y,Z) +// See the comment in "attitudeA" for a explanation about the calculation. +// +// input[0]: F ; input[1]: L ; input[2]: U +// output[0]: X ; output[1]: Y ; output[2]: Z + +void Dsp1::subjectiveA(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixA[0][0] * F >> 15) + (shared.MatrixA[0][1] * L >> 15) + (shared.MatrixA[0][2] * U >> 15); + Y = (shared.MatrixA[1][0] * F >> 15) + (shared.MatrixA[1][1] * L >> 15) + (shared.MatrixA[1][2] * U >> 15); + Z = (shared.MatrixA[2][0] * F >> 15) + (shared.MatrixA[2][1] * L >> 15) + (shared.MatrixA[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'subjectiveA', but for the 'B' attitude + +void Dsp1::subjectiveB(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixB[0][0] * F >> 15) + (shared.MatrixB[0][1] * L >> 15) + (shared.MatrixB[0][2] * U >> 15); + Y = (shared.MatrixB[1][0] * F >> 15) + (shared.MatrixB[1][1] * L >> 15) + (shared.MatrixB[1][2] * U >> 15); + Z = (shared.MatrixB[2][0] * F >> 15) + (shared.MatrixB[2][1] * L >> 15) + (shared.MatrixB[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'subjectiveA', but for the 'C' attitude + +void Dsp1::subjectiveC(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixC[0][0] * F >> 15) + (shared.MatrixC[0][1] * L >> 15) + (shared.MatrixC[0][2] * U >> 15); + Y = (shared.MatrixC[1][0] * F >> 15) + (shared.MatrixC[1][1] * L >> 15) + (shared.MatrixC[1][2] * U >> 15); + Z = (shared.MatrixC[2][0] * F >> 15) + (shared.MatrixC[2][1] * L >> 15) + (shared.MatrixC[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// This command calculates the inner product (S) of a vector (X,Y,Z) and +// the first column of MatrixA. It should be noted that that first column +// represent the global coordinates of an unity vector in the forward +// direction in the object coordinate system (coordinates (1,0,0) in the FLU +// axes system). +// +// input[0]: X ; input[1]: Y ; input[2]: Z +// output[0]: S + +void Dsp1::scalarA(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixA[0][0] + Y * shared.MatrixA[1][0] + Z * shared.MatrixA[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'scalarA', but for the 'B' attitude + +void Dsp1::scalarB(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixB[0][0] + Y * shared.MatrixB[1][0] + Z * shared.MatrixB[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'scalarA', but for the 'C' attitude + +void Dsp1::scalarC(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixC[0][0] + Y * shared.MatrixC[1][0] + Z * shared.MatrixC[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// This command determines the final attitude angles after the body with attitude angles (Ax, Ay, Az) with +// respect to the global coordinates is rotated by the minor angular displacements (DeltaF, DeltaL, DeltaU). +// It means that the XYZ axes are rotated by (Ax, Ay, Az) to obtain the FLU axes and, then, these +// are rotated by (DeltaF, DeltaL, DeltaU). The command calculates and return the new FLU angles respect to the +// XYZ system (Rx, Ry, Rz) +// The formulae are: +// Rx = Ax + (DeltaU*sin(Ay)+DeltaF*cos(Ay)) +// Ry = Ay + DeltaL - tan(Ax)*(DeltaU*cos(Ay)+DeltaF*sin(Ay)) +// Rz = Az + sec(Ax)*(DeltaU*cos(Ay)-DeltaF*sin(Ay)) +// +// Now the discussion: according to the official documentation, as described in various commands, you pass from +// XYZ to FLU by doing the rotations in the order Y, X, Z. In this command, the formulae are coherent with the +// fact that Y is the first axis to do a rotation around it. However, in the "attitude" command, while the official +// document describe it that way, we have discovered, when reverse engineering the command, that the calculated +// matrix do the rotation around Y in the second place. This incoherent behaviour of various commands is, in my +// opinion, a pretty severe implementation error. However, if you only use small "minor displacements", the error term +// introduced by that incoherence should be almost negligible. + +void Dsp1::gyrate(int16 *input, int16 *output) +{ + int16& Az = input[0]; + int16& Ax = input[1]; + int16& Ay = input[2]; + int16& U = input[3]; + int16& F = input[4]; + int16& L = input[5]; + int16& Rz = output[0]; + int16& Rx = output[1]; + int16& Ry = output[2]; + + int16 CSec, ESec, CSin, C, E; + int16 SinAy = sin(Ay); + int16 CosAy = cos(Ay); + + inverse(cos(Ax), 0, CSec, ESec); + + // Rotation Around Z + normalizeDouble(U * CosAy - F * SinAy, C, E); + + E = ESec - E; + + normalize(C * CSec >> 15, C, E); + + Rz = Az + denormalizeAndClip(C, E); + + // Rotation Around X + Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); + + // Rotation Around Y + normalizeDouble(U * CosAy + F * SinAy, C, E); + + E = ESec - E; + + normalize(sin(Ax), CSin, E); + + normalize(-(C * (CSec * CSin >> 15) >> 15), C, E); + + Ry = Ay + denormalizeAndClip(C, E) + L; +} + +////////////////////////////////////////////////////////////////// + +const int16 Dsp1::MaxAZS_Exp[16] = { + 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, + 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 +}; + +////////////////////////////////////////////////////////////////// + + +// Set-up the projection framework. Besides returning some values, it store in RAM some values that +// will be used by the other three projection commands (raster, target an project) +// Input: +// (Fx, Fy, Fz)-> coordinates of base point (global coordinates) +// Lfe-> distance between the base point and the viewpoint (center of projection) +// Les-> distance between the base point and the screen +// Aas-> azimuth angle (0º is east; 90ª is north) +// Azs-> zenith angle (0º is zenith) +// Output: +// Vof-> raster line of imaginary center (whatever it means ;) ) +// Vva-> raster line representing the horizon line +// (Cx, Cy)-> coordinates of the projection of the center of the screen over the ground (ground coordinates) + +void Dsp1::parameter(int16 *input, int16 *output) +{ + int16& Fx = input[0]; + int16& Fy = input[1]; + int16& Fz = input[2]; + int16& Lfe = input[3]; + int16& Les = input[4]; + int16& Aas = input[5]; + int16& Azs = input[6]; + int16& Vof = output[0]; + int16& Vva = output[1]; + int16& Cx = output[2]; + int16& Cy = output[3]; + + int16 CSec, C, E; + int16 LfeNx, LfeNy, LfeNz; + int16 LesNx, LesNy, LesNz; + + // Copy Zenith angle for clipping + int16 AZS = Azs; + + // Store Les and his coefficient and exponent when normalized + shared.Les = Les; + shared.E_Les=0; + normalize(Les, shared.C_Les, shared.E_Les); + + // Store Sine and Cosine of Azimuth and Zenith angle + shared.SinAas = sin(Aas); + shared.CosAas = cos(Aas); + shared.SinAzs = sin(Azs); + shared.CosAzs = cos(Azs); + + // normal vector to the screen (norm 1, points toward the center of projection) + shared.Nx = shared.SinAzs * -shared.SinAas >> 15; + shared.Ny = shared.SinAzs * shared.CosAas >> 15; + shared.Nz = shared.CosAzs * 0x7fff >> 15; + + // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) + shared.Hx = shared.CosAas*0x7fff>>15; + shared.Hy = shared.SinAas*0x7fff>>15; + + // vertical vector of the screen (norm 1, points toward the top of the screen) + shared.Vx = shared.CosAzs*-shared.SinAas>>15; + shared.Vy = shared.CosAzs*shared.CosAas>>15; + shared.Vz = -shared.SinAzs*0x7fff>>15; + + LfeNx = Lfe*shared.Nx>>15; + LfeNy = Lfe*shared.Ny>>15; + LfeNz = Lfe*shared.Nz>>15; + + // Center of Projection + shared.CentreX = Fx+LfeNx; + shared.CentreY = Fy+LfeNy; + shared.CentreZ = Fz+LfeNz; + + LesNx = Les*shared.Nx>>15; + LesNy = Les*shared.Ny>>15; + LesNz = Les*shared.Nz>>15; + + // center of the screen (global coordinates) + shared.Gx=shared.CentreX-LesNx; + shared.Gy=shared.CentreY-LesNy; + shared.Gz=shared.CentreZ-LesNz; + + + E = 0; + normalize(shared.CentreZ, C, E); + + shared.CentreZ_C = C; + shared.CentreZ_E = E; + + // Determine clip boundary and clip Zenith angle if necessary + // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...) + int16 MaxAZS = MaxAZS_Exp[-E]; + + if (AZS < 0) { + MaxAZS = -MaxAZS; + if (AZS < MaxAZS + 1) AZS = MaxAZS + 1; + } else { + if (AZS > MaxAZS) AZS = MaxAZS; + } + + // Store Sine and Cosine of clipped Zenith angle + shared.SinAZS = sin(AZS); + shared.CosAZS = cos(AZS); + + // calculate the separation of (cx, cy) from the projection of + // the 'centre of projection' over the ground... (CentreZ*tg(AZS)) + inverse(shared.CosAZS, 0, shared.SecAZS_C1, shared.SecAZS_E1); + normalize(C * shared.SecAZS_C1 >> 15, C, E); + E += shared.SecAZS_E1; + C = denormalizeAndClip(C, E) * shared.SinAZS >> 15; + + // ... and then take into account the position of the centre of + // projection and the azimuth angle + shared.CentreX += C * shared.SinAas >> 15; + shared.CentreY -= C * shared.CosAas >> 15; + + Cx = shared.CentreX; + Cy = shared.CentreY; + + // Raster number of imaginary center and horizontal line + Vof = 0; + + if ((Azs != AZS) || (Azs == MaxAZS)) + { + // correct vof and vva when Azs is outside the 'non-clipping interval' + // we have only some few Taylor coefficients, so we cannot guess which ones + // are the approximated functions and, what is worse, we don't know why + // the own clipping stuff (and, particularly, this correction) is done + if (Azs == -32768) Azs = -32767; + + C = Azs - MaxAZS; + if (C >= 0) C--; + int16 Aux = ~(C << 2); + + // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 + C = Aux * DataRom[0x0328] >> 15; + C = (C * Aux >> 15) + DataRom[0x0327]; + Vof -= (C * Aux >> 15) * Les >> 15; + + // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 + C = Aux * Aux >> 15; + Aux = (C * DataRom[0x0324] >> 15) + DataRom[0x0325]; + shared.CosAZS += (C * Aux >> 15) * shared.CosAZS >> 15; + } + + // vertical offset of the screen with regard to the horizontal plane + // containing the centre of projection + shared.VOffset = Les * shared.CosAZS >> 15; + + // The horizon line (the line in the screen that is crossed by the horizon plane + // -the horizontal plane containing the 'centre of projection'-), + // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult + // to explain but easily seen in a graph. To better see it, consider it in this way: + // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;) + inverse(shared.SinAZS, 0, CSec, E); + normalize(shared.VOffset, C, E); + normalize(C * CSec >> 15, C, E); + + if (C == -32768) { C >>= 1; E++; } + + Vva = denormalizeAndClip(-C, E); + + // Store Secant of clipped Zenith angle + inverse(shared.CosAZS, 0, shared.SecAZS_C2, shared.SecAZS_E2); +} + +////////////////////////////////////////////////////////////////// + +// Calculates the matrix which transform an object situated on a raster line (Vs) into +// his projection over the ground. The modified SecAZS is used here, so +// i don't understand the fine details, but, basically, it's done +// this way: The vertical offset between the point of projection and the +// raster line is calculated (Vs*SinAzs>>15)+VOffset, then the height of +// the center of projection is measured in that units (*CentreZ_C). If, now +// you consider the "reference case" (center of projection at an unit of height), +// the projection of a thin strip containing the raster line will have the same +// width (as the raster line would be on the ground in this case, but will suffer a +// change of scale in height (as the ground and the vertical axis would form an angle of 180º-Azs). +// This scale factor, when the angle 'center of screen-center of projection-raster line' is small, +// can be aproximated by the one of the center of the screen, 1/cos(Azs).(**) (Here is when it's used +// SecAZS). By last, you have to consider the effect of the azimuth angle Aas, and you are done. +// +// Using matrix notation: +// |A B| Centre_ZS | cos(Aas) -sin(Aas)| |1 0| +// ProjectionMatrix = | | = ----------- * | | * | | +// |C D| Vs*sin(Azs) |sin(Aas) cos(Aas)| |0 sec(Azs)| +// +// (**) +// If Les=1, the vertical offset between the center +// of projection and the center of the screen is Cos(Azs); then, if the vertical +// offset is 1, the ratio of the projection over the ground respect to the +// line on the screen is 1/cos(Azs). + +void Dsp1::raster(int16 *input, int16 *output) +{ + int16& Vs = input[0]; + int16& An = output[0]; + int16& Bn = output[1]; + int16& Cn = output[2]; + int16& Dn = output[3]; + + int16 C, E, C1, E1; + + inverse((Vs * shared.SinAzs >> 15) + shared.VOffset, 7, C, E); + + E += shared.CentreZ_E; + C1 = C * shared.CentreZ_C >> 15; + + E1 = E + shared.SecAZS_E2; + + normalize(C1, C, E); + C = denormalizeAndClip(C, E); + + An = C * shared.CosAas >> 15; + Cn = C * shared.SinAas >> 15; + + normalize(C1 * shared.SecAZS_C2 >> 15, C, E1); + C = denormalizeAndClip(C, E1); + + Bn = C * -shared.SinAas >> 15; + Dn = C * shared.CosAas >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Calculate the projection over the ground of a selected point of screen +// It simply apply the projection matrix described in the "Raster" command +// to the vector (H,V) transposed, and add the result to the position of +// the centre of projection. +// The only special point to take into account is the directions on the screen: +// H is positive rightward, but V is positive downward; this is why +// the signs take that configuration + +void Dsp1::target(int16 *input, int16 *output) +{ + int16& H = input[0]; + int16& V = input[1]; + int16& X = output[0]; + int16& Y = output[1]; + + int16 C, E, C1, E1; + + inverse((V * shared.SinAzs >> 15) + shared.VOffset, 8, C, E); + + E += shared.CentreZ_E; + C1 = C * shared.CentreZ_C >> 15; + + E1 = E + shared.SecAZS_E1; + + H <<= 8; + normalize(C1, C, E); + C = denormalizeAndClip(C, E) * H >> 15; + + X = shared.CentreX + (C * shared.CosAas >> 15); + Y = shared.CentreY - (C * shared.SinAas >> 15); + + V <<= 8; + normalize(C1 * shared.SecAZS_C1 >> 15, C, E1); + C = denormalizeAndClip(C, E1) * V >> 15; + + X += C * -shared.SinAas >> 15; + Y += C * shared.CosAas >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Calculation of the projection over the screen (H,V) of an object (X,Y,Z) and his +// 'enlargement ratio' (M). The positive directions on the screen are as described +// in the targe command. M is scaled down by 2^-7, that is, M==0x0100 means ratio 1:1 + + void Dsp1::project(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& H = output[0]; + int16& V = output[1]; + int16& M = output[2]; + + int32 aux, aux4; + int16 E, E2, E3, E4, E5, refE, E6, E7; + int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; + int16 Px, Py, Pz; + + E4=E3=E2=E=E5=0; + + normalizeDouble(int32(X)-shared.Gx, Px, E4); + normalizeDouble(int32(Y)-shared.Gy, Py, E); + normalizeDouble(int32(Z)-shared.Gz, Pz, E3); + Px>>=1; E4--; // to avoid overflows when calculating the scalar products + Py>>=1; E--; + Pz>>=1; E3--; + + refE = (E>15); + C8=- (Py*shared.Ny>>15); + C9=- (Pz*shared.Nz>>15); + C12=C11+C8+C9; // this cannot overflow! + + aux4=C12; // de-normalization with 32-bits arithmetic + refE = 16-refE; // refE can be up to 3 + if (refE>=0) + aux4 <<=(refE); + else + aux4 >>=-(refE); + if (aux4==-1) aux4 = 0; // why? + aux4>>=1; + + aux = static_cast(shared.Les) + aux4; // Les - the scalar product of P with the normal vector of the screen + normalizeDouble(aux, C10, E2); + E2 = 15-E2; + + inverse(C10, 0, C4, E4); + C2=C4*shared.C_Les>>15; // scale factor + + + // H + E7=0; + C16= (Px*shared.Hx>>15); + C20= (Py*shared.Hy>>15); + C17=C16+C20; // scalar product of P with the normalized horizontal vector of the screen... + + C18=C17*C2>>15; // ... multiplied by the scale factor + normalize(C18, C19, E7); + H=denormalizeAndClip(C19, shared.E_Les-E2+refE+E7); + + // V + E6=0; + C21 = Px*shared.Vx>>15; + C22 = Py*shared.Vy>>15; + C23 = Pz*shared.Vz>>15; + C24=C21+C22+C23; // scalar product of P with the normalized vertical vector of the screen... + + C26=C24*C2>>15; // ... multiplied by the scale factor + normalize(C26, C25, E6); + V=denormalizeAndClip(C25, shared.E_Les-E2+refE+E6); + + // M + normalize(C2, C6, E4); + M=denormalizeAndClip(C6, E4+shared.E_Les-E2-7); // M is the scale factor divided by 2^7 +} + +////////////////////////////////////////////////////////////////// + +// Calculate the sine of the input parameter +// this is done by linear interpolation between +// the points of a look-up table + +int16 Dsp1::sin(int16 Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return 0; + return -sin(-Angle); + } + int32 S = SinTable[Angle >> 8] + (MulTable[Angle & 0xff] * SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) S = 32767; + return (int16) S; +} + +////////////////////////////////////////////////////////////////// + +// Calculate the cosine of the input parameter. +// It's used the same method than in sin(int16) + +int16 Dsp1::cos(int16 Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return -32768; + Angle = -Angle; + } + int32 S = SinTable[0x40 + (Angle >> 8)] - (MulTable[Angle & 0xff] * SinTable[Angle >> 8] >> 15); + if (S < -32768) S = -32767; + return (int16) S; +} + +////////////////////////////////////////////////////////////////// + +// Determines the inverse of a floating point decimal number +// iCoefficient*2^iExponent = 1/(Coefficient*2^Exponent), with the output +// normalized (iCoefficient represents a number whose absolute value is between 1/2 and 1) +// To invert 'Coefficient' a first initial guess is taken from a look-up table +// and, then, two iterations of the Newton method (applied to the function +// f(x)=1/(2*x)-Coefficient) are done. This results in a close approximation (iCoefficient) to a number 'y' +// that verify Coefficient*y=1/2. This is why you have to correct the exponent by one +// unit at the end. + +void Dsp1::inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent) +{ + // Step One: Division by Zero + if (Coefficient == 0x0000) + { + iCoefficient = 0x7fff; + iExponent = 0x002f; + } + else + { + int16 Sign = 1; + + // Step Two: Remove Sign + if (Coefficient < 0) + { + if (Coefficient < -32767) Coefficient = -32767; + Coefficient = -Coefficient; + Sign = -1; + } + + // Step Three: Normalize + while (Coefficient < 0x4000) + { + Coefficient <<= 1; + Exponent--; + } + + // Step Four: Special Case + if (Coefficient == 0x4000) + if (Sign == 1) iCoefficient = 0x7fff; + else { + iCoefficient = -0x4000; + Exponent--; + } + else { + // Step Five: Initial Guess + int16 i = DataRom[((Coefficient - 0x4000) >> 7) + 0x0065]; + + // Step Six: Iterate Newton's Method + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + + iCoefficient = i * Sign; + } + + iExponent = 1 - Exponent; + } +} + +////////////////////////////////////////////////////////////////// + +int16 Dsp1::denormalizeAndClip(int16 C, int16 E) +{ + if (E > 0) { + if (C > 0) return 32767; else if (C < 0) return -32767; + } else { + if (E < 0) return C * DataRom[0x0031 + E] >> 15; + } + return C; +} + +////////////////////////////////////////////////////////////////// + +// Normalize the input number (m), understood as ranging from -1 to 1, +// to the form: Coefficient*2^Exponent, +// where the absolute value of Coefficient is >= 1/2 +// (Coefficient>=0x4000 or Coefficient <= (int16)0xc001) + +void Dsp1::normalize(int16 m, int16 &Coefficient, int16 &Exponent) +{ + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + while ((m & i) && i) + { + i >>= 1; + e++; + } + else + while (!(m & i) && i) + { + i >>= 1; + e++; + } + + if (e > 0) + Coefficient = m * DataRom[0x21 + e] << 1; + else + Coefficient = m; + + Exponent -= e; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'normalize' but with an int32 input + +void Dsp1::normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent) +{ + int16 n = Product & 0x7fff; + int16 m = Product >> 15; + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + while ((m & i) && i) + { + i >>= 1; + e++; + } + else + while (!(m & i) && i) + { + i >>= 1; + e++; + } + + if (e > 0) + { + Coefficient = m * DataRom[0x0021 + e] << 1; + + if (e < 15) + Coefficient += n * DataRom[0x0040 - e] >> 15; + else + { + i = 0x4000; + + if (m < 0) + while ((n & i) && i) + { + i >>= 1; + e++; + } + else + while (!(n & i) && i) + { + i >>= 1; + e++; + } + + if (e > 15) + Coefficient = n * DataRom[0x0012 + e] << 1; + else + Coefficient += n; + } + } + else + Coefficient = m; + + Exponent = e; +} + +////////////////////////////////////////////////////////////////// + +// Shift to the right + +int16 Dsp1::shiftR(int16 C, int16 E) +{ + return (C * DataRom[0x0031 + E] >> 15); +} + +////////////////////////////////////////////////////////////////// + +// this is, indeed, only part of the Data ROM +const int16 Dsp1::SinTable[256] = { + 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, + 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, + 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, + 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, + 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, + 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, + 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, + -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, + -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, + -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, + -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, + -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, + -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, + -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, + -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, + -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, + -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; + + ////////////////////////////////////////////////////////////////// + +// Optimised for Performance + const int16 Dsp1::MulTable[256] = { + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, + 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, + 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, + 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, + 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, + 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, + 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, + 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, + 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, + 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, + 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, + 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, + 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, + 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, + 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, + 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, + 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, + 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, + 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, + 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, + 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, + 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, + 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, + 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, + 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, + 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, + 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, + 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, + 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, + 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, + 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; + +////////////////////////////////////////////////////////////////// + +// Data ROM, as logged from a DSP-1B with the 0x1f command; +// it contains the tables and constants used by the commands. +// The tables used are: two shift tables (0x022-0x031 and 0x031-0x040 -this last one +// with an error in 0x03c which has survived to all the DSP-1 revisions-); a inverse +// table (used as initial guess) at 0x065-0x0e4; a square root table (used also +// as initial guess) at 0x0e5-0x115; two sin and cos tables (used as nodes to construct +// a interpolation curve) at, respectively, 0x116-0x197 and 0x196-0x215. +// As a curiosity, in the positions 0x21c-0x31c it's contained a +// 257-points arccos table that, apparently, have been not used anywhere +// (maybe for the MaxAZS_Exp table?). + const uint16 Dsp1::DataRom[1024] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, + 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, + 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, + 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, + 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, + 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, + 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, + 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, + 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; + +////////////////////////////////////////////////////////////////// + diff --git a/src/chip/dsp1/_dsp1emu.h b/src/chip/dsp1/_dsp1emu.h new file mode 100644 index 00000000..537ba9a8 --- /dev/null +++ b/src/chip/dsp1/_dsp1emu.h @@ -0,0 +1,126 @@ +// DSP-1's emulation code +// +// Based on research by Overload, The Dumper, Neviksti and Andreas Naive +// Date: June 2006 + +#ifndef __DSP1EMUL_H +#define __DSP1EMUL_H + +#define DSP1_VERSION 0x0102 + +class Dsp1 +{ + public: + // The DSP-1 status register has 16 bits, but only + // the upper 8 bits can be accessed from an external device, so all these + // positions are referred to the upper byte (bits D8 to D15) + enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80}; + + // According to Overload's docs, these are the meanings of the flags: + // DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU. + // 0: Data transfer to and from the DSP-1 is 16 bits. + // 1: Data transfer to and from the DSP-1 is 8 bits. + // DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data. + // 0: Data transfer has terminated. + // 1: Data transfer in progress. + // RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write. + // 0: Internal Data Register Transfer. + // 1: External Data Register Transfer. + + Dsp1(); + uint8 getSr() const; // return the status register's high byte + uint8 getDr(); + void setDr(uint8 iDr); + void reset(); + + private: + enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA}; + enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024}; + + struct Command { + void (Dsp1::*callback)(int16 *, int16 *); + unsigned int reads; + unsigned int writes; + }; + + static const Command mCommandTable[]; + static const int16 MaxAZS_Exp[16]; + static const int16 SinTable[]; + static const int16 MulTable[]; + static const uint16 DataRom[]; + + struct SharedData { // some RAM variables shared between commands + int16 MatrixA[3][3]; // attitude matrix A + int16 MatrixB[3][3]; + int16 MatrixC[3][3]; + int16 CentreX, CentreY, CentreZ; // center of projection + int16 CentreZ_C, CentreZ_E; + int16 VOffset; // vertical offset of the screen with regard to the centre of projection + int16 Les, C_Les, E_Les; + int16 SinAas, CosAas; + int16 SinAzs, CosAzs; + int16 SinAZS, CosAZS; + int16 SecAZS_C1, SecAZS_E1; + int16 SecAZS_C2, SecAZS_E2; + int16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection) + int16 Gx, Gy, Gz; // center of the screen (global coordinates) + int16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) + int16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen) + + } shared; + + uint8 mSr; // status register + uint16 mDr; // "internal" representation of the data register + FsmMajorState mFsmMajorState; // current major state of the FSM + uint8 mCommand; // current command processed by the FSM + uint8 mDataCounter; // #uint16 read/writes counter used by the FSM + int16 mReadBuffer[MAX_READS]; + int16 mWriteBuffer[MAX_WRITES]; + bool mFreeze; // need explanation? ;) + + void fsmStep(bool read, uint8 &data); // FSM logic + + // commands + void memoryTest(int16 *input, int16 *output); + void memoryDump(int16 *input, int16 *output); + void memorySize(int16 *input, int16 *output); + void multiply(int16* input, int16* output); + void multiply2(int16* input, int16* output); + void inverse(int16 *input, int16 *output); + void triangle(int16 *input, int16 *output); + void radius(int16 *input, int16 *output); + void range(int16 *input, int16 *output); + void range2(int16 *input, int16 *output); + void distance(int16 *input, int16 *output); + void rotate(int16 *input, int16 *output); + void polar(int16 *input, int16 *output); + void attitudeA(int16 *input, int16 *output); + void attitudeB(int16 *input, int16 *output); + void attitudeC(int16 *input, int16 *output); + void objectiveA(int16 *input, int16 *output); + void objectiveB(int16 *input, int16 *output); + void objectiveC(int16 *input, int16 *output); + void subjectiveA(int16 *input, int16 *output); + void subjectiveB(int16 *input, int16 *output); + void subjectiveC(int16 *input, int16 *output); + void scalarA(int16 *input, int16 *output); + void scalarB(int16 *input, int16 *output); + void scalarC(int16 *input, int16 *output); + void gyrate(int16 *input, int16 *output); + void parameter(int16 *input, int16 *output); + void raster(int16 *input, int16 *output); + void target(int16 *input, int16 *output); + void project(int16 *input, int16 *output); + + // auxiliar functions + int16 sin(int16 Angle); + int16 cos(int16 Angle); + void inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent); + int16 denormalizeAndClip(int16 C, int16 E); + void normalize(int16 m, int16 &Coefficient, int16 &Exponent); + void normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent); + int16 shiftR(int16 C, int16 E); +}; + +#endif + diff --git a/src/chip/dsp1/dsp1.cpp b/src/chip/dsp1/dsp1.cpp new file mode 100644 index 00000000..31539697 --- /dev/null +++ b/src/chip/dsp1/dsp1.cpp @@ -0,0 +1,54 @@ +#include "../../base.h" +#include "dsp1emu.cpp" + +void DSP1::init() {} +void DSP1::enable() {} + +void DSP1::power() { + reset(); +} + +void DSP1::reset() { + dsp1.reset(); +} + +/***** + * addr_decode() + * determine whether address is accessing + * data register (DR) or status register (SR) + * -- 0 (false) = DR + * -- 1 (true ) = SR + * + * note: there is no need to bounds check addresses, + * as memory mapper will not allow DSP1 accesses outside + * of expected ranges + *****/ +bool DSP1::addr_decode(uint16 addr) { + switch(cartridge.cart.dsp1_mapper) { + + case Cartridge::DSP1_LOROM_1MB: + //$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR + return (addr >= 0xc000); + + case Cartridge::DSP1_LOROM_2MB: + //$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR + return (addr >= 0x4000); + + case Cartridge::DSP1_HIROM: + //$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR + return (addr >= 0x7000); + + } + + return 0; +} + +uint8 DSP1::read(uint16 addr) { + return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr(); +} + +void DSP1::write(uint16 addr, uint8 data) { + if(addr_decode(addr) == 0) { + dsp1.setDr(data); + } +} diff --git a/src/chip/dsp1/dsp1.h b/src/chip/dsp1/dsp1.h new file mode 100644 index 00000000..50477f31 --- /dev/null +++ b/src/chip/dsp1/dsp1.h @@ -0,0 +1,16 @@ +#include "dsp1emu.h" + +class DSP1 { +private: +Dsp1 dsp1; + +public: + void init(); + void enable(); + void power(); + void reset(); + + bool addr_decode(uint16 addr); + uint8 read (uint16 addr); + void write(uint16 addr, uint8 data); +}; diff --git a/src/chip/dsp1/dsp1emu.cpp b/src/chip/dsp1/dsp1emu.cpp new file mode 100644 index 00000000..720c7977 --- /dev/null +++ b/src/chip/dsp1/dsp1emu.cpp @@ -0,0 +1,1622 @@ +// DSP-1's emulation code +// +// Based on research by Overload, The Dumper, Neviksti and Andreas Naive +// Date: June 2006 + +////////////////////////////////////////////////////////////////// + +Dsp1::Dsp1() +{ + reset(); +} + +////////////////////////////////////////////////////////////////// + +uint8 Dsp1::getSr() +{ + mSrLowByteAccess = ~mSrLowByteAccess; + if (mSrLowByteAccess) + return 0; + else + return mSr; +} + +////////////////////////////////////////////////////////////////// + +uint8 Dsp1::getDr() +{ + uint8 oDr; + + fsmStep(true, oDr); + return oDr; +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::setDr(uint8 iDr) +{ + fsmStep(false, iDr); +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::reset() +{ + mSr = DRC|RQM; + mSrLowByteAccess = false; + mDr = 0x0080; // Only a supposition. Is this correct? + mFreeze = false; + mFsmMajorState = WAIT_COMMAND; + memset(&shared, 0, sizeof(SharedData)); // another supposition +} + +////////////////////////////////////////////////////////////////// + +// Though the DSP-1 is unaware of the type of operation (read or write) +// we need to know what is being done by the program, as the class +// is responsible for maintaining the binding between the +// "external" and "internal" representations of the DR (data register). + +void Dsp1::fsmStep(bool read, uint8 &data) +{ + if (0 == (mSr&RQM)) return; + // Now RQM would be cleared; however, as this code is not to be used in + // a multithread environment, we will simply fake RQM operation. + // (The only exception would be Op1A's freeze.) + + // binding + if (read) + { + if (mSr&DRS) + data = static_cast(mDr>>8); + else + data = static_cast(mDr); + } + else + { + if (mSr&DRS) + { + mDr &= 0x00ff; + mDr |= data<<8; + } + else + { + mDr &= 0xff00; + mDr |= data; + } + } + + + switch (mFsmMajorState) + { + case WAIT_COMMAND: + mCommand = static_cast(mDr); + if (!(mCommand & 0xc0)) // valid command? + { + switch(mCommand) + { + // freeze cases + case 0x1a: + case 0x2a: + case 0x3a: + mFreeze = true; + break; + // normal cases + default: + mDataCounter=0; + mFsmMajorState = READ_DATA; + mSr &= ~DRC; + break; + } + } + break; + case READ_DATA: + mSr ^= DRS; + if (!(mSr&DRS)) + { + mReadBuffer[mDataCounter++] = static_cast(mDr); + if (mDataCounter >= mCommandTable[mCommand].reads) + { + (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); + if (0 != mCommandTable[mCommand].writes) // any output? + { + mDataCounter = 0; + mDr = static_cast(mWriteBuffer[mDataCounter]); + mFsmMajorState = WRITE_DATA; + } + else + { + mDr = 0x0080; // valid command completion + mFsmMajorState = WAIT_COMMAND; + mSr |= DRC; + } + } + } + break; + case WRITE_DATA: + mSr ^= DRS; + if (!(mSr&DRS)) + { + ++mDataCounter; + if (mDataCounter >= mCommandTable[mCommand].writes) + { + if ((mCommand == 0x0a)&&(mDr != 0x8000)) + { + // works in continuous mode + mReadBuffer[0]++; // next raster line + (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); + mDataCounter = 0; + mDr = static_cast(mWriteBuffer[mDataCounter]); + } + else + { + mDr = 0x0080; // valid command completion + mFsmMajorState = WAIT_COMMAND; + mSr |= DRC; + } + } + else + { + mDr = static_cast(mWriteBuffer[mDataCounter]); + } + } + break; + } + + + + // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-). + if (mFreeze) + mSr &= ~RQM; +} + +////////////////////////////////////////////////////////////////// + +// The info on this table follows Overload's docs. + +const Dsp1::Command Dsp1::mCommandTable[0x40] = { + {&Dsp1::multiply, 2, 1}, //0x00 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveA, 3, 3}, //0x03 + {&Dsp1::triangle, 2, 2}, //0x04 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryTest, 1, 1}, //0x0f + {&Dsp1::radius, 3, 2}, //0x08 + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::raster, 1, 4}, // 0x0a. This will normally work in continuous mode + {&Dsp1::scalarA, 3, 1}, //0x0b + {&Dsp1::rotate, 3, 2}, //0x0c + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryTest, 1, 1}, //0x0f + + {&Dsp1::inverse, 2, 2}, //0x10 + {&Dsp1::attitudeB, 4, 0}, //0x11 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveB, 3, 3}, //0x13 + {&Dsp1::gyrate, 6, 3}, //0x14 + {&Dsp1::attitudeB, 4, 0}, //0x11 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryDump, 1, 1024}, //0x1f + {&Dsp1::range, 4, 1}, //0x18 + {&Dsp1::objectiveB, 3, 3}, //0x1d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarB, 3, 1}, //0x1b + {&Dsp1::polar, 6, 3}, //0x1c + {&Dsp1::objectiveB, 3, 3}, //0x1d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryDump, 1, 1024}, //0x1f + + {&Dsp1::multiply2, 2, 1}, //0x20 + {&Dsp1::attitudeC, 4, 0}, //0x21 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveC, 3, 3}, //0x23 + {&Dsp1::triangle, 2, 2}, //0x04 + {&Dsp1::attitudeC, 4, 0}, //0x21 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memorySize, 1, 1}, //0x2f + {&Dsp1::distance, 3, 1}, //0x28 + {&Dsp1::objectiveC, 3, 3}, //0x2d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarC, 3, 1}, //0x2b + {&Dsp1::rotate, 3, 2}, //0x0c + {&Dsp1::objectiveC, 3, 3}, //0x2d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memorySize, 1, 1}, //0x2f + + {&Dsp1::inverse, 2, 2}, //0x10 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::parameter, 7, 4}, //0x02 + {&Dsp1::subjectiveA, 3, 3}, //0x03 + {&Dsp1::gyrate, 6, 3}, //0x14 + {&Dsp1::attitudeA, 4, 0}, //0x01 + {&Dsp1::project, 3, 3}, //0x06 + {&Dsp1::memoryDump, 1, 1024}, //0x1f + {&Dsp1::range2, 4, 1}, //0x38 + {&Dsp1::objectiveA, 3, 3}, //0x0d + {0, 0, 0}, // 0x1a; the chip freezes + {&Dsp1::scalarA, 3, 1}, //0x0b + {&Dsp1::polar, 6, 3}, //0x1c + {&Dsp1::objectiveA, 3, 3}, //0x0d + {&Dsp1::target, 2, 2}, //0x0e + {&Dsp1::memoryDump, 1, 1024}, //0x1f +}; + +////////////////////////////////////////////////////////////////// + +void Dsp1::memoryTest(int16 *input, int16 *output) +{ + int16& Size = input[0]; + int16& Result = output[0]; + + Result = 0x0000; +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::memoryDump(int16 *input, int16 *output) +{ + memcpy(output, DataRom, 1024); +} + +////////////////////////////////////////////////////////////////// + +void Dsp1::memorySize(int16 *input, int16 *output) +{ + int16& Size = output[0]; + + Size = 0x0100; +} + +////////////////////////////////////////////////////////////////// + +// 16-bit multiplication + +void Dsp1::multiply(int16 *input, int16 *output) +{ + int16& Multiplicand = input[0]; + int16& Multiplier = input[1]; + int16& Product = output[0]; + + Product = Multiplicand * Multiplier >> 15; +} + +////////////////////////////////////////////////////////////////// + +// 16-bit multiplication. 'Alternative' method. Can anyone check this carefully? + +void Dsp1::multiply2(int16 *input, int16 *output) +{ + int16& Multiplicand = input[0]; + int16& Multiplier = input[1]; + int16& Product = output[0]; + + Product = (Multiplicand * Multiplier >> 15)+1; +} + +////////////////////////////////////////////////////////////////// + +// This command determines the inverse of a floating point decimal number. + +void Dsp1::inverse(int16 *input, int16 *output) +{ + int16& Coefficient = input[0]; + int16& Exponent = input[1]; + int16& iCoefficient = output[0]; + int16& iExponent = output[1]; + + inverse(Coefficient, Exponent, iCoefficient, iExponent); +} + +////////////////////////////////////////////////////////////////// + +// Vector component calculation. Determines the X and Y components for a +// two-dimensional vector whose size and direction is known. +// Y = Radius * sin(Angle) +// X = Radius * cos(Angle) + +void Dsp1::triangle(int16 *input, int16 *output) +{ + int16& Angle = input[0]; + int16& Radius = input[1]; + int16& Y = output[0]; + int16& X = output[1]; + + Y = sin(Angle) * Radius >> 15; + X = cos(Angle) * Radius >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Determines the squared norm of a vector (X,Y,Z) +// The output is Radius = X^2+Y^2+Z^2 (double integer) + +void Dsp1::radius(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& RadiusLow = output[0]; + int16& RadiusHigh = output[1]; + + int32 Radius; + + Radius = (X * X + Y * Y + Z * Z) << 1; + RadiusLow = static_cast(Radius); + RadiusHigh = static_cast(Radius>>16); +} + +////////////////////////////////////////////////////////////////// + +// Vector size comparison. This command compares the size of the vector (X,Y,Z) and the distance (R) +// from a particular point, and so may be used to determine if a point is within the sphere or radius R. +// The output is D = X^2+Y^2+Z^2-R^2 + +void Dsp1::range(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Radius = input[3]; + int16& Range = output[0]; + + Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Vector size comparison. 'Alternative' method. + +void Dsp1::range2(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Radius = input[3]; + int16& Range = output[0]; + + Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1; +} + +////////////////////////////////////////////////////////////////// + +// This command calculates the norm of a (X,Y,Z) vector, or the distance from +// the point (X,Y,Z) to (0,0,0), as you prefer to see it. +// Distance = sqrt(X^2+Y^2+Z^2) +// The square root of a number 'a' is calculated by doing this: you +// write 'a' as b*2^2n, with 'b' between 1/4 and 1; then, you calculate +// c=sqrt(b) by using lineal interpolation between points of a +// look-up table and, finally, you output the result as c*2^n. + +void Dsp1::distance(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& Distance = output[0]; + + int32 Radius = X * X + Y * Y + Z * Z; + + if (Radius == 0) Distance = 0; + else + { + int16 C, E; + normalizeDouble(Radius, C, E); + if (E & 1) C = C * 0x4000 >> 15; + + int16 Pos = C * 0x0040 >> 15; + + int16 Node1 = DataRom[0x00d5 + Pos]; + int16 Node2 = DataRom[0x00d6 + Pos]; + + Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + +#if DSP1_VERSION < 0x0102 + if (Pos & 1) Distance -= (Node2 - Node1); +#endif + Distance >>= (E >> 1); + } +} + +////////////////////////////////////////////////////////////////// + +// Determines the (X2, Y2) coordinates obtained by rotating (X1, Y1) +// clockwise for an angle 'Angle'. The official documentation says +// 'counterclockwise', but it's obviously wrong (surprise! :P) +// +// In matrix notation: +// |X2| |cos(Angle) sin(Angle)| |X1| +// | | = | | | | +// |Y2| |-sin(Angle cos(Angle)| |Y1| + +void Dsp1::rotate(int16 *input, int16 *output) +{ + int16& Angle = input[0]; + int16& X1 = input[1]; + int16& Y1 = input[2]; + int16& X2 = output[0]; + int16& Y2 = output[1]; + + X2 = (Y1 * sin(Angle) >> 15) + (X1 * cos(Angle) >> 15); + Y2 = (Y1 * cos(Angle) >> 15) - (X1 * sin(Angle) >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Calculate the coordinates (X2, Y2, Z2) obtained when rotating (X1, Y1, Z1) +// three-dimensionally. Rotation is done in the order of Az around the Z axis, +// Ay around the Y axis and Ax around the X axis. As occur with the "attitude" commands +// (see comments in the "gyrate" command), this doesn't match what explained in +// the official documentation, but it's coherent with what it is done in the "attitude" +// command (but not with the "gyrate" command). +// +// In matrix notation: +// |X2| |1 0 0 | |cosRy 0 -sinRy| | cosRz sinRz 0| |X1| +// |Y2| = |0 cosRx sinRx| | 0 1 0 | |-sinRz cosRz 0| |Y1| +// |Z2| |0 -sinRx cosRx| |sinRy 0 cosRy| | 0 0 1| |Z1| + +void Dsp1::polar(int16 *input, int16 *output) +{ + int16& Az = input[0]; + int16& Ay = input[1]; + int16& Ax = input[2]; + int16& X1 = input[3]; + int16& Y1 = input[4]; + int16& Z1 = input[5]; + int16& X2 = output[0]; + int16& Y2 = output[1]; + int16& Z2 = output[2]; + + int16 X, Y, Z; + + // Rotate Around Z + X = (Y1 * sin(Az) >> 15) + (X1 * cos(Az) >> 15); + Y = (Y1 * cos(Az) >> 15) - (X1 * sin(Az) >> 15); + X1 = X; Y1 = Y; + + // Rotate Around Y + Z = (X1 * sin(Ay) >> 15) + (Z1 * cos(Ay) >> 15); + X = (X1 * cos(Ay) >> 15) - (Z1 * sin(Ay) >> 15); + X2 = X; Z1 = Z; + + // Rotate Around X + Y = (Z1 * sin(Ax) >> 15) + (Y1 * cos(Ax) >> 15); + Z = (Z1 * cos(Ax) >> 15) - (Y1 * sin(Ax) >> 15); + Y2 = Y; Z2 = Z; +} + +////////////////////////////////////////////////////////////////// + +// Set up the elements of an "attitude matrix" (there are other ones): +// S | cosRz sinRz 0| |cosRy 0 -sinRy| |1 0 0 | +// MatrixA = - |-sinRz cosRz 0| | 0 1 0 | |0 cosRx sinRx| +// 2 | 0 0 1| |sinRy 0 cosRy| |0 -sinRx cosRx| +// This matrix is thought to be used within the following framework: +// let's suppose we define positive rotations around a system of orthogonal axes in this manner: +// a rotation of +90 degrees around axis3 converts axis2 into axis1 +// a rotation of +90 degrees around axis2 converts axis1 into axis3 +// a rotation of +90 degrees around axis1 converts axis3 into axis2 +// and let's suppose that we have defined a new orthonormal axes system (FLU) +// by doing the following operations about the standard one (XYZ): +// first rotating the XYZ system around Z by an angle Rz (obtaining X'Y'Z'), +// then rotating the resulting system around Y by an angle Ry (obtaining X''Y''Z'') +// and, finally, rotating the resulting system around X by an angle Rx (obtaining FLU) +// This FLU (forward/left/up) system represents an "attitude" and, then, the matrix here defined +// is the change of coordinates matrix that transform coordinates in the FLU +// system (the "object coordinates") into the standard XYZ system (the "global coordinates"), +// multiplied by a scale factor S/2, that is: +// |x| S |f| +// |y| * - = MatrixA * |l| +// |z| 2 |u| +// In a similar way, if we use the transpose of the matrix, we can transform global coordinates +// into object coordinates: +// |f| S |x| +// |l| * - = MatrixA_transposed * |y| +// |u| 2 |z| +// +// input[0]: S +// input[1]: Rz +// input[2]: Ry +// input[3]: Rx + +void Dsp1::attitudeA(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixA[2][0] = S * SinRy >> 15; + shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'attitudeA', but with a difference attitude matrix (matrixB) + +void Dsp1::attitudeB(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixB[2][0] = S * SinRy >> 15; + shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'attitudeA', but with a difference attitude matrix (matrixC) + +void Dsp1::attitudeC(int16 *input, int16 *output) +{ + int16& S = input[0]; + int16& Rz = input[1]; + int16& Ry = input[2]; + int16& Rx = input[3]; + + int16 SinRz = sin(Rz); + int16 CosRz = cos(Rz); + int16 SinRy = sin(Ry); + int16 CosRy = cos(Ry); + int16 SinRx = sin(Rx); + int16 CosRx = cos(Rx); + + S >>= 1; + + shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15; + shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15); + shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); + shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); + + shared.MatrixC[2][0] = S * SinRy >> 15; + shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15); + shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Convert global coordinates (X,Y,Z) to object coordinates (F,L,U) +// See the comment in "attitudeA" for a explanation about the calculation. +// +// input[0]: X ; input[1]: Y ; input[2]: Z +// output[0]: F ; output[1]: L ; output[2]: U + +void Dsp1::objectiveA(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixA[0][0] * X >> 15) + (shared.MatrixA[1][0] * Y >> 15) + (shared.MatrixA[2][0] * Z >> 15); + L = (shared.MatrixA[0][1] * X >> 15) + (shared.MatrixA[1][1] * Y >> 15) + (shared.MatrixA[2][1] * Z >> 15); + U = (shared.MatrixA[0][2] * X >> 15) + (shared.MatrixA[1][2] * Y >> 15) + (shared.MatrixA[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'objectiveA', but for the 'B' attitude + +void Dsp1::objectiveB(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixB[0][0] * X >> 15) + (shared.MatrixB[1][0] * Y >> 15) + (shared.MatrixB[2][0] * Z >> 15); + L = (shared.MatrixB[0][1] * X >> 15) + (shared.MatrixB[1][1] * Y >> 15) + (shared.MatrixB[2][1] * Z >> 15); + U = (shared.MatrixB[0][2] * X >> 15) + (shared.MatrixB[1][2] * Y >> 15) + (shared.MatrixB[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'objectiveA', but for the 'C' attitude + +void Dsp1::objectiveC(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& F = output[0]; + int16& L = output[1]; + int16& U = output[2]; + + F = (shared.MatrixC[0][0] * X >> 15) + (shared.MatrixC[1][0] * Y >> 15) + (shared.MatrixC[2][0] * Z >> 15); + L = (shared.MatrixC[0][1] * X >> 15) + (shared.MatrixC[1][1] * Y >> 15) + (shared.MatrixC[2][1] * Z >> 15); + U = (shared.MatrixC[0][2] * X >> 15) + (shared.MatrixC[1][2] * Y >> 15) + (shared.MatrixC[2][2] * Z >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Convert object coordinates (F,L,U) to object coordinates (X,Y,Z) +// See the comment in "attitudeA" for a explanation about the calculation. +// +// input[0]: F ; input[1]: L ; input[2]: U +// output[0]: X ; output[1]: Y ; output[2]: Z + +void Dsp1::subjectiveA(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixA[0][0] * F >> 15) + (shared.MatrixA[0][1] * L >> 15) + (shared.MatrixA[0][2] * U >> 15); + Y = (shared.MatrixA[1][0] * F >> 15) + (shared.MatrixA[1][1] * L >> 15) + (shared.MatrixA[1][2] * U >> 15); + Z = (shared.MatrixA[2][0] * F >> 15) + (shared.MatrixA[2][1] * L >> 15) + (shared.MatrixA[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'subjectiveA', but for the 'B' attitude + +void Dsp1::subjectiveB(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixB[0][0] * F >> 15) + (shared.MatrixB[0][1] * L >> 15) + (shared.MatrixB[0][2] * U >> 15); + Y = (shared.MatrixB[1][0] * F >> 15) + (shared.MatrixB[1][1] * L >> 15) + (shared.MatrixB[1][2] * U >> 15); + Z = (shared.MatrixB[2][0] * F >> 15) + (shared.MatrixB[2][1] * L >> 15) + (shared.MatrixB[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// Same than 'subjectiveA', but for the 'C' attitude + +void Dsp1::subjectiveC(int16 *input, int16 *output) +{ + int16& F = input[0]; + int16& L = input[1]; + int16& U = input[2]; + int16& X = output[0]; + int16& Y = output[1]; + int16& Z = output[2]; + + X = (shared.MatrixC[0][0] * F >> 15) + (shared.MatrixC[0][1] * L >> 15) + (shared.MatrixC[0][2] * U >> 15); + Y = (shared.MatrixC[1][0] * F >> 15) + (shared.MatrixC[1][1] * L >> 15) + (shared.MatrixC[1][2] * U >> 15); + Z = (shared.MatrixC[2][0] * F >> 15) + (shared.MatrixC[2][1] * L >> 15) + (shared.MatrixC[2][2] * U >> 15); +} + +////////////////////////////////////////////////////////////////// + +// This command calculates the inner product (S) of a vector (X,Y,Z) and +// the first column of MatrixA. It should be noted that that first column +// represent the global coordinates of an unity vector in the forward +// direction in the object coordinate system (coordinates (1,0,0) in the FLU +// axes system). +// +// input[0]: X ; input[1]: Y ; input[2]: Z +// output[0]: S + +void Dsp1::scalarA(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixA[0][0] + Y * shared.MatrixA[1][0] + Z * shared.MatrixA[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'scalarA', but for the 'B' attitude + +void Dsp1::scalarB(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixB[0][0] + Y * shared.MatrixB[1][0] + Z * shared.MatrixB[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'scalarA', but for the 'C' attitude + +void Dsp1::scalarC(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& S = output[0]; + + S = (X * shared.MatrixC[0][0] + Y * shared.MatrixC[1][0] + Z * shared.MatrixC[2][0]) >> 15; +} + +////////////////////////////////////////////////////////////////// + +// This command determines the final attitude angles after the body with attitude angles (Ax, Ay, Az) with +// respect to the global coordinates is rotated by the minor angular displacements (DeltaF, DeltaL, DeltaU). +// It means that the XYZ axes are rotated by (Ax, Ay, Az) to obtain the FLU axes and, then, these +// are rotated by (DeltaF, DeltaL, DeltaU). The command calculates and return the new FLU angles respect to the +// XYZ system (Rx, Ry, Rz) +// The formulae are: +// Rx = Ax + (DeltaU*sin(Ay)+DeltaF*cos(Ay)) +// Ry = Ay + DeltaL - tan(Ax)*(DeltaU*cos(Ay)+DeltaF*sin(Ay)) +// Rz = Az + sec(Ax)*(DeltaU*cos(Ay)-DeltaF*sin(Ay)) +// +// Now the discussion: according to the official documentation, as described in various commands, you pass from +// XYZ to FLU by doing the rotations in the order Y, X, Z. In this command, the formulae are coherent with the +// fact that Y is the first axis to do a rotation around it. However, in the "attitude" command, while the official +// document describe it that way, we have discovered, when reverse engineering the command, that the calculated +// matrix do the rotation around Y in the second place. This incoherent behaviour of various commands is, in my +// opinion, a pretty severe implementation error. However, if you only use small "minor displacements", the error term +// introduced by that incoherence should be almost negligible. + +void Dsp1::gyrate(int16 *input, int16 *output) +{ + int16& Az = input[0]; + int16& Ax = input[1]; + int16& Ay = input[2]; + int16& U = input[3]; + int16& F = input[4]; + int16& L = input[5]; + int16& Rz = output[0]; + int16& Rx = output[1]; + int16& Ry = output[2]; + + int16 CSec, ESec, CSin, C, E; + int16 SinAy = sin(Ay); + int16 CosAy = cos(Ay); + + inverse(cos(Ax), 0, CSec, ESec); + + // Rotation Around Z + normalizeDouble(U * CosAy - F * SinAy, C, E); + + E = ESec - E; + + normalize(C * CSec >> 15, C, E); + + Rz = Az + denormalizeAndClip(C, E); + + // Rotation Around X + Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); + + // Rotation Around Y + normalizeDouble(U * CosAy + F * SinAy, C, E); + + E = ESec - E; + + normalize(sin(Ax), CSin, E); + + normalize(-(C * (CSec * CSin >> 15) >> 15), C, E); + + Ry = Ay + denormalizeAndClip(C, E) + L; +} + +////////////////////////////////////////////////////////////////// + +const int16 Dsp1::MaxAZS_Exp[16] = { + 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, + 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 +}; + +////////////////////////////////////////////////////////////////// + + +// Set-up the projection framework. Besides returning some values, it store in RAM some values that +// will be used by the other three projection commands (raster, target an project) +// Input: +// (Fx, Fy, Fz)-> coordinates of base point (global coordinates) +// Lfe-> distance between the base point and the viewpoint (center of projection) +// Les-> distance between the base point and the screen +// Aas-> azimuth angle (0º is east; 90ª is north) +// Azs-> zenith angle (0º is zenith) +// Output: +// Vof-> raster line of imaginary center (whatever it means ;) ) +// Vva-> raster line representing the horizon line +// (Cx, Cy)-> coordinates of the projection of the center of the screen over the ground (ground coordinates) + +void Dsp1::parameter(int16 *input, int16 *output) +{ + int16& Fx = input[0]; + int16& Fy = input[1]; + int16& Fz = input[2]; + int16& Lfe = input[3]; + int16& Les = input[4]; + int16& Aas = input[5]; + int16& Azs = input[6]; + int16& Vof = output[0]; + int16& Vva = output[1]; + int16& Cx = output[2]; + int16& Cy = output[3]; + + int16 CSec, C, E; + int16 LfeNx, LfeNy, LfeNz; + int16 LesNx, LesNy, LesNz; + + // Copy Zenith angle for clipping + int16 AZS = Azs; + + // Store Les and his coefficient and exponent when normalized + shared.Les = Les; + shared.E_Les=0; + normalize(Les, shared.C_Les, shared.E_Les); + + // Store Sine and Cosine of Azimuth and Zenith angle + shared.SinAas = sin(Aas); + shared.CosAas = cos(Aas); + shared.SinAzs = sin(Azs); + shared.CosAzs = cos(Azs); + + // normal vector to the screen (norm 1, points toward the center of projection) + shared.Nx = shared.SinAzs * -shared.SinAas >> 15; + shared.Ny = shared.SinAzs * shared.CosAas >> 15; + shared.Nz = shared.CosAzs * 0x7fff >> 15; + + // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) + shared.Hx = shared.CosAas*0x7fff>>15; + shared.Hy = shared.SinAas*0x7fff>>15; + + // vertical vector of the screen (norm 1, points toward the top of the screen) + shared.Vx = shared.CosAzs*-shared.SinAas>>15; + shared.Vy = shared.CosAzs*shared.CosAas>>15; + shared.Vz = -shared.SinAzs*0x7fff>>15; + + LfeNx = Lfe*shared.Nx>>15; + LfeNy = Lfe*shared.Ny>>15; + LfeNz = Lfe*shared.Nz>>15; + + // Center of Projection + shared.CentreX = Fx+LfeNx; + shared.CentreY = Fy+LfeNy; + shared.CentreZ = Fz+LfeNz; + + LesNx = Les*shared.Nx>>15; + LesNy = Les*shared.Ny>>15; + LesNz = Les*shared.Nz>>15; + + // center of the screen (global coordinates) + shared.Gx=shared.CentreX-LesNx; + shared.Gy=shared.CentreY-LesNy; + shared.Gz=shared.CentreZ-LesNz; + + + E = 0; + normalize(shared.CentreZ, C, E); + + shared.CentreZ_C = C; + shared.CentreZ_E = E; + + // Determine clip boundary and clip Zenith angle if necessary + // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...) + int16 MaxAZS = MaxAZS_Exp[-E]; + + if (AZS < 0) { + MaxAZS = -MaxAZS; + if (AZS < MaxAZS + 1) AZS = MaxAZS + 1; + } else { + if (AZS > MaxAZS) AZS = MaxAZS; + } + + // Store Sine and Cosine of clipped Zenith angle + shared.SinAZS = sin(AZS); + shared.CosAZS = cos(AZS); + + // calculate the separation of (cx, cy) from the projection of + // the 'centre of projection' over the ground... (CentreZ*tg(AZS)) + inverse(shared.CosAZS, 0, shared.SecAZS_C1, shared.SecAZS_E1); + normalize(C * shared.SecAZS_C1 >> 15, C, E); + E += shared.SecAZS_E1; + C = denormalizeAndClip(C, E) * shared.SinAZS >> 15; + + // ... and then take into account the position of the centre of + // projection and the azimuth angle + shared.CentreX += C * shared.SinAas >> 15; + shared.CentreY -= C * shared.CosAas >> 15; + + Cx = shared.CentreX; + Cy = shared.CentreY; + + // Raster number of imaginary center and horizontal line + Vof = 0; + + if ((Azs != AZS) || (Azs == MaxAZS)) + { + // correct vof and vva when Azs is outside the 'non-clipping interval' + // we have only some few Taylor coefficients, so we cannot guess which ones + // are the approximated functions and, what is worse, we don't know why + // the own clipping stuff (and, particularly, this correction) is done + if (Azs == -32768) Azs = -32767; + + C = Azs - MaxAZS; + if (C >= 0) C--; + int16 Aux = ~(C << 2); + + // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 + C = Aux * DataRom[0x0328] >> 15; + C = (C * Aux >> 15) + DataRom[0x0327]; + Vof -= (C * Aux >> 15) * Les >> 15; + + // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 + C = Aux * Aux >> 15; + Aux = (C * DataRom[0x0324] >> 15) + DataRom[0x0325]; + shared.CosAZS += (C * Aux >> 15) * shared.CosAZS >> 15; + } + + // vertical offset of the screen with regard to the horizontal plane + // containing the centre of projection + shared.VOffset = Les * shared.CosAZS >> 15; + + // The horizon line (the line in the screen that is crossed by the horizon plane + // -the horizontal plane containing the 'centre of projection'-), + // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult + // to explain but easily seen in a graph. To better see it, consider it in this way: + // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;) + inverse(shared.SinAZS, 0, CSec, E); + normalize(shared.VOffset, C, E); + normalize(C * CSec >> 15, C, E); + + if (C == -32768) { C >>= 1; E++; } + + Vva = denormalizeAndClip(-C, E); + + // Store Secant of clipped Zenith angle + inverse(shared.CosAZS, 0, shared.SecAZS_C2, shared.SecAZS_E2); +} + +////////////////////////////////////////////////////////////////// + +// Calculates the matrix which transform an object situated on a raster line (Vs) into +// his projection over the ground. The modified SecAZS is used here, so +// i don't understand the fine details, but, basically, it's done +// this way: The vertical offset between the point of projection and the +// raster line is calculated (Vs*SinAzs>>15)+VOffset, then the height of +// the center of projection is measured in that units (*CentreZ_C). If, now +// you consider the "reference case" (center of projection at an unit of height), +// the projection of a thin strip containing the raster line will have the same +// width (as the raster line would be on the ground in this case, but will suffer a +// change of scale in height (as the ground and the vertical axis would form an angle of 180º-Azs). +// This scale factor, when the angle 'center of screen-center of projection-raster line' is small, +// can be aproximated by the one of the center of the screen, 1/cos(Azs).(**) (Here is when it's used +// SecAZS). By last, you have to consider the effect of the azimuth angle Aas, and you are done. +// +// Using matrix notation: +// |A B| Centre_ZS | cos(Aas) -sin(Aas)| |1 0| +// ProjectionMatrix = | | = ----------- * | | * | | +// |C D| Vs*sin(Azs) |sin(Aas) cos(Aas)| |0 sec(Azs)| +// +// (**) +// If Les=1, the vertical offset between the center +// of projection and the center of the screen is Cos(Azs); then, if the vertical +// offset is 1, the ratio of the projection over the ground respect to the +// line on the screen is 1/cos(Azs). + +void Dsp1::raster(int16 *input, int16 *output) +{ + int16& Vs = input[0]; + int16& An = output[0]; + int16& Bn = output[1]; + int16& Cn = output[2]; + int16& Dn = output[3]; + + int16 C, E, C1, E1; + + inverse((Vs * shared.SinAzs >> 15) + shared.VOffset, 7, C, E); + + E += shared.CentreZ_E; + C1 = C * shared.CentreZ_C >> 15; + + E1 = E + shared.SecAZS_E2; + + normalize(C1, C, E); + C = denormalizeAndClip(C, E); + + An = C * shared.CosAas >> 15; + Cn = C * shared.SinAas >> 15; + + normalize(C1 * shared.SecAZS_C2 >> 15, C, E1); + C = denormalizeAndClip(C, E1); + + Bn = C * -shared.SinAas >> 15; + Dn = C * shared.CosAas >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Calculate the projection over the ground of a selected point of screen +// It simply apply the projection matrix described in the "Raster" command +// to the vector (H,V) transposed, and add the result to the position of +// the centre of projection. +// The only special point to take into account is the directions on the screen: +// H is positive rightward, but V is positive downward; this is why +// the signs take that configuration + +void Dsp1::target(int16 *input, int16 *output) +{ + int16& H = input[0]; + int16& V = input[1]; + int16& X = output[0]; + int16& Y = output[1]; + + int16 C, E, C1, E1; + + inverse((V * shared.SinAzs >> 15) + shared.VOffset, 8, C, E); + + E += shared.CentreZ_E; + C1 = C * shared.CentreZ_C >> 15; + + E1 = E + shared.SecAZS_E1; + + H <<= 8; + normalize(C1, C, E); + C = denormalizeAndClip(C, E) * H >> 15; + + X = shared.CentreX + (C * shared.CosAas >> 15); + Y = shared.CentreY - (C * shared.SinAas >> 15); + + V <<= 8; + normalize(C1 * shared.SecAZS_C1 >> 15, C, E1); + C = denormalizeAndClip(C, E1) * V >> 15; + + X += C * -shared.SinAas >> 15; + Y += C * shared.CosAas >> 15; +} + +////////////////////////////////////////////////////////////////// + +// Calculation of the projection over the screen (H,V) of an object (X,Y,Z) and his +// 'enlargement ratio' (M). The positive directions on the screen are as described +// in the targe command. M is scaled down by 2^-7, that is, M==0x0100 means ratio 1:1 + + void Dsp1::project(int16 *input, int16 *output) +{ + int16& X = input[0]; + int16& Y = input[1]; + int16& Z = input[2]; + int16& H = output[0]; + int16& V = output[1]; + int16& M = output[2]; + + int32 aux, aux4; + int16 E, E2, E3, E4, E5, refE, E6, E7; + int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; + int16 Px, Py, Pz; + + E4=E3=E2=E=E5=0; + + normalizeDouble(int32(X)-shared.Gx, Px, E4); + normalizeDouble(int32(Y)-shared.Gy, Py, E); + normalizeDouble(int32(Z)-shared.Gz, Pz, E3); + Px>>=1; E4--; // to avoid overflows when calculating the scalar products + Py>>=1; E--; + Pz>>=1; E3--; + + refE = (E>15); + C8=- (Py*shared.Ny>>15); + C9=- (Pz*shared.Nz>>15); + C12=C11+C8+C9; // this cannot overflow! + + aux4=C12; // de-normalization with 32-bits arithmetic + refE = 16-refE; // refE can be up to 3 + if (refE>=0) + aux4 <<=(refE); + else + aux4 >>=-(refE); + if (aux4==-1) aux4 = 0; // why? + aux4>>=1; + + aux = static_cast(shared.Les) + aux4; // Les - the scalar product of P with the normal vector of the screen + normalizeDouble(aux, C10, E2); + E2 = 15-E2; + + inverse(C10, 0, C4, E4); + C2=C4*shared.C_Les>>15; // scale factor + + + // H + E7=0; + C16= (Px*shared.Hx>>15); + C20= (Py*shared.Hy>>15); + C17=C16+C20; // scalar product of P with the normalized horizontal vector of the screen... + + C18=C17*C2>>15; // ... multiplied by the scale factor + normalize(C18, C19, E7); + H=denormalizeAndClip(C19, shared.E_Les-E2+refE+E7); + + // V + E6=0; + C21 = Px*shared.Vx>>15; + C22 = Py*shared.Vy>>15; + C23 = Pz*shared.Vz>>15; + C24=C21+C22+C23; // scalar product of P with the normalized vertical vector of the screen... + + C26=C24*C2>>15; // ... multiplied by the scale factor + normalize(C26, C25, E6); + V=denormalizeAndClip(C25, shared.E_Les-E2+refE+E6); + + // M + normalize(C2, C6, E4); + M=denormalizeAndClip(C6, E4+shared.E_Les-E2-7); // M is the scale factor divided by 2^7 +} + +////////////////////////////////////////////////////////////////// + +// Calculate the sine of the input parameter +// this is done by linear interpolation between +// the points of a look-up table + +int16 Dsp1::sin(int16 Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return 0; + return -sin(-Angle); + } + int32 S = SinTable[Angle >> 8] + (MulTable[Angle & 0xff] * SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) S = 32767; + return (int16) S; +} + +////////////////////////////////////////////////////////////////// + +// Calculate the cosine of the input parameter. +// It's used the same method than in sin(int16) + +int16 Dsp1::cos(int16 Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return -32768; + Angle = -Angle; + } + int32 S = SinTable[0x40 + (Angle >> 8)] - (MulTable[Angle & 0xff] * SinTable[Angle >> 8] >> 15); + if (S < -32768) S = -32767; + return (int16) S; +} + +////////////////////////////////////////////////////////////////// + +// Determines the inverse of a floating point decimal number +// iCoefficient*2^iExponent = 1/(Coefficient*2^Exponent), with the output +// normalized (iCoefficient represents a number whose absolute value is between 1/2 and 1) +// To invert 'Coefficient' a first initial guess is taken from a look-up table +// and, then, two iterations of the Newton method (applied to the function +// f(x)=1/(2*x)-Coefficient) are done. This results in a close approximation (iCoefficient) to a number 'y' +// that verify Coefficient*y=1/2. This is why you have to correct the exponent by one +// unit at the end. + +void Dsp1::inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent) +{ + // Step One: Division by Zero + if (Coefficient == 0x0000) + { + iCoefficient = 0x7fff; + iExponent = 0x002f; + } + else + { + int16 Sign = 1; + + // Step Two: Remove Sign + if (Coefficient < 0) + { + if (Coefficient < -32767) Coefficient = -32767; + Coefficient = -Coefficient; + Sign = -1; + } + + // Step Three: Normalize + while (Coefficient < 0x4000) + { + Coefficient <<= 1; + Exponent--; + } + + // Step Four: Special Case + if (Coefficient == 0x4000) + if (Sign == 1) iCoefficient = 0x7fff; + else { + iCoefficient = -0x4000; + Exponent--; + } + else { + // Step Five: Initial Guess + int16 i = DataRom[((Coefficient - 0x4000) >> 7) + 0x0065]; + + // Step Six: Iterate Newton's Method + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + + iCoefficient = i * Sign; + } + + iExponent = 1 - Exponent; + } +} + +////////////////////////////////////////////////////////////////// + +int16 Dsp1::denormalizeAndClip(int16 C, int16 E) +{ + if (E > 0) { + if (C > 0) return 32767; else if (C < 0) return -32767; + } else { + if (E < 0) return C * DataRom[0x0031 + E] >> 15; + } + return C; +} + +////////////////////////////////////////////////////////////////// + +// Normalize the input number (m), understood as ranging from -1 to 1, +// to the form: Coefficient*2^Exponent, +// where the absolute value of Coefficient is >= 1/2 +// (Coefficient>=0x4000 or Coefficient <= (int16)0xc001) + +void Dsp1::normalize(int16 m, int16 &Coefficient, int16 &Exponent) +{ + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + while ((m & i) && i) + { + i >>= 1; + e++; + } + else + while (!(m & i) && i) + { + i >>= 1; + e++; + } + + if (e > 0) + Coefficient = m * DataRom[0x21 + e] << 1; + else + Coefficient = m; + + Exponent -= e; +} + +////////////////////////////////////////////////////////////////// + +// Same than 'normalize' but with an int32 input + +void Dsp1::normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent) +{ + int16 n = Product & 0x7fff; + int16 m = Product >> 15; + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + while ((m & i) && i) + { + i >>= 1; + e++; + } + else + while (!(m & i) && i) + { + i >>= 1; + e++; + } + + if (e > 0) + { + Coefficient = m * DataRom[0x0021 + e] << 1; + + if (e < 15) + Coefficient += n * DataRom[0x0040 - e] >> 15; + else + { + i = 0x4000; + + if (m < 0) + while ((n & i) && i) + { + i >>= 1; + e++; + } + else + while (!(n & i) && i) + { + i >>= 1; + e++; + } + + if (e > 15) + Coefficient = n * DataRom[0x0012 + e] << 1; + else + Coefficient += n; + } + } + else + Coefficient = m; + + Exponent = e; +} + +////////////////////////////////////////////////////////////////// + +// Shift to the right + +int16 Dsp1::shiftR(int16 C, int16 E) +{ + return (C * DataRom[0x0031 + E] >> 15); +} + +////////////////////////////////////////////////////////////////// + +// this is, indeed, only part of the Data ROM +const int16 Dsp1::SinTable[256] = { + 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, + 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, + 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, + 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, + 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, + 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, + 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, + -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, + -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, + -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, + -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, + -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, + -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, + -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, + -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, + -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, + -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; + + ////////////////////////////////////////////////////////////////// + +// Optimised for Performance + const int16 Dsp1::MulTable[256] = { + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, + 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, + 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, + 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, + 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, + 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, + 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, + 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, + 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, + 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, + 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, + 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, + 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, + 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, + 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, + 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, + 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, + 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, + 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, + 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, + 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, + 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, + 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, + 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, + 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, + 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, + 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, + 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, + 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, + 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, + 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; + +////////////////////////////////////////////////////////////////// + +// Data ROM, as logged from a DSP-1B with the 0x1f command; +// it contains the tables and constants used by the commands. +// The tables used are: two shift tables (0x022-0x031 and 0x031-0x040 -this last one +// with an error in 0x03c which has survived to all the DSP-1 revisions-); a inverse +// table (used as initial guess) at 0x065-0x0e4; a square root table (used also +// as initial guess) at 0x0e5-0x115; two sin and cos tables (used as nodes to construct +// a interpolation curve) at, respectively, 0x116-0x197 and 0x196-0x215. +// As a curiosity, in the positions 0x21c-0x31c it's contained a +// 257-points arccos table that, apparently, have been not used anywhere +// (maybe for the MaxAZS_Exp table?). + const uint16 Dsp1::DataRom[1024] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, + 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, + 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, + 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, + 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, + 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, + 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, + 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, + 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; + +////////////////////////////////////////////////////////////////// + diff --git a/src/chip/dsp1/dsp1emu.h b/src/chip/dsp1/dsp1emu.h new file mode 100644 index 00000000..c89e57d7 --- /dev/null +++ b/src/chip/dsp1/dsp1emu.h @@ -0,0 +1,127 @@ +// DSP-1's emulation code +// +// Based on research by Overload, The Dumper, Neviksti and Andreas Naive +// Date: June 2006 + +#ifndef __DSP1EMUL_H +#define __DSP1EMUL_H + +#define DSP1_VERSION 0x0102 + +class Dsp1 +{ + public: + // The DSP-1 status register has 16 bits, but only + // the upper 8 bits can be accessed from an external device, so all these + // positions are referred to the upper byte (bits D8 to D15) + enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80}; + + // According to Overload's docs, these are the meanings of the flags: + // DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU. + // 0: Data transfer to and from the DSP-1 is 16 bits. + // 1: Data transfer to and from the DSP-1 is 8 bits. + // DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data. + // 0: Data transfer has terminated. + // 1: Data transfer in progress. + // RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write. + // 0: Internal Data Register Transfer. + // 1: External Data Register Transfer. + + Dsp1(); + uint8 getSr(); // return the status register's high byte + uint8 getDr(); + void setDr(uint8 iDr); + void reset(); + + private: + enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA}; + enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024}; + + struct Command { + void (Dsp1::*callback)(int16 *, int16 *); + unsigned int reads; + unsigned int writes; + }; + + static const Command mCommandTable[]; + static const int16 MaxAZS_Exp[16]; + static const int16 SinTable[]; + static const int16 MulTable[]; + static const uint16 DataRom[]; + + struct SharedData { // some RAM variables shared between commands + int16 MatrixA[3][3]; // attitude matrix A + int16 MatrixB[3][3]; + int16 MatrixC[3][3]; + int16 CentreX, CentreY, CentreZ; // center of projection + int16 CentreZ_C, CentreZ_E; + int16 VOffset; // vertical offset of the screen with regard to the centre of projection + int16 Les, C_Les, E_Les; + int16 SinAas, CosAas; + int16 SinAzs, CosAzs; + int16 SinAZS, CosAZS; + int16 SecAZS_C1, SecAZS_E1; + int16 SecAZS_C2, SecAZS_E2; + int16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection) + int16 Gx, Gy, Gz; // center of the screen (global coordinates) + int16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) + int16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen) + + } shared; + + uint8 mSr; // status register + int mSrLowByteAccess; + uint16 mDr; // "internal" representation of the data register + FsmMajorState mFsmMajorState; // current major state of the FSM + uint8 mCommand; // current command processed by the FSM + uint8 mDataCounter; // #uint16 read/writes counter used by the FSM + int16 mReadBuffer[MAX_READS]; + int16 mWriteBuffer[MAX_WRITES]; + bool mFreeze; // need explanation? ;) + + void fsmStep(bool read, uint8 &data); // FSM logic + + // commands + void memoryTest(int16 *input, int16 *output); + void memoryDump(int16 *input, int16 *output); + void memorySize(int16 *input, int16 *output); + void multiply(int16* input, int16* output); + void multiply2(int16* input, int16* output); + void inverse(int16 *input, int16 *output); + void triangle(int16 *input, int16 *output); + void radius(int16 *input, int16 *output); + void range(int16 *input, int16 *output); + void range2(int16 *input, int16 *output); + void distance(int16 *input, int16 *output); + void rotate(int16 *input, int16 *output); + void polar(int16 *input, int16 *output); + void attitudeA(int16 *input, int16 *output); + void attitudeB(int16 *input, int16 *output); + void attitudeC(int16 *input, int16 *output); + void objectiveA(int16 *input, int16 *output); + void objectiveB(int16 *input, int16 *output); + void objectiveC(int16 *input, int16 *output); + void subjectiveA(int16 *input, int16 *output); + void subjectiveB(int16 *input, int16 *output); + void subjectiveC(int16 *input, int16 *output); + void scalarA(int16 *input, int16 *output); + void scalarB(int16 *input, int16 *output); + void scalarC(int16 *input, int16 *output); + void gyrate(int16 *input, int16 *output); + void parameter(int16 *input, int16 *output); + void raster(int16 *input, int16 *output); + void target(int16 *input, int16 *output); + void project(int16 *input, int16 *output); + + // auxiliar functions + int16 sin(int16 Angle); + int16 cos(int16 Angle); + void inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent); + int16 denormalizeAndClip(int16 C, int16 E); + void normalize(int16 m, int16 &Coefficient, int16 &Exponent); + void normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent); + int16 shiftR(int16 C, int16 E); +}; + +#endif + diff --git a/src/chip/dsp2/dsp2.h b/src/chip/dsp2/dsp2.h index 1c3b9a45..a506454c 100644 --- a/src/chip/dsp2/dsp2.h +++ b/src/chip/dsp2/dsp2.h @@ -1,13 +1,13 @@ class DSP2 { public: struct { - bool waiting_for_command; - uint command; - uint in_count, in_index; - uint out_count, out_index; + bool waiting_for_command; + uint command; + uint in_count, in_index; + uint out_count, out_index; - uint8 parameters[512]; - uint8 output[512]; + uint8 parameters[512]; + uint8 output[512]; uint8 op05transparent; bool op05haslen; @@ -20,6 +20,7 @@ struct { int op0doutlen; int op0dinlen; } status; + void init(); void enable(); void power(); diff --git a/src/config/config.cpp b/src/config/config.cpp index 624cf2e7..a486fdd9 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -55,7 +55,7 @@ void SNES::VideoColorAdjust::set(uint32 _data) { Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields", "Merge fields in NTSC video filter\n" "Set to true if using filter at any refresh rate other than 60hz\n" -"", false, Setting::TRUE_FALSE); +"", true, Setting::TRUE_FALSE); Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled", false, Setting::TRUE_FALSE); diff --git a/src/cpu/bcpu/bcpu.cpp b/src/cpu/bcpu/bcpu.cpp index 8d5dae8c..d7f8ae3d 100644 --- a/src/cpu/bcpu/bcpu.cpp +++ b/src/cpu/bcpu/bcpu.cpp @@ -27,11 +27,11 @@ void bCPU::run() { if(!run_state.irq && !run_state.stp) { if(time.nmi_pending == true) { time.nmi_pending = false; - aa.w = 0xffea; + aa.w = (regs.e == false) ? 0xffea : 0xfffa; run_state.irq = true; } else if(time.irq_pending == true) { time.irq_pending = false; - aa.w = 0xffee; + aa.w = (regs.e == false) ? 0xffee : 0xfffe; run_state.irq = true; } } @@ -41,9 +41,9 @@ void bCPU::run() { } void bCPU::scanline() { - time.hdma_triggered = false; + time.hdma_triggered = (vcounter() <= (!overscan() ? 224 : 239)) ? false : true; - if(vcounter() == (overscan() == false ? 227 : 242) && status.auto_joypad_poll == true) { + if(vcounter() == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) { snes->poll_input(SNES::DEV_JOYPAD1); snes->poll_input(SNES::DEV_JOYPAD2); //When the SNES auto-polls the joypads, it writes 1, then 0 to @@ -93,9 +93,6 @@ void bCPU::reset() { regs.e = 1; regs.mdr = 0x00; -//simulate pbr:pc push during reset irq vector - regs.s.l -= 3; - time_reset(); mmio_reset(); dma_reset(); diff --git a/src/cpu/bcpu/bcpu.h b/src/cpu/bcpu/bcpu.h index 9018027e..fd0dbef4 100644 --- a/src/cpu/bcpu/bcpu.h +++ b/src/cpu/bcpu/bcpu.h @@ -82,7 +82,7 @@ struct { inline uint8 pio_status(); inline void run(); - inline uint32 cycles_executed(); + inline uint32 clocks_executed(); inline void scanline(); inline void frame(); inline void power(); diff --git a/src/cpu/bcpu/bcpu_exec.cpp b/src/cpu/bcpu/bcpu_exec.cpp index 3020aff9..427f9e4f 100644 --- a/src/cpu/bcpu/bcpu_exec.cpp +++ b/src/cpu/bcpu/bcpu_exec.cpp @@ -1,8 +1,8 @@ void bCPU::last_cycle() { //DMV27: keep previous nmi value, //to allow wai and irq to work properly - time.nmi_pending = nmi_test() || time.nmi_pending; - time.irq_pending = irq_test(); + time.nmi_pending |= nmi_test(); + time.irq_pending |= irq_test(); } void bCPU::pre_exec_cycle() { @@ -56,12 +56,7 @@ static int z; status.hdma_state = HDMASTATE_IDMASYNC3; break; case HDMASTATE_IDMASYNC3: - channel[z].hdma_active = channel[z].hdma_enabled; - if(channel[z].hdma_enabled) { - channel[z].hdma_addr = channel[z].srcaddr; - hdma_update(z); //updates status.hdma_cycle_count - } - if(++z < 8)break; + hdma_init(); if(!run_state.dma) { status.hdma_state = HDMASTATE_ICPUSYNC; } else { @@ -89,7 +84,7 @@ static int z; status.hdma_state = HDMASTATE_DMASYNC3; break; case HDMASTATE_DMASYNC3: - if(channel[z].hdma_active) { + if(channel[z].hdma_line_counter) { add_cycles(8); status.hdma_cycle_count += 8; } @@ -126,7 +121,7 @@ static int z; status.dma_state = DMASTATE_DMASYNC3; break; case DMASTATE_DMASYNC3: - if(channel[z].active == true) { + if(channel[z].dma_enabled == true) { add_cycles(8); status.dma_cycle_count += 8; } diff --git a/src/cpu/bcpu/bcpu_int.cpp b/src/cpu/bcpu/bcpu_int.cpp index d2ee6e5f..3c4e8b69 100644 --- a/src/cpu/bcpu/bcpu_int.cpp +++ b/src/cpu/bcpu/bcpu_int.cpp @@ -32,7 +32,7 @@ void bCPU::irq_run() { break; case 5: //emulation-mode irqs clear brk bit 0x10 - stack_write((regs.e) ? (regs.p & ~0x10) : regs.p); + stack_write(regs.e ? (regs.p & ~0x10) : regs.p); break; case 6: //todo: test if NMI can override IRQ here... @@ -83,6 +83,5 @@ _true: time.irq_transition = 0; run_state.wai = false; - if(regs.p.i)return false; - return true; + return (regs.p.i) ? false : true; } diff --git a/src/cpu/bcpu/bcpu_mmio.cpp b/src/cpu/bcpu/bcpu_mmio.cpp index d2a03a7c..0b3b0c6d 100644 --- a/src/cpu/bcpu/bcpu_mmio.cpp +++ b/src/cpu/bcpu/bcpu_mmio.cpp @@ -329,12 +329,12 @@ uint8 bCPU::mmio_r43xb(uint8 i) { uint8 bCPU::mmio_read(uint16 addr) { //APU - if(addr >= 0x2140 && addr <= 0x217f) { + if((addr & 0xffc0) == 0x2140) { //$2140-$217f return r_apu->port_read(addr & 3); } //HDMA - if(addr >= 0x4300 && addr <= 0x437f) { + if((addr & 0xff80) == 0x4300) { //$4300-$437f uint i = (addr >> 4) & 7; switch(addr & 0xf) { case 0x0: return mmio_r43x0(i); @@ -457,6 +457,7 @@ void bCPU::mmio_w4202(uint8 value) { status.mul_a = value; } +//WRMPYB void bCPU::mmio_w4203(uint8 value) { status.mul_b = value; status.r4216 = status.mul_a * status.mul_b; @@ -464,7 +465,7 @@ void bCPU::mmio_w4203(uint8 value) { //WRDIVL void bCPU::mmio_w4204(uint8 value) { - status.div_a = (status.div_a & 0xff00) | value; + status.div_a = (status.div_a & 0xff00) | (value); } //WRDIVH @@ -504,6 +505,7 @@ void bCPU::mmio_w420a(uint8 value) { } //DMAEN +//DMA enable does not disable active HDMA channels void bCPU::mmio_w420b(uint8 value) { if(value != 0x00) { run_state.dma = true; @@ -511,11 +513,9 @@ void bCPU::mmio_w420b(uint8 value) { } for(int i = 0; i < 8; i++) { - if(value & (1 << i)) { - //DMA enable does not disable active HDMA channels - channel[i].active = true; - channel[i].read_index = 0; - } + channel[i].dma_enabled = bool(value & (1 << i)); + //TODO: clearing read_index may interfere with DMA+HDMA occurring simultaneously + if(channel[i].dma_enabled)channel[i].read_index = 0; } } @@ -523,7 +523,6 @@ void bCPU::mmio_w420b(uint8 value) { void bCPU::mmio_w420c(uint8 value) { for(int i = 0; i < 8; i++) { channel[i].hdma_enabled = bool(value & (1 << i)); - channel[i].hdma_active = bool(value & (1 << i)); } } @@ -599,13 +598,13 @@ void bCPU::mmio_w43xb(uint8 value, uint8 i) { void bCPU::mmio_write(uint16 addr, uint8 data) { //APU - if(addr >= 0x2140 && addr <= 0x217f) { + if((addr & 0xffc0) == 0x2140) { //$2140-$217f port_write(addr & 3, data); return; } //HDMA - if(addr >= 0x4300 && addr <= 0x437f) { + if((addr & 0xff80) == 0x4300) { //$4300-$437f uint i = (addr >> 4) & 7; switch(addr & 0xf) { case 0x0: mmio_w43x0(data, i); return; diff --git a/src/cpu/bcpu/core/clean.bat b/src/cpu/bcpu/core/clean.bat index eeb92f44..d807f14d 100644 --- a/src/cpu/bcpu/core/clean.bat +++ b/src/cpu/bcpu/core/clean.bat @@ -1,8 +1 @@ @del *.exe -@del op_misc.cpp -@del op_pc.cpp -@del op_read.cpp -@del op_rmw.cpp -@del op_write.cpp -@del optable.cpp -@del op.h diff --git a/src/cpu/bcpu/dma/dma.cpp b/src/cpu/bcpu/dma/dma.cpp index b7442b28..259fd45d 100644 --- a/src/cpu/bcpu/dma/dma.cpp +++ b/src/cpu/bcpu/dma/dma.cpp @@ -31,6 +31,20 @@ uint8 r; } } +uint8 bCPU::dma_bbus(uint8 i, uint8 index) { + switch(channel[i].xfermode) { + default: + case 0: return (channel[i].destaddr); break; //0 + case 1: return (channel[i].destaddr + (index & 1)); break; //0,1 + case 2: return (channel[i].destaddr); break; //0,0 + case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 + case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3 + case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1 + case 6: return (channel[i].destaddr); break; //0,0 [2] + case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3] + } +} + void bCPU::dma_add_cycles(uint32 cycles) { status.dma_cycle_count += cycles; } @@ -53,19 +67,19 @@ uint32 r; return r; } -void bCPU::dma_cputommio(uint8 i, uint8 index) { - if(sdd1->dma_active() == true) { - r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), sdd1->dma_read()); +void bCPU::dma_cputommio(uint8 i, uint8 bbus) { + if(cartridge.cart.sdd1 == true && sdd1->dma_active() == true) { + r_mem->write(0x2100 | bbus, sdd1->dma_read()); } else { - dma_transfer_byte(0, ((channel[i].destaddr + index) & 0xff), dma_addr(i)); + dma_transfer_byte(0, bbus, dma_addr(i)); } add_cycles(8); channel[i].xfersize--; } -void bCPU::dma_mmiotocpu(uint8 i, uint8 index) { - dma_transfer_byte(1, ((channel[i].destaddr + index) & 0xff), dma_addr(i)); +void bCPU::dma_mmiotocpu(uint8 i, uint8 bbus) { + dma_transfer_byte(1, bbus, dma_addr(i)); add_cycles(8); channel[i].xfersize--; @@ -81,30 +95,19 @@ void bCPU::dma_write(uint8 i, uint8 index) { void bCPU::dma_run() { for(int i = 0; i < 8; i++) { - if(channel[i].active == false)continue; + if(channel[i].dma_enabled == false)continue; //first byte transferred? - if(channel[i].read_index == 0) { + if(cartridge.cart.sdd1 == true && channel[i].read_index == 0) { sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize); } - switch(channel[i].xfermode) { - case 0: dma_write(i, 0); break; //0 - case 1: dma_write(i, channel[i].read_index & 1); break; //0,1 - case 2: dma_write(i, 0); break; //0,0 - case 3: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1 - case 4: dma_write(i, channel[i].read_index & 3); break; //0,1,2,3 - case 5: dma_write(i, channel[i].read_index & 1); break; //0,1,0,1 - case 6: dma_write(i, 0); break; //0,0 [2] - case 7: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1 [3] - } - - channel[i].read_index++; + dma_write(i, dma_bbus(i, channel[i].read_index++)); dma_add_cycles(8); if(channel[i].xfersize == 0) { - channel[i].active = false; + channel[i].dma_enabled = false; } return; @@ -121,23 +124,6 @@ uint32 bCPU::hdma_iaddr(uint8 i) { return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++); } -uint16 bCPU::hdma_mmio(uint8 i) { -uint8 l = channel[i].read_index; -uint16 index; - switch(channel[i].xfermode) { - case 0: index = 0; break; //0 - case 1: index = l & 1; break; //0,1 - case 2: index = 0; break; //0,0 - case 3: index = (l >> 1) & 1; break; //0,0,1,1 - case 4: index = l & 3; break; //0,1,2,3 - case 5: index = l & 1; break; //0,1,0,1 - case 6: index = 0; break; //0,0 [2] - case 7: index = (l >> 1) & 1; break; //0,0,1,1 [3] - } - - return (0x2100 | ((channel[i].destaddr + index) & 0xff)); -} - void bCPU::hdma_update(uint8 i) { channel[i].hdma_line_counter = r_mem->read(hdma_addr(i)); add_cycles(8); @@ -150,7 +136,7 @@ void bCPU::hdma_update(uint8 i) { } if(channel[i].hdma_line_counter == 0) { - channel[i].hdma_active = false; + channel[i].hdma_completed = true; channel[i].hdma_do_transfer = false; return; } @@ -168,13 +154,13 @@ void bCPU::hdma_update(uint8 i) { void bCPU::hdma_run() { static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 }; for(int i = 0; i < 8; i++) { - if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue; + if(!channel[i].hdma_enabled || channel[i].hdma_completed)continue; if(channel[i].hdma_do_transfer) { int xferlen = hdma_xferlen[channel[i].xfermode]; for(channel[i].read_index = 0; channel[i].read_index < xferlen; channel[i].read_index++) { if(bool(config::cpu.hdma_enable) == true) { - dma_transfer_byte(channel[i].direction, hdma_mmio(i), + dma_transfer_byte(channel[i].direction, dma_bbus(i, channel[i].read_index), channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i)); } add_cycles(8); @@ -190,6 +176,15 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 }; } } +void bCPU::hdma_init() { + for(int i = 0; i < 8; i++) { + if(!channel[i].hdma_enabled)continue; + + channel[i].hdma_addr = channel[i].srcaddr; + hdma_update(i); + } +} + uint8 bCPU::hdma_enabled_channels() { int r = 0; for(int i = 0; i < 8; i++) { @@ -201,7 +196,7 @@ int r = 0; uint8 bCPU::hdma_active_channels() { int r = 0; for(int i = 0; i < 8; i++) { - if(channel[i].hdma_enabled && channel[i].hdma_active)r++; + if(channel[i].hdma_enabled && !channel[i].hdma_completed)r++; } return r; } @@ -215,7 +210,7 @@ int r = 0; void bCPU::hdmainit_activate() { for(int i = 0; i < 8; i++) { - channel[i].hdma_active = false; + channel[i].hdma_completed = false; channel[i].hdma_do_transfer = false; } @@ -240,7 +235,7 @@ void bCPU::dma_reset() { for(int i = 0; i < 8; i++) { channel[i].read_index = 0; - channel[i].active = false; + channel[i].dma_enabled = false; channel[i].hdma_enabled = false; channel[i].dmap = 0xff; channel[i].direction = 1; @@ -259,7 +254,7 @@ void bCPU::dma_reset() { channel[i].hdma_line_counter = 0xff; channel[i].hdma_unknown = 0xff; - channel[i].hdma_active = false; + channel[i].hdma_completed = false; channel[i].hdma_do_transfer = false; } } diff --git a/src/cpu/bcpu/dma/dma.h b/src/cpu/bcpu/dma/dma.h index 2a123703..fd0ba726 100644 --- a/src/cpu/bcpu/dma/dma.h +++ b/src/cpu/bcpu/dma/dma.h @@ -2,7 +2,7 @@ struct { uint32 read_index; //set to 0 at beginning of DMA/HDMA //$420b - bool active; + bool dma_enabled; //$420c bool hdma_enabled; //$43x0 @@ -33,7 +33,7 @@ struct { uint8 hdma_unknown; //hdma-specific - bool hdma_active; + bool hdma_completed; //for this frame bool hdma_do_transfer; uint8 hdma_current_channel; @@ -41,10 +41,12 @@ struct { } channel[8]; inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus); + inline uint8 dma_bbus(uint8 i, uint8 index); inline void dma_add_cycles(uint32 cycles); inline void hdma_add_cycles(uint32 cycles); inline void dma_run(); inline void hdma_run(); + inline void hdma_init(); inline void hdma_update(uint8 i); inline uint8 hdma_enabled_channels(); inline uint8 hdma_active_channels(); @@ -56,5 +58,4 @@ struct { inline uint32 dma_addr(uint8 i); inline uint32 hdma_addr(uint8 i); inline uint32 hdma_iaddr(uint8 i); - inline uint16 hdma_mmio(uint8 i); inline void dma_reset(); diff --git a/src/cpu/bcpu/timing/timing.cpp b/src/cpu/bcpu/timing/timing.cpp index 6e84f6a3..1f857f59 100644 --- a/src/cpu/bcpu/timing/timing.cpp +++ b/src/cpu/bcpu/timing/timing.cpp @@ -48,15 +48,16 @@ uint16 hc = 2 + offset; bool bCPU::irq_trigger_pos_match(uint32 offset) { uint16 v = status.virq_pos; uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0; +uint16 vlimit = region_scanlines() >> 1; //positions that can never be latched -//region_scanlines() = 262/NTSC, 312/PAL +//region_scanlines() = 525/NTSC, 625/PAL //PAL results are unverified on hardware if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false; - if(v == (region_scanlines() - 1) && hc == 339 && interlace() == false)return false; - if(v == region_scanlines() && interlace() == false)return false; - if(v == region_scanlines() && hc == 339)return false; - if(v > region_scanlines())return false; + if(v == (vlimit - 1) && hc == 339 && interlace() == false)return false; + if(v == vlimit && interlace() == false)return false; + if(v == vlimit && hc == 339)return false; + if(v > vlimit)return false; if(hc > 339)return false; hc = (hc != 0) ? ((hc << 2) + 14) : 10; @@ -88,15 +89,16 @@ void bCPU::update_nmi() { void bCPU::update_irq() { int vpos = status.virq_pos; int hpos = (status.hirq_enabled) ? status.hirq_pos : 0; +int vlimit = region_scanlines() >> 1; //positions that can never be latched //region_scanlines() = 262/NTSC, 312/PAL //PAL results are unverified on hardware if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch; - if(vpos == (region_scanlines() - 1) && hpos == 339 && interlace() == false)goto _nolatch; - if(vpos == region_scanlines() && interlace() == false)goto _nolatch; - if(vpos == region_scanlines() && hpos == 339)goto _nolatch; - if(vpos > region_scanlines())goto _nolatch; + if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)goto _nolatch; + if(vpos == vlimit && interlace() == false)goto _nolatch; + if(vpos == vlimit && hpos == 339)goto _nolatch; + if(vpos > vlimit)goto _nolatch; if(hpos > 339)goto _nolatch; hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10; @@ -201,9 +203,9 @@ void bCPU::inc_vcounter() { time.interlace_field ^= 1; if(interlace() == true && interlace_field() == 0) { - time.frame_lines = time.region_scanlines + 1; + time.frame_lines = (time.region_scanlines >> 1) + 1; } else { - time.frame_lines = time.region_scanlines; + time.frame_lines = (time.region_scanlines >> 1); } } @@ -233,7 +235,7 @@ uint16 bCPU::get_hcounter() { return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2; } -uint32 bCPU::cycles_executed() { +uint32 bCPU::clocks_executed() { uint32 r = status.cycles_executed; status.cycles_executed = 0; return r; @@ -248,18 +250,16 @@ void bCPU::cycle_edge() { } if(time.hdma_triggered == false) { - if(time.v <= (overscan() ? 239 : 224)) { - if(time.hc >= 1106) { - time.hdma_triggered = true; - hdma_activate(); - } + //hdma_triggered only set to false for v <= (overscan ? 239 : 224) + if(time.hc >= 1106) { + time.hdma_triggered = true; + hdma_activate(); } } } void bCPU::add_cycles(int cycles) { status.cycles_executed += cycles; - poll_interrupts(cycles); if(time.hc + cycles >= time.line_cycles) { @@ -267,7 +267,6 @@ void bCPU::add_cycles(int cycles) { time.hc = 0; inc_vcounter(); - poll_interrupts(cycles); if(time.v == 0) { frame(); @@ -279,8 +278,20 @@ void bCPU::add_cycles(int cycles) { r_ppu->scanline(); snes->scanline(); time.line_rendered = false; + + poll_interrupts(cycles); } + time.hc += cycles; + + if(time.dram_refreshed == false) { + if(time.hc >= time.dram_refresh_pos) { + time.dram_refreshed = true; + add_cycles(40); + return; + } + } +/* if(time.dram_refreshed == false) { if(time.hc + cycles >= time.dram_refresh_pos) { time.dram_refreshed = true; @@ -299,19 +310,19 @@ void bCPU::add_cycles(int cycles) { } } } - +*/ if(time.line_rendered == false) { //rendering should start at H=18 (+256=274), but since the //current PPU emulation renders the entire scanline at once, //PPU register changes mid-scanline do not show up. //therefore, wait a few dots before rendering the scanline - if(time.hc + cycles >= (48 * 4)) { + if(time.hc >= (48 * 4)) { time.line_rendered = true; r_ppu->render_scanline(); } } - time.hc += cycles; +//time.hc += cycles; } void bCPU::time_reset() { @@ -347,12 +358,12 @@ void bCPU::time_reset() { switch(region) { case NTSC: - time.region_scanlines = 262; + time.region_scanlines = 525; break; case PAL: - time.region_scanlines = 312; + time.region_scanlines = 625; break; } - time.frame_lines = time.region_scanlines; + time.frame_lines = time.region_scanlines >> 1; } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 915a06b0..8026f73d 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -12,9 +12,9 @@ uint8 cpu_version; virtual uint16 vcounter() = 0; virtual uint16 hcounter() = 0; virtual uint16 hcycles() = 0; - virtual bool overscan() = 0; virtual bool interlace() = 0; virtual bool interlace_field() = 0; + virtual bool overscan() = 0; virtual uint16 region_scanlines() = 0; virtual void set_interlace(bool r) = 0; virtual void set_overscan (bool r) = 0; @@ -30,14 +30,32 @@ CPURegs regs; FLAG_Z = 0x02, FLAG_C = 0x01 }; virtual uint8 pio_status() = 0; + virtual void main() {} virtual void run() = 0; - virtual uint32 cycles_executed() = 0; + virtual uint32 clocks_executed() = 0; virtual void scanline() = 0; virtual void frame() = 0; virtual void power() = 0; virtual void reset() = 0; -//opcode disassembler +/***** + * in opcode-based CPU emulators, the main emulation routine + * will only be able to call the disassemble_opcode() function + * on clean opcode edges. but with cycle-based CPU emulators, + * the CPU may be in the middle of executing an opcode when the + * emulator (e.g. debugger) wants to disassemble an opcode. this + * would mean that important registers may not reflect what they + * did at the start of the opcode (especially regs.pc), so in + * cycle-based emulators, this function should be overridden to + * reflect whether or not an opcode has only been partially + * executed. if not, the debugger should abort attempts to skip, + * disable, or disassemble the current opcode. + *****/ + virtual bool in_opcode() { return false; } + +/***** + * opcode disassembler + *****/ enum { OPTYPE_DP = 0, //dp OPTYPE_DPX, //dp,x @@ -57,16 +75,17 @@ enum { OPTYPE_SR, //sr,s OPTYPE_ISRY, //(sr,s),y OPTYPE_ADDR_PC, //pbr:addr - OPTYPE_IADDR_PC //pbr:(addr) + OPTYPE_IADDR_PC, //pbr:(addr) + OPTYPE_RELB, //relb + OPTYPE_RELW, //relw }; -//see dcpu.cpp for notes on this function - virtual bool in_opcode(); void disassemble_opcode(char *output); - uint32 resolve_offset(uint8 offset_type, uint32 addr); + uint8 dreadb(uint32 addr); + uint16 dreadw(uint32 addr); + uint32 dreadl(uint32 addr); + uint32 decode(uint8 offset_type, uint32 addr); uint8 opcode_length(); - uint16 __relb(int8 offset); - uint16 __relw(int16 offset); CPU(); virtual ~CPU() {} diff --git a/src/cpu/cpuregs.h b/src/cpu/cpuregs.h index bf5207cb..62852687 100644 --- a/src/cpu/cpuregs.h +++ b/src/cpu/cpuregs.h @@ -1,20 +1,18 @@ class CPURegFlags { private: - template class bit { + template class bit { public: - uint8 _b; - inline operator bool() { return (_b & B); } - inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); } - inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); } - inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); } - inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); } - inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); } - inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); } - inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); } + uint data; + inline operator bool() { return bool(data & mask); } + inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); } + inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); } + inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); } + inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); } }; + public: union { - uint8 _b; + uint8 data; bit<0x80> n; bit<0x40> v; bit<0x20> m, p; @@ -25,64 +23,57 @@ union { bit<0x01> c; }; - CPURegFlags() { _b = 0; } - inline operator uint8() { return _b; } - inline unsigned operator = (uint8 i) { _b = i; return _b; } - inline unsigned operator &= (uint8 i) { _b &= i; return _b; } - inline unsigned operator |= (uint8 i) { _b |= i; return _b; } - inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; } + CPURegFlags() { data = 0; } + inline operator unsigned() { return data; } + inline unsigned operator = (const uint8 i) { data = i; return data; } + inline unsigned operator |= (const uint8 i) { data |= i; return data; } + inline unsigned operator ^= (const uint8 i) { data ^= i; return data; } + inline unsigned operator &= (const uint8 i) { data &= i; return data; } }; class CPUReg16 { public: union { uint16 w; -#ifdef ARCH_LSB - struct { uint8 l, h; }; -#else - struct { uint8 h, l; }; -#endif + struct { uint8 order_lsb2(l, h); }; }; CPUReg16() { w = 0; } - inline operator uint16() { return w; } - inline unsigned operator = (uint16 i) { w = i; return w; } - inline unsigned operator += (uint16 i) { w += i; return w; } - inline unsigned operator -= (uint16 i) { w -= i; return w; } - inline unsigned operator *= (uint16 i) { w *= i; return w; } - inline unsigned operator /= (uint16 i) { w /= i; return w; } - inline unsigned operator &= (uint16 i) { w &= i; return w; } - inline unsigned operator |= (uint16 i) { w |= i; return w; } - inline unsigned operator ^= (uint16 i) { w ^= i; return w; } - inline unsigned operator <<= (uint16 i) { w <<= i; return w; } - inline unsigned operator >>= (uint16 i) { w >>= i; return w; } + inline operator unsigned() { return w; } + template inline unsigned operator = (const T i) { w = i; return w; } + template inline unsigned operator |= (const T i) { w |= i; return w; } + template inline unsigned operator ^= (const T i) { w ^= i; return w; } + template inline unsigned operator &= (const T i) { w &= i; return w; } + template inline unsigned operator <<= (const T i) { w <<= i; return w; } + template inline unsigned operator >>= (const T i) { w >>= i; return w; } + template inline unsigned operator += (const T i) { w += i; return w; } + template inline unsigned operator -= (const T i) { w -= i; return w; } + template inline unsigned operator *= (const T i) { w *= i; return w; } + template inline unsigned operator /= (const T i) { w /= i; return w; } + template inline unsigned operator %= (const T i) { w %= i; return w; } }; class CPUReg24 { public: union { uint32 d; -#ifdef ARCH_LSB - struct { uint16 w, null_w; }; - struct { uint8 l, h, b, null_b; }; -#else - struct { uint16 null_w, w; }; - struct { uint8 null_b, b, h, l; }; -#endif + struct { uint16 order_lsb2(w, wh); }; + struct { uint8 order_lsb4(l, h, b, bh); }; }; CPUReg24() { d = 0; } - inline operator uint32() { return (d & 0xffffff); } - inline unsigned operator = (uint16 i) { d = i; return d; } - inline unsigned operator += (uint16 i) { d += i; return d; } - inline unsigned operator -= (uint16 i) { d -= i; return d; } - inline unsigned operator *= (uint16 i) { d *= i; return d; } - inline unsigned operator /= (uint16 i) { d /= i; return d; } - inline unsigned operator &= (uint16 i) { d &= i; return d; } - inline unsigned operator |= (uint16 i) { d |= i; return d; } - inline unsigned operator ^= (uint16 i) { d ^= i; return d; } - inline unsigned operator <<= (uint16 i) { d <<= i; return d; } - inline unsigned operator >>= (uint16 i) { d >>= i; return d; } + inline operator unsigned() { return d; } + template inline unsigned operator = (const T i) { d = uclip<24>(i); return d; } + template inline unsigned operator |= (const T i) { d = uclip<24>(d | i); return d; } + template inline unsigned operator ^= (const T i) { d = uclip<24>(d ^ i); return d; } + template inline unsigned operator &= (const T i) { d = uclip<24>(d & i); return d; } + template inline unsigned operator <<= (const T i) { d = uclip<24>(d << i); return d; } + template inline unsigned operator >>= (const T i) { d = uclip<24>(d >> i); return d; } + template inline unsigned operator += (const T i) { d = uclip<24>(d + i); return d; } + template inline unsigned operator -= (const T i) { d = uclip<24>(d - i); return d; } + template inline unsigned operator *= (const T i) { d = uclip<24>(d * i); return d; } + template inline unsigned operator /= (const T i) { d = uclip<24>(d / i); return d; } + template inline unsigned operator %= (const T i) { d = uclip<24>(d % i); return d; } }; class CPURegs { @@ -90,8 +81,8 @@ public: CPUReg24 pc; CPUReg16 a, x, y, s, d; CPURegFlags p; -uint8 db; -uint8 mdr; //memory data register (openbus) -bool e; +uint8 db; +uint8 mdr; +bool e; CPURegs() { db = 0; mdr = 0x00; e = false; } }; diff --git a/src/cpu/dcpu.cpp b/src/cpu/dcpu.cpp index 8a3952ae..5a6ed51e 100644 --- a/src/cpu/dcpu.cpp +++ b/src/cpu/dcpu.cpp @@ -1,30 +1,28 @@ -//this is a virtual function. -//in opcode-based CPU emulators, the main emulation routine -//will only be able to call the disassemble_opcode() function -//on clean opcode edges. but with cycle-based CPU emulators, -//the CPU may be in the middle of executing an opcode when the -//emulator (e.g. debugger) wants to disassemble an opcode. this -//would mean that important registers may not reflect what they -//did at the start of the opcode (especially regs.pc), so in -//cycle-based emulators, this function should be overridden to -//reflect whether or not an opcode has only been partially -//executed. if not, the debugger should abort attempts to skip, -//disable, or disassemble the current opcode. -bool CPU::in_opcode() { return false; } - -uint16 CPU::__relb(int8 offset) { -uint32 addr; - addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 2) & 0xffff); - return addr + offset; +uint8 CPU::dreadb(uint32 addr) { + if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) { + //$[00-3f|80-bf]:[2000-5fff] + //do not read MMIO registers within debugger + return 0x00; + } + return r_mem->read(addr); } -uint16 CPU::__relw(int16 offset) { -uint32 addr; - addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 3) & 0xffff); - return addr + offset; +uint16 CPU::dreadw(uint32 addr) { +uint16 r; + r = dreadb((addr + 0) & 0xffffff) << 0; + r |= dreadb((addr + 1) & 0xffffff) << 8; + return r; } -uint32 CPU::resolve_offset(uint8 offset_type, uint32 addr) { +uint32 CPU::dreadl(uint32 addr) { +uint32 r; + r = dreadb((addr + 0) & 0xffffff) << 0; + r |= dreadb((addr + 1) & 0xffffff) << 8; + r |= dreadb((addr + 2) & 0xffffff) << 16; + return r; +} + +uint32 CPU::decode(uint8 offset_type, uint32 addr) { uint32 r = 0; switch(offset_type) { case OPTYPE_DP: @@ -38,23 +36,23 @@ uint32 r = 0; break; case OPTYPE_IDP: addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + r_mem->read_word(addr); + r = (regs.db << 16) + dreadw(addr); break; case OPTYPE_IDPX: addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + r_mem->read_word(addr); + r = (regs.db << 16) + dreadw(addr); break; case OPTYPE_IDPY: addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + r_mem->read_word(addr) + regs.y; + r = (regs.db << 16) + dreadw(addr) + regs.y; break; case OPTYPE_ILDP: addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = r_mem->read_long(addr); + r = dreadl(addr); break; case OPTYPE_ILDPY: addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = r_mem->read_long(addr) + regs.y; + r = dreadl(addr) + regs.y; break; case OPTYPE_ADDR: r = (regs.db << 16) + (addr & 0xffff); @@ -75,31 +73,37 @@ uint32 r = 0; r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff); break; case OPTYPE_ILADDR: - r = addr & 0xffffff; + r = addr; break; case OPTYPE_LONG: - r = addr & 0xffffff; + r = addr; break; case OPTYPE_LONGX: - r = (addr + regs.x) & 0xffffff; + r = (addr + regs.x); break; case OPTYPE_SR: r = (regs.s + (addr & 0xff)) & 0xffff; break; case OPTYPE_ISRY: addr = (regs.s + (addr & 0xff)) & 0xffff; - r = (regs.db << 16) + r_mem->read_word(addr) + regs.y; + r = (regs.db << 16) + dreadw(addr) + regs.y; + break; + case OPTYPE_RELB: + r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff); + r += int8(addr); + break; + case OPTYPE_RELW: + r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff); + r += int16(addr); break; } - return r; + return(r & 0xffffff); } void CPU::disassemble_opcode(char *output) { -char *s; -char t[256]; -uint8 op, op0, op1, op2; static CPUReg24 pc; - s = output; +char t[256]; +char *s = output; if(in_opcode() == true) { strcpy(s, "?????? "); @@ -107,332 +111,334 @@ static CPUReg24 pc; } pc.d = regs.pc.d; - sprintf(s, "%0.6x ", pc.d); + sprintf(s, "%0.6x ", uint32(pc.d)); - op = r_mem->read(pc.d); pc.w++; - op0 = r_mem->read(pc.d); pc.w++; - op1 = r_mem->read(pc.d); pc.w++; - op2 = r_mem->read(pc.d); +uint8 op = dreadb(pc.d); pc.w++; +uint8 op0 = dreadb(pc.d); pc.w++; +uint8 op1 = dreadb(pc.d); pc.w++; +uint8 op2 = dreadb(pc.d); +#define op8 ((op0)) +#define op16 ((op0) | (op1 << 8)) +#define op24 ((op0) | (op1 << 8) | (op2 << 16)) +#define a8 (regs.e || regs.p.m) +#define x8 (regs.e || regs.p.x) switch(op) { - case 0x00:sprintf(t, "brk #$%0.2x ", op0);break; - case 0x01:sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0x02:sprintf(t, "cop #$%0.2x ", op0);break; - case 0x03:sprintf(t, "ora $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0x04:sprintf(t, "tsb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x05:sprintf(t, "ora $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x06:sprintf(t, "asl $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x07:sprintf(t, "ora [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0x08:sprintf(t, "php ");break; - case 0x09: - if(regs.p.m)sprintf(t, "ora #$%0.2x ", op0); - else sprintf(t, "ora #$%0.4x ", op0|op1<<8);break; - case 0x0a:sprintf(t, "asl a ");break; - case 0x0b:sprintf(t, "phd ");break; - case 0x0c:sprintf(t, "tsb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x0d:sprintf(t, "ora $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x0e:sprintf(t, "asl $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x0f:sprintf(t, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x10:sprintf(t, "bpl $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x11:sprintf(t, "ora ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0x12:sprintf(t, "ora ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0x13:sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0x14:sprintf(t, "trb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x15:sprintf(t, "ora $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x16:sprintf(t, "asl $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x17:sprintf(t, "ora [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0x18:sprintf(t, "clc ");break; - case 0x19:sprintf(t, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0x1a:sprintf(t, "inc ");break; - case 0x1b:sprintf(t, "tcs ");break; - case 0x1c:sprintf(t, "trb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x1d:sprintf(t, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x1e:sprintf(t, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x1f:sprintf(t, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0x20:sprintf(t, "jsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break; - case 0x21:sprintf(t, "and ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0x22:sprintf(t, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x23:sprintf(t, "and $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0x24:sprintf(t, "bit $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x25:sprintf(t, "and $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x26:sprintf(t, "rol $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x27:sprintf(t, "and [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0x28:sprintf(t, "plp ");break; - case 0x29: - if(regs.p.m)sprintf(t, "and #$%0.2x ", op0); - else sprintf(t, "and #$%0.4x ", op0|op1<<8);break; - case 0x2a:sprintf(t, "rol a ");break; - case 0x2b:sprintf(t, "pld ");break; - case 0x2c:sprintf(t, "bit $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x2d:sprintf(t, "and $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x2e:sprintf(t, "rol $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x2f:sprintf(t, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x30:sprintf(t, "bmi $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x31:sprintf(t, "and ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0x32:sprintf(t, "and ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0x33:sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0x34:sprintf(t, "bit $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x35:sprintf(t, "and $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x36:sprintf(t, "rol $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x37:sprintf(t, "and [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0x38:sprintf(t, "sec ");break; - case 0x39:sprintf(t, "and $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0x3a:sprintf(t, "dec ");break; - case 0x3b:sprintf(t, "tsc ");break; - case 0x3c:sprintf(t, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x3d:sprintf(t, "and $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x3e:sprintf(t, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x3f:sprintf(t, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0x40:sprintf(t, "rti ");break; - case 0x41:sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0x42:sprintf(t, "wdm ");break; - case 0x43:sprintf(t, "eor $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0x44:sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op0);break; - case 0x45:sprintf(t, "eor $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x46:sprintf(t, "lsr $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x47:sprintf(t, "eor [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0x48:sprintf(t, "pha ");break; - case 0x49: - if(regs.p.m)sprintf(t, "eor #$%0.2x ", op0); - else sprintf(t, "eor #$%0.4x ", op0|op1<<8);break; - case 0x4a:sprintf(t, "lsr a ");break; - case 0x4b:sprintf(t, "phk ");break; - case 0x4c:sprintf(t, "jmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break; - case 0x4d:sprintf(t, "eor $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x4e:sprintf(t, "lsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x4f:sprintf(t, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x50:sprintf(t, "bvc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x51:sprintf(t, "eor ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0x52:sprintf(t, "eor ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0x53:sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0x54:sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op0);break; - case 0x55:sprintf(t, "eor $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x56:sprintf(t, "lsr $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x57:sprintf(t, "eor [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0x58:sprintf(t, "cli ");break; - case 0x59:sprintf(t, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0x5a:sprintf(t, "phy ");break; - case 0x5b:sprintf(t, "tcd ");break; - case 0x5c:sprintf(t, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x5d:sprintf(t, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x5e:sprintf(t, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x5f:sprintf(t, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0x60:sprintf(t, "rts ");break; - case 0x61:sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0x62:sprintf(t, "per $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x63:sprintf(t, "adc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0x64:sprintf(t, "stz $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x65:sprintf(t, "adc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x66:sprintf(t, "ror $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x67:sprintf(t, "adc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0x68:sprintf(t, "pla ");break; - case 0x69: - if(regs.p.m)sprintf(t, "adc #$%0.2x ", op0); - else sprintf(t, "adc #$%0.4x ", op0|op1<<8);break; - case 0x6a:sprintf(t, "ror a ");break; - case 0x6b:sprintf(t, "rtl ");break; - case 0x6c:sprintf(t, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDR_PC, (op0|op1<<8)));break; - case 0x6d:sprintf(t, "adc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x6e:sprintf(t, "ror $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x6f:sprintf(t, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x70:sprintf(t, "bvs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x71:sprintf(t, "adc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0x72:sprintf(t, "adc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0x73:sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0x74:sprintf(t, "stz $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x75:sprintf(t, "adc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x76:sprintf(t, "ror $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x77:sprintf(t, "adc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0x78:sprintf(t, "sei ");break; - case 0x79:sprintf(t, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0x7a:sprintf(t, "ply ");break; - case 0x7b:sprintf(t, "tdc ");break; - case 0x7c:sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break; - case 0x7d:sprintf(t, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x7e:sprintf(t, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x7f:sprintf(t, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0x80:sprintf(t, "bra $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x81:sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0x82:sprintf(t, "brl $%0.4x [$%0.6x]", __relw(op0|op1<<8)&0xffff, __relw(op0|op1<<8)&0xffffff);break; - case 0x83:sprintf(t, "sta $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0x84:sprintf(t, "sty $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x85:sprintf(t, "sta $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x86:sprintf(t, "stx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0x87:sprintf(t, "sta [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0x88:sprintf(t, "dey ");break; - case 0x89: - if(regs.p.m)sprintf(t, "bit #$%0.2x ", op0); - else sprintf(t, "bit #$%0.4x ", op0|op1<<8);break; - case 0x8a:sprintf(t, "txa ");break; - case 0x8b:sprintf(t, "phb ");break; - case 0x8c:sprintf(t, "sty $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x8d:sprintf(t, "sta $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x8e:sprintf(t, "stx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x8f:sprintf(t, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0x90:sprintf(t, "bcc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0x91:sprintf(t, "sta ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0x92:sprintf(t, "sta ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0x93:sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0x94:sprintf(t, "sty $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x95:sprintf(t, "sta $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0x96:sprintf(t, "stx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break; - case 0x97:sprintf(t, "sta [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0x98:sprintf(t, "tya ");break; - case 0x99:sprintf(t, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0x9a:sprintf(t, "txs ");break; - case 0x9b:sprintf(t, "txy ");break; - case 0x9c:sprintf(t, "stz $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0x9d:sprintf(t, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x9e:sprintf(t, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0x9f:sprintf(t, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0xa0: - if(regs.p.x)sprintf(t, "ldy #$%0.2x ", op0); - else sprintf(t, "ldy #$%0.4x ", op0|op1<<8);break; - case 0xa1:sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0xa2: - if(regs.p.x)sprintf(t, "ldx #$%0.2x ", op0); - else sprintf(t, "ldx #$%0.4x ", op0|op1<<8);break; - case 0xa3:sprintf(t, "lda $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0xa4:sprintf(t, "ldy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xa5:sprintf(t, "lda $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xa6:sprintf(t, "ldx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xa7:sprintf(t, "lda [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0xa8:sprintf(t, "tay ");break; - case 0xa9: - if(regs.p.m)sprintf(t, "lda #$%0.2x ", op0); - else sprintf(t, "lda #$%0.4x ", op0|op1<<8);break; - case 0xaa:sprintf(t, "tax ");break; - case 0xab:sprintf(t, "plb ");break; - case 0xac:sprintf(t, "ldy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xad:sprintf(t, "lda $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xae:sprintf(t, "ldx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xaf:sprintf(t, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0xb0:sprintf(t, "bcs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0xb1:sprintf(t, "lda ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0xb2:sprintf(t, "lda ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0xb3:sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0xb4:sprintf(t, "ldy $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xb5:sprintf(t, "lda $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xb6:sprintf(t, "ldx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break; - case 0xb7:sprintf(t, "lda [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0xb8:sprintf(t, "clv ");break; - case 0xb9:sprintf(t, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0xba:sprintf(t, "tsx ");break; - case 0xbb:sprintf(t, "tyx ");break; - case 0xbc:sprintf(t, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xbd:sprintf(t, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xbe:sprintf(t, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0xbf:sprintf(t, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0xc0: - if(regs.p.x)sprintf(t, "cpy #$%0.2x ", op0); - else sprintf(t, "cpy #$%0.4x ", op0|op1<<8);break; - case 0xc1:sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0xc2:sprintf(t, "rep #$%0.2x ", op0);break; - case 0xc3:sprintf(t, "cmp $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0xc4:sprintf(t, "cpy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xc5:sprintf(t, "cmp $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xc6:sprintf(t, "dec $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xc7:sprintf(t, "cmp [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0xc8:sprintf(t, "iny ");break; - case 0xc9: - if(regs.p.m)sprintf(t, "cmp #$%0.2x ", op0); - else sprintf(t, "cmp #$%0.4x ", op0|op1<<8);break; - case 0xca:sprintf(t, "dex ");break; - case 0xcb:sprintf(t, "wai ");break; - case 0xcc:sprintf(t, "cpy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xcd:sprintf(t, "cmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xce:sprintf(t, "dec $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xcf:sprintf(t, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0xd0:sprintf(t, "bne $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0xd1:sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0xd2:sprintf(t, "cmp ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0xd3:sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0xd4:sprintf(t, "pei ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0xd5:sprintf(t, "cmp $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xd6:sprintf(t, "dec $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xd7:sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0xd8:sprintf(t, "cld ");break; - case 0xd9:sprintf(t, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0xda:sprintf(t, "phx ");break; - case 0xdb:sprintf(t, "stp ");break; - case 0xdc:sprintf(t, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ILADDR, (op0|op1<<8)));break; - case 0xdd:sprintf(t, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xde:sprintf(t, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xdf:sprintf(t, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; - case 0xe0: - if(regs.p.x)sprintf(t, "cpx #$%0.2x ", op0); - else sprintf(t, "cpx #$%0.4x ", op0|op1<<8);break; - case 0xe1:sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break; - case 0xe2:sprintf(t, "sep #$%0.2x ", op0);break; - case 0xe3:sprintf(t, "sbc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break; - case 0xe4:sprintf(t, "cpx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xe5:sprintf(t, "sbc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xe6:sprintf(t, "inc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break; - case 0xe7:sprintf(t, "sbc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break; - case 0xe8:sprintf(t, "inx ");break; - case 0xe9: - if(regs.p.m)sprintf(t, "sbc #$%0.2x ", op0); - else sprintf(t, "sbc #$%0.4x ", op0|op1<<8);break; - case 0xea:sprintf(t, "nop ");break; - case 0xeb:sprintf(t, "xba ");break; - case 0xec:sprintf(t, "cpx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xed:sprintf(t, "sbc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xee:sprintf(t, "inc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xef:sprintf(t, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break; - case 0xf0:sprintf(t, "beq $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break; - case 0xf1:sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break; - case 0xf2:sprintf(t, "sbc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break; - case 0xf3:sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break; - case 0xf4:sprintf(t, "pea $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break; - case 0xf5:sprintf(t, "sbc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xf6:sprintf(t, "inc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break; - case 0xf7:sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break; - case 0xf8:sprintf(t, "sed ");break; - case 0xf9:sprintf(t, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break; - case 0xfa:sprintf(t, "plx ");break; - case 0xfb:sprintf(t, "xce ");break; - case 0xfc:sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break; - case 0xfd:sprintf(t, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xfe:sprintf(t, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break; - case 0xff:sprintf(t, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break; + case 0x00: sprintf(t, "brk #$%0.2x ", op8); break; + case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0x02: sprintf(t, "cop #$%0.2x ", op8); break; + case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0x08: sprintf(t, "php "); break; + case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8); + else sprintf(t, "ora #$%0.4x ", op16); break; + case 0x0a: sprintf(t, "asl a "); break; + case 0x0b: sprintf(t, "phd "); break; + case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0x18: sprintf(t, "clc "); break; + case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0x1a: sprintf(t, "inc "); break; + case 0x1b: sprintf(t, "tcs "); break; + case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break; + case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0x28: sprintf(t, "plp "); break; + case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8); + else sprintf(t, "and #$%0.4x ", op16); break; + case 0x2a: sprintf(t, "rol a "); break; + case 0x2b: sprintf(t, "pld "); break; + case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0x38: sprintf(t, "sec "); break; + case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0x3a: sprintf(t, "dec "); break; + case 0x3b: sprintf(t, "tsc "); break; + case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0x40: sprintf(t, "rti "); break; + case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0x42: sprintf(t, "wdm "); break; + case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break; + case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0x48: sprintf(t, "pha "); break; + case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8); + else sprintf(t, "eor #$%0.4x ", op16); break; + case 0x4a: sprintf(t, "lsr a "); break; + case 0x4b: sprintf(t, "phk "); break; + case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break; + case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break; + case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0x58: sprintf(t, "cli "); break; + case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0x5a: sprintf(t, "phy "); break; + case 0x5b: sprintf(t, "tcd "); break; + case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0x60: sprintf(t, "rts "); break; + case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0x68: sprintf(t, "pla "); break; + case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8); + else sprintf(t, "adc #$%0.4x ", op16); break; + case 0x6a: sprintf(t, "ror a "); break; + case 0x6b: sprintf(t, "rtl "); break; + case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break; + case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0x78: sprintf(t, "sei "); break; + case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0x7a: sprintf(t, "ply "); break; + case 0x7b: sprintf(t, "tdc "); break; + case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break; + case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break; + case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0x88: sprintf(t, "dey "); break; + case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8); + else sprintf(t, "bit #$%0.4x ", op16); break; + case 0x8a: sprintf(t, "txa "); break; + case 0x8b: sprintf(t, "phb "); break; + case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break; + case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0x98: sprintf(t, "tya "); break; + case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0x9a: sprintf(t, "txs "); break; + case 0x9b: sprintf(t, "txy "); break; + case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8); + else sprintf(t, "ldy #$%0.4x ", op16); break; + case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8); + else sprintf(t, "ldx #$%0.4x ", op16); break; + case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0xa8: sprintf(t, "tay "); break; + case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8); + else sprintf(t, "lda #$%0.4x ", op16); break; + case 0xaa: sprintf(t, "tax "); break; + case 0xab: sprintf(t, "plb "); break; + case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break; + case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0xb8: sprintf(t, "clv "); break; + case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0xba: sprintf(t, "tsx "); break; + case 0xbb: sprintf(t, "tyx "); break; + case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8); + else sprintf(t, "cpy #$%0.4x ", op16); break; + case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break; + case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0xc8: sprintf(t, "iny "); break; + case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8); + else sprintf(t, "cmp #$%0.4x ", op16); break; + case 0xca: sprintf(t, "dex "); break; + case 0xcb: sprintf(t, "wai "); break; + case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0xd8: sprintf(t, "cld "); break; + case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0xda: sprintf(t, "phx "); break; + case 0xdb: sprintf(t, "stp "); break; + case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break; + case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; + case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8); + else sprintf(t, "cpx #$%0.4x ", op16); break; + case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break; + case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break; + case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break; + case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break; + case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break; + case 0xe8: sprintf(t, "inx "); break; + case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8); + else sprintf(t, "sbc #$%0.4x ", op16); break; + case 0xea: sprintf(t, "nop "); break; + case 0xeb: sprintf(t, "xba "); break; + case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break; + case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break; + case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break; + case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break; + case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break; + case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break; + case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break; + case 0xf8: sprintf(t, "sed "); break; + case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break; + case 0xfa: sprintf(t, "plx "); break; + case 0xfb: sprintf(t, "xce "); break; + case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break; + case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; + case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break; } +#undef op8 +#undef op16 +#undef op24 +#undef a8 +#undef x8 + strcat(s, t); strcat(s, " "); sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ", regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db); strcat(s, t); + if(regs.e) { sprintf(t, "%c%c%c%c%c%c%c%c", - (regs.p.n)?'N':'n', (regs.p.v)?'V':'v', - (regs.p.m)?'1':'0', (regs.p.x)?'B':'b', - (regs.p.d)?'D':'d', (regs.p.i)?'I':'i', - (regs.p.z)?'Z':'z', (regs.p.c)?'C':'c'); + (regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v', + (regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b', + (regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i', + (regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c'); } else { sprintf(t, "%c%c%c%c%c%c%c%c", - (regs.p.n)?'N':'n', (regs.p.v)?'V':'v', - (regs.p.m)?'M':'m', (regs.p.x)?'X':'x', - (regs.p.d)?'D':'d', (regs.p.i)?'I':'i', - (regs.p.z)?'Z':'z', (regs.p.c)?'C':'c'); + (regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v', + (regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x', + (regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i', + (regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c'); } + strcat(s, t); } -/* - opcode_length() retrieves the length of the next opcode - to be executed. It is used by the debugger to step over, - disable, and proceed cpu opcodes. - - 5 and 6 are special cases, 5 is used for #consts based on - the A register size, 6 for the X/Y register size. the - rest are literal sizes. There's no need to test for - emulation mode, as regs.p.m/regs.p.x should *always* be - set in emulation mode. -*/ +/***** + * opcode_length() retrieves the length of the next opcode + * to be executed. It is used by the debugger to step over, + * disable and proceed cpu opcodes. + * + * 5 and 6 are special cases, 5 is used for #consts based on + * the A register size, 6 for the X/Y register size. the + * rest are literal sizes. There's no need to test for + * emulation mode, as regs.p.m/regs.p.x should *always* be + * set in emulation mode. + *****/ uint8 CPU::opcode_length() { uint8 op, len; static uint8 op_len_tbl[256] = { //0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f + 2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n 2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n 3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n @@ -457,9 +463,9 @@ static uint8 op_len_tbl[256] = { return 0; } - op = r_mem->read(regs.pc.d); + op = dreadb(regs.pc.d); len = op_len_tbl[op]; - if(len == 5)return (regs.p.m)?2:3; - if(len == 6)return (regs.p.x)?2:3; + if(len == 5)return (regs.e || regs.p.m) ? 2 : 3; + if(len == 6)return (regs.e || regs.p.x) ? 2 : 3; return len; } diff --git a/src/cpu/scpu/core/cc.bat b/src/cpu/scpu/core/cc.bat new file mode 100644 index 00000000..de7d9674 --- /dev/null +++ b/src/cpu/scpu/core/cc.bat @@ -0,0 +1,3 @@ +cl /O2 scpugen.cpp +@pause +@del *.obj \ No newline at end of file diff --git a/src/cpu/scpu/core/clean.bat b/src/cpu/scpu/core/clean.bat new file mode 100644 index 00000000..d807f14d --- /dev/null +++ b/src/cpu/scpu/core/clean.bat @@ -0,0 +1 @@ +@del *.exe diff --git a/src/cpu/scpu/core/core.cpp b/src/cpu/scpu/core/core.cpp new file mode 100644 index 00000000..7e5c059f --- /dev/null +++ b/src/cpu/scpu/core/core.cpp @@ -0,0 +1,71 @@ +#include "opfn.cpp" +//#include "op_read.cpp" +//#include "op_write.cpp" +//#include "op_rmw.cpp" +//#include "op_pc.cpp" +//#include "op_misc.cpp" + +void sCPU::main() { + for(;;) { + status.in_opcode = true; + + if(event.irq) { + event.irq = false; + if(status.nmi_pending == true) { + status.nmi_pending = false; + event.irq_vector = (regs.e == false) ? 0xffea : 0xfffa; + } else if(status.irq_pending == true) { + status.irq_pending = false; + event.irq_vector = (regs.e == false) ? 0xffee : 0xfffe; + } + op_irq(); + } + +// (this->*optbl[op_readpc()])(); + switch(op_readpc()) { + #include "op_read.cpp" + #include "op_write.cpp" + #include "op_rmw.cpp" + #include "op_pc.cpp" + #include "op_misc.cpp" + } + + status.in_opcode = false; + opcode_edge(); + } +} + +void sCPU::op_irq() { + op_read(regs.pc.d); + op_io(); + if(!regs.e)op_writestack(regs.pc.b); + op_writestack(regs.pc.h); + op_writestack(regs.pc.l); + op_writestack(regs.e ? (regs.p & ~0x10) : regs.p); + rd.l = op_read(event.irq_vector + 0); + regs.pc.b = 0x00; + regs.p.i = 1; + regs.p.d = 0; + rd.h = op_read(event.irq_vector + 1); + regs.pc.w = rd.w; + +#ifdef DEBUGGER + status.in_opcode = false; + snes->notify(SNES::CPU_EXEC_OPCODE_END); + status.in_opcode = true; +#endif +} + +// + +void sCPU::op_io_cond2() { + if(regs.d.l != 0x00)op_io(); +} + +void sCPU::op_io_cond4(uint16 x, uint16 y) { + if(!regs.p.x && (x & 0xff00) != (y & 0xff00))op_io(); +} + +void sCPU::op_io_cond6(uint16 addr) { + if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00))op_io(); +} diff --git a/src/cpu/scpu/core/core.h b/src/cpu/scpu/core/core.h new file mode 100644 index 00000000..cf2ff9e0 --- /dev/null +++ b/src/cpu/scpu/core/core.h @@ -0,0 +1,58 @@ +//void (sCPU::*optbl[256])(); + +CPUReg24 aa, rd; +uint8 dp, sp; + + inline void main(); + inline void op_irq(); + + bool in_opcode() { return status.in_opcode; } + +//op_read + void op_adc_b(); + void op_adc_w(); + void op_and_b(); + void op_and_w(); + void op_bit_b(); + void op_bit_w(); + void op_cmp_b(); + void op_cmp_w(); + void op_cpx_b(); + void op_cpx_w(); + void op_cpy_b(); + void op_cpy_w(); + void op_eor_b(); + void op_eor_w(); + void op_lda_b(); + void op_lda_w(); + void op_ldx_b(); + void op_ldx_w(); + void op_ldy_b(); + void op_ldy_w(); + void op_ora_b(); + void op_ora_w(); + void op_sbc_b(); + void op_sbc_w(); +//op_rmw + void op_inc_b(); + void op_inc_w(); + void op_dec_b(); + void op_dec_w(); + void op_asl_b(); + void op_asl_w(); + void op_lsr_b(); + void op_lsr_w(); + void op_rol_b(); + void op_rol_w(); + void op_ror_b(); + void op_ror_w(); + void op_trb_b(); + void op_trb_w(); + void op_tsb_b(); + void op_tsb_w(); + + void op_io_cond2(); + void op_io_cond4(uint16 x, uint16 y); + void op_io_cond6(uint16 addr); + +//#include "op.h" diff --git a/src/cpu/scpu/core/op_misc.b b/src/cpu/scpu/core/op_misc.b new file mode 100644 index 00000000..19d12f31 --- /dev/null +++ b/src/cpu/scpu/core/op_misc.b @@ -0,0 +1,276 @@ +nop(0xea) { +1:last_cycle(); + op_io(); +} + +wdm(0x42) { +1:last_cycle(); + op_readpc(); +} + +xba(0xeb) { +1:op_io(); +2:last_cycle(); + op_io(); + regs.a.l ^= regs.a.h; + regs.a.h ^= regs.a.l; + regs.a.l ^= regs.a.h; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +mvn(0x54, ++), +mvp(0x44, --) { +1:dp = op_readpc(); +2:sp = op_readpc(); +3:regs.db = dp; + rd.l = op_readlong((sp << 16) | regs.x.w); +4:op_writelong((dp << 16) | regs.y.w, rd.l); +5:op_io(); + if(regs.p.x) { regs.x.l$1; regs.y.l$1; } + else { regs.x.w$1; regs.y.w$1; } +6:last_cycle(); + op_io(); + if(regs.a.w--)regs.pc.w -= 3; +} + +brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7), +cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) { +1:op_readpc(); +2:if(!regs.e)op_writestack(regs.pc.b); +3:op_writestack(regs.pc.h); +4:op_writestack(regs.pc.l); +5:op_writestack(regs.p); +6:rd.l = op_readlong((regs.e) ? $1 : $3); + regs.pc.b = 0x00; + regs.p.i = 1; + regs.p.d = 0; +7:last_cycle(); + rd.h = op_readlong((regs.e) ? $2 : $4); + regs.pc.w = rd.w; +} + +stp(0xdb) { +1:op_io(); +2:last_cycle(); + while(1) { + op_io(); + co_return(); + } +} + +wai(0xcb) { +1:op_io(); + event.wai = true; +2:last_cycle(); + op_io(); +3:while(event.wai) { + last_cycle(); + op_io(); + co_return(); + } +} + +xce(0xfb) { +1:last_cycle(); + op_io(); +bool c = regs.p.c; + regs.p.c = regs.e; + regs.e = c; + if(regs.e) { + regs.p |= 0x30; + regs.x.h = 0x00; + regs.y.h = 0x00; + regs.s.h = 0x01; + } +} + +clc(0x18, regs.p.c = 0), +cld(0xd8, regs.p.d = 0), +cli(0x58, regs.p.i = 0), +clv(0xb8, regs.p.v = 0), +sec(0x38, regs.p.c = 1), +sed(0xf8, regs.p.d = 1), +sei(0x78, regs.p.i = 1) { +1:last_cycle(); + op_io(); + $1; +} + +rep(0xc2, &=~), +sep(0xe2, |=) { +1:rd.l = op_readpc(); +2:last_cycle(); + op_io(); + regs.p $1 rd.l; + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +} + +tax(0xaa, regs.p.x, x, a), +tay(0xa8, regs.p.x, y, a), +txa(0x8a, regs.p.m, a, x), +txy(0x9b, regs.p.x, y, x), +tya(0x98, regs.p.m, a, y), +tyx(0xbb, regs.p.x, x, y) { +1:last_cycle(); + op_io(); + if($1) { + regs.$2.l = regs.$3.l; + regs.p.n = !!(regs.$2.l & 0x80); + regs.p.z = (regs.$2.l == 0); + } else { + regs.$2.w = regs.$3.w; + regs.p.n = !!(regs.$2.w & 0x8000); + regs.p.z = (regs.$2.w == 0); + } +} + +tcd(0x5b) { +1:last_cycle(); + op_io(); + regs.d.w = regs.a.w; + regs.p.n = !!(regs.d.w & 0x8000); + regs.p.z = (regs.d.w == 0); +} + +tcs(0x1b) { +1:last_cycle(); + op_io(); + regs.s.w = regs.a.w; + if(regs.e)regs.s.h = 0x01; +} + +tdc(0x7b) { +1:last_cycle(); + op_io(); + regs.a.w = regs.d.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +tsc(0x3b) { +1:last_cycle(); + op_io(); + regs.a.w = regs.s.w; + if(regs.e) { + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +tsx(0xba) { +1:last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l = regs.s.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.s.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} + +txs(0x9a) { +1:last_cycle(); + op_io(); + if(regs.e) { + regs.s.l = regs.x.l; + } else { + regs.s.w = regs.x.w; + } +} + +pha(0x48, regs.p.m, a), +phx(0xda, regs.p.x, x), +phy(0x5a, regs.p.x, y), +phd(0x0b, 0, d) { +1:op_io(); +2:if(!$1)op_writestack(regs.$2.h); +3:last_cycle(); + op_writestack(regs.$2.l); +} + +phb(0x8b, regs.db), +phk(0x4b, regs.pc.b), +php(0x08, regs.p) { +1:op_io(); +2:last_cycle(); + op_writestack($1); +} + +pla(0x68, regs.p.m, a), +plx(0xfa, regs.p.x, x), +ply(0x7a, regs.p.x, y), +pld(0x2b, 0, d) { +1:op_io(); +2:op_io(); +3:if($1)last_cycle(); + regs.$2.l = op_readstack(); + if($1) { + regs.p.n = !!(regs.$2.l & 0x80); + regs.p.z = (regs.$2.l == 0); + end; + } +4:last_cycle(); + regs.$2.h = op_readstack(); + regs.p.n = !!(regs.$2.w & 0x8000); + regs.p.z = (regs.$2.w == 0); +} + +plb(0xab) { +1:op_io(); +2:op_io(); +3:last_cycle(); + regs.db = op_readstack(); + regs.p.n = !!(regs.db & 0x80); + regs.p.z = (regs.db == 0); +} + +plp(0x28) { +1:op_io(); +2:op_io(); +3:last_cycle(); + regs.p = op_readstack(); + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +} + +pea(0xf4) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_writestack(aa.h); +4:last_cycle(); + op_writestack(aa.l); +} + +pei(0xd4) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:op_writestack(aa.h); +6:last_cycle(); + op_writestack(aa.l); +} + +per(0x62) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io(); + rd.w = regs.pc.d + (int16)aa.w; +4:op_writestack(rd.h); +5:last_cycle(); + op_writestack(rd.l); +} diff --git a/src/cpu/scpu/core/op_misc.cpp b/src/cpu/scpu/core/op_misc.cpp new file mode 100644 index 00000000..632e2b21 --- /dev/null +++ b/src/cpu/scpu/core/op_misc.cpp @@ -0,0 +1,530 @@ +//nop +case 0xea: { + last_cycle(); + op_io(); +} break; + +//wdm +case 0x42: { + last_cycle(); + op_readpc(); +} break; + +//xba +case 0xeb: { + op_io(); + last_cycle(); + op_io(); + regs.a.l ^= regs.a.h; + regs.a.h ^= regs.a.l; + regs.a.l ^= regs.a.h; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} break; + +//mvn +case 0x54: { + dp = op_readpc(); + sp = op_readpc(); + regs.db = dp; + rd.l = op_readlong((sp << 16) | regs.x.w); + op_writelong((dp << 16) | regs.y.w, rd.l); + op_io(); + if(regs.p.x) { regs.x.l++; regs.y.l++; } + else { regs.x.w++; regs.y.w++; } + last_cycle(); + op_io(); + if(regs.a.w--)regs.pc.w -= 3; +} break; + +//mvp +case 0x44: { + dp = op_readpc(); + sp = op_readpc(); + regs.db = dp; + rd.l = op_readlong((sp << 16) | regs.x.w); + op_writelong((dp << 16) | regs.y.w, rd.l); + op_io(); + if(regs.p.x) { regs.x.l--; regs.y.l--; } + else { regs.x.w--; regs.y.w--; } + last_cycle(); + op_io(); + if(regs.a.w--)regs.pc.w -= 3; +} break; + +//brk +case 0x00: { + op_readpc(); + if(!regs.e)op_writestack(regs.pc.b); + op_writestack(regs.pc.h); + op_writestack(regs.pc.l); + op_writestack(regs.p); + rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6); + regs.pc.b = 0x00; + regs.p.i = 1; + regs.p.d = 0; + last_cycle(); + rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7); + regs.pc.w = rd.w; +} break; + +//cop +case 0x02: { + op_readpc(); + if(!regs.e)op_writestack(regs.pc.b); + op_writestack(regs.pc.h); + op_writestack(regs.pc.l); + op_writestack(regs.p); + rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4); + regs.pc.b = 0x00; + regs.p.i = 1; + regs.p.d = 0; + last_cycle(); + rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5); + regs.pc.w = rd.w; +} break; + +//stp +case 0xdb: { + op_io(); + last_cycle(); + while(1) { + op_io(); + co_return(); + } +} break; + +//wai +case 0xcb: { + op_io(); + event.wai = true; + last_cycle(); + op_io(); + while(event.wai) { + last_cycle(); + op_io(); + co_return(); + } +} break; + +//xce +case 0xfb: { + last_cycle(); + op_io(); +bool c = regs.p.c; + regs.p.c = regs.e; + regs.e = c; + if(regs.e) { + regs.p |= 0x30; + regs.x.h = 0x00; + regs.y.h = 0x00; + regs.s.h = 0x01; + } +} break; + +//clc +case 0x18: { + last_cycle(); + op_io(); + regs.p.c = 0; +} break; + +//cld +case 0xd8: { + last_cycle(); + op_io(); + regs.p.d = 0; +} break; + +//cli +case 0x58: { + last_cycle(); + op_io(); + regs.p.i = 0; +} break; + +//clv +case 0xb8: { + last_cycle(); + op_io(); + regs.p.v = 0; +} break; + +//sec +case 0x38: { + last_cycle(); + op_io(); + regs.p.c = 1; +} break; + +//sed +case 0xf8: { + last_cycle(); + op_io(); + regs.p.d = 1; +} break; + +//sei +case 0x78: { + last_cycle(); + op_io(); + regs.p.i = 1; +} break; + +//rep +case 0xc2: { + rd.l = op_readpc(); + last_cycle(); + op_io(); + regs.p &=~ rd.l; + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +} break; + +//sep +case 0xe2: { + rd.l = op_readpc(); + last_cycle(); + op_io(); + regs.p |= rd.l; + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +} break; + +//tax +case 0xaa: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l = regs.a.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.a.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} break; + +//tay +case 0xa8: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.y.l = regs.a.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w = regs.a.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} break; + +//txa +case 0x8a: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.a.l = regs.x.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w = regs.x.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//txy +case 0x9b: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.y.l = regs.x.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w = regs.x.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} break; + +//tya +case 0x98: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.a.l = regs.y.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w = regs.y.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//tyx +case 0xbb: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l = regs.y.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.y.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} break; + +//tcd +case 0x5b: { + last_cycle(); + op_io(); + regs.d.w = regs.a.w; + regs.p.n = !!(regs.d.w & 0x8000); + regs.p.z = (regs.d.w == 0); +} break; + +//tcs +case 0x1b: { + last_cycle(); + op_io(); + regs.s.w = regs.a.w; + if(regs.e)regs.s.h = 0x01; +} break; + +//tdc +case 0x7b: { + last_cycle(); + op_io(); + regs.a.w = regs.d.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} break; + +//tsc +case 0x3b: { + last_cycle(); + op_io(); + regs.a.w = regs.s.w; + if(regs.e) { + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//tsx +case 0xba: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l = regs.s.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w = regs.s.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} break; + +//txs +case 0x9a: { + last_cycle(); + op_io(); + if(regs.e) { + regs.s.l = regs.x.l; + } else { + regs.s.w = regs.x.w; + } +} break; + +//pha +case 0x48: { + op_io(); + if(!regs.p.m)op_writestack(regs.a.h); + last_cycle(); + op_writestack(regs.a.l); +} break; + +//phx +case 0xda: { + op_io(); + if(!regs.p.x)op_writestack(regs.x.h); + last_cycle(); + op_writestack(regs.x.l); +} break; + +//phy +case 0x5a: { + op_io(); + if(!regs.p.x)op_writestack(regs.y.h); + last_cycle(); + op_writestack(regs.y.l); +} break; + +//phd +case 0x0b: { + op_io(); + if(!0)op_writestack(regs. d.h); + last_cycle(); + op_writestack(regs. d.l); +} break; + +//phb +case 0x8b: { + op_io(); + last_cycle(); + op_writestack(regs.db); +} break; + +//phk +case 0x4b: { + op_io(); + last_cycle(); + op_writestack(regs.pc.b); +} break; + +//php +case 0x08: { + op_io(); + last_cycle(); + op_writestack(regs.p); +} break; + +//pla +case 0x68: { + op_io(); + op_io(); + if(regs.p.m)last_cycle(); + regs.a.l = op_readstack(); + if(regs.p.m) { + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + break; + } + last_cycle(); + regs.a.h = op_readstack(); + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} break; + +//plx +case 0xfa: { + op_io(); + op_io(); + if(regs.p.x)last_cycle(); + regs.x.l = op_readstack(); + if(regs.p.x) { + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + break; + } + last_cycle(); + regs.x.h = op_readstack(); + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); +} break; + +//ply +case 0x7a: { + op_io(); + op_io(); + if(regs.p.x)last_cycle(); + regs.y.l = op_readstack(); + if(regs.p.x) { + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + break; + } + last_cycle(); + regs.y.h = op_readstack(); + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); +} break; + +//pld +case 0x2b: { + op_io(); + op_io(); + if(0)last_cycle(); + regs. d.l = op_readstack(); + if(0) { + regs.p.n = !!(regs. d.l & 0x80); + regs.p.z = (regs. d.l == 0); + break; + } + last_cycle(); + regs. d.h = op_readstack(); + regs.p.n = !!(regs. d.w & 0x8000); + regs.p.z = (regs. d.w == 0); +} break; + +//plb +case 0xab: { + op_io(); + op_io(); + last_cycle(); + regs.db = op_readstack(); + regs.p.n = !!(regs.db & 0x80); + regs.p.z = (regs.db == 0); +} break; + +//plp +case 0x28: { + op_io(); + op_io(); + last_cycle(); + regs.p = op_readstack(); + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +} break; + +//pea +case 0xf4: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_writestack(aa.h); + last_cycle(); + op_writestack(aa.l); +} break; + +//pei +case 0xd4: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_writestack(aa.h); + last_cycle(); + op_writestack(aa.l); +} break; + +//per +case 0x62: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.w = regs.pc.d + (int16)aa.w; + op_writestack(rd.h); + last_cycle(); + op_writestack(rd.l); +} break; + diff --git a/src/cpu/scpu/core/op_pc.b b/src/cpu/scpu/core/op_pc.b new file mode 100644 index 00000000..7b126675 --- /dev/null +++ b/src/cpu/scpu/core/op_pc.b @@ -0,0 +1,160 @@ +bcc(0x90, !regs.p.c), +bcs(0xb0, regs.p.c), +bne(0xd0, !regs.p.z), +beq(0xf0, regs.p.z), +bpl(0x10, !regs.p.n), +bmi(0x30, regs.p.n), +bvc(0x50, !regs.p.v), +bvs(0x70, regs.p.v) { +1:if(!$1)last_cycle(); + rd.l = op_readpc(); + if($1) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + end; + } +2:op_io_cond6(aa.w); +3:last_cycle(); + op_io(); +} + +bra(0x80) { +1:rd.l = op_readpc(); + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; +2:op_io_cond6(aa.w); +3:last_cycle(); + op_io(); +} + +brl(0x82) { +1:rd.l = op_readpc(); +2:rd.h = op_readpc(); +3:last_cycle(); + op_io(); + regs.pc.w = regs.pc.d + (int16)rd.w; +} + +jmp_addr(0x4c) { +1:rd.l = op_readpc(); +2:last_cycle(); + rd.h = op_readpc(); + regs.pc.w = rd.w; +} + +jmp_long(0x5c) { +1:rd.l = op_readpc(); +2:rd.h = op_readpc(); +3:last_cycle(); + rd.b = op_readpc(); + regs.pc.d = rd.d & 0xffffff; +} + +jmp_iaddr(0x6c) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:rd.l = op_readaddr(aa.w); +4:last_cycle(); + rd.h = op_readaddr(aa.w + 1); + regs.pc.w = rd.w; +} + +jmp_iaddrx(0x7c) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io(); +4:rd.l = op_readpbr(aa.w + regs.x.w); +5:last_cycle(); + rd.h = op_readpbr(aa.w + regs.x.w + 1); + regs.pc.w = rd.w; +} + +jmp_iladdr(0xdc) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:rd.l = op_readaddr(aa.w); +4:rd.h = op_readaddr(aa.w + 1); +5:last_cycle(); + rd.b = op_readaddr(aa.w + 2); + regs.pc.d = rd.d & 0xffffff; +} + +jsr_addr(0x20) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io(); +4:regs.pc.w--; + op_writestack(regs.pc.h); +5:last_cycle(); + op_writestack(regs.pc.l); + regs.pc.w = aa.w; +} + +jsr_long(0x22) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_writestack(regs.pc.b); +4:op_io(); +5:aa.b = op_readpc(); +6:regs.pc.w--; + op_writestack(regs.pc.h); +7:last_cycle(); + op_writestack(regs.pc.l); + regs.pc.d = aa.d & 0xffffff; +} + +jsr_iaddrx(0xfc) { +1:aa.l = op_readpc(); +2:op_writestack(regs.pc.h); +3:op_writestack(regs.pc.l); +4:aa.h = op_readpc(); +5:op_io(); +6:rd.l = op_readpbr(aa.w + regs.x.w); +7:last_cycle(); + rd.h = op_readpbr(aa.w + regs.x.w + 1); + regs.pc.w = rd.w; +} + +rti(0x40) { +1:op_io(); +2:op_io(); +3:regs.p = op_readstack(); + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } +4:rd.l = op_readstack(); +5:if(regs.e)last_cycle(); + rd.h = op_readstack(); + if(regs.e) { + regs.pc.w = rd.w; + end; + } +6:last_cycle(); + rd.b = op_readstack(); + regs.pc.d = rd.d & 0xffffff; +} + +rts(0x60) { +1:op_io(); +2:op_io(); +3:rd.l = op_readstack(); +4:rd.h = op_readstack(); +5:last_cycle(); + op_io(); + regs.pc.w = rd.w; + regs.pc.w++; +} + +rtl(0x6b) { +1:op_io(); +2:op_io(); +3:rd.l = op_readstack(); +4:rd.h = op_readstack(); +5:last_cycle(); + rd.b = op_readstack(); + regs.pc.d = rd.d & 0xffffff; + regs.pc.w++; +} diff --git a/src/cpu/scpu/core/op_pc.cpp b/src/cpu/scpu/core/op_pc.cpp new file mode 100644 index 00000000..14a4c74e --- /dev/null +++ b/src/cpu/scpu/core/op_pc.cpp @@ -0,0 +1,273 @@ +//bcc +case 0x90: { + if(!!regs.p.c)last_cycle(); + rd.l = op_readpc(); + if(!regs.p.c) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bcs +case 0xb0: { + if(!regs.p.c)last_cycle(); + rd.l = op_readpc(); + if(regs.p.c) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bne +case 0xd0: { + if(!!regs.p.z)last_cycle(); + rd.l = op_readpc(); + if(!regs.p.z) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//beq +case 0xf0: { + if(!regs.p.z)last_cycle(); + rd.l = op_readpc(); + if(regs.p.z) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bpl +case 0x10: { + if(!!regs.p.n)last_cycle(); + rd.l = op_readpc(); + if(!regs.p.n) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bmi +case 0x30: { + if(!regs.p.n)last_cycle(); + rd.l = op_readpc(); + if(regs.p.n) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bvc +case 0x50: { + if(!!regs.p.v)last_cycle(); + rd.l = op_readpc(); + if(!regs.p.v) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bvs +case 0x70: { + if(!regs.p.v)last_cycle(); + rd.l = op_readpc(); + if(regs.p.v) { + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + } else { + break; + } + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//bra +case 0x80: { + rd.l = op_readpc(); + aa.w = regs.pc.d + (int8)rd.l; + regs.pc.w = aa.w; + op_io_cond6(aa.w); + last_cycle(); + op_io(); +} break; + +//brl +case 0x82: { + rd.l = op_readpc(); + rd.h = op_readpc(); + last_cycle(); + op_io(); + regs.pc.w = regs.pc.d + (int16)rd.w; +} break; + +//jmp_addr +case 0x4c: { + rd.l = op_readpc(); + last_cycle(); + rd.h = op_readpc(); + regs.pc.w = rd.w; +} break; + +//jmp_long +case 0x5c: { + rd.l = op_readpc(); + rd.h = op_readpc(); + last_cycle(); + rd.b = op_readpc(); + regs.pc.d = rd.d & 0xffffff; +} break; + +//jmp_iaddr +case 0x6c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readaddr(aa.w); + last_cycle(); + rd.h = op_readaddr(aa.w + 1); + regs.pc.w = rd.w; +} break; + +//jmp_iaddrx +case 0x7c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readpbr(aa.w + regs.x.w); + last_cycle(); + rd.h = op_readpbr(aa.w + regs.x.w + 1); + regs.pc.w = rd.w; +} break; + +//jmp_iladdr +case 0xdc: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readaddr(aa.w); + rd.h = op_readaddr(aa.w + 1); + last_cycle(); + rd.b = op_readaddr(aa.w + 2); + regs.pc.d = rd.d & 0xffffff; +} break; + +//jsr_addr +case 0x20: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + regs.pc.w--; + op_writestack(regs.pc.h); + last_cycle(); + op_writestack(regs.pc.l); + regs.pc.w = aa.w; +} break; + +//jsr_long +case 0x22: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_writestack(regs.pc.b); + op_io(); + aa.b = op_readpc(); + regs.pc.w--; + op_writestack(regs.pc.h); + last_cycle(); + op_writestack(regs.pc.l); + regs.pc.d = aa.d & 0xffffff; +} break; + +//jsr_iaddrx +case 0xfc: { + aa.l = op_readpc(); + op_writestack(regs.pc.h); + op_writestack(regs.pc.l); + aa.h = op_readpc(); + op_io(); + rd.l = op_readpbr(aa.w + regs.x.w); + last_cycle(); + rd.h = op_readpbr(aa.w + regs.x.w + 1); + regs.pc.w = rd.w; +} break; + +//rti +case 0x40: { + op_io(); + op_io(); + regs.p = op_readstack(); + if(regs.e)regs.p |= 0x30; + if(regs.p.x) { + regs.x.h = 0x00; + regs.y.h = 0x00; + } + rd.l = op_readstack(); + if(regs.e)last_cycle(); + rd.h = op_readstack(); + if(regs.e) { + regs.pc.w = rd.w; + break; + } + last_cycle(); + rd.b = op_readstack(); + regs.pc.d = rd.d & 0xffffff; +} break; + +//rts +case 0x60: { + op_io(); + op_io(); + rd.l = op_readstack(); + rd.h = op_readstack(); + last_cycle(); + op_io(); + regs.pc.w = rd.w; + regs.pc.w++; +} break; + +//rtl +case 0x6b: { + op_io(); + op_io(); + rd.l = op_readstack(); + rd.h = op_readstack(); + last_cycle(); + rd.b = op_readstack(); + regs.pc.d = rd.d & 0xffffff; + regs.pc.w++; +} break; + diff --git a/src/cpu/scpu/core/op_read.b b/src/cpu/scpu/core/op_read.b new file mode 100644 index 00000000..1b3d986f --- /dev/null +++ b/src/cpu/scpu/core/op_read.b @@ -0,0 +1,317 @@ +adc_const(0x69, adc, regs.p.m), +and_const(0x29, and, regs.p.m), +cmp_const(0xc9, cmp, regs.p.m), +cpx_const(0xe0, cpx, regs.p.x), +cpy_const(0xc0, cpy, regs.p.x), +eor_const(0x49, eor, regs.p.m), +lda_const(0xa9, lda, regs.p.m), +ldx_const(0xa2, ldx, regs.p.x), +ldy_const(0xa0, ldy, regs.p.x), +ora_const(0x09, ora, regs.p.m), +sbc_const(0xe9, sbc, regs.p.m) { +1:if($2)last_cycle(); + rd.l = op_readpc(); + if($2) { op_$1_b(); end; } +2:last_cycle(); + rd.h = op_readpc(); + op_$1_w(); +} + +adc_addr(0x6d, adc, regs.p.m), +and_addr(0x2d, and, regs.p.m), +bit_addr(0x2c, bit, regs.p.m), +cmp_addr(0xcd, cmp, regs.p.m), +cpx_addr(0xec, cpx, regs.p.x), +cpy_addr(0xcc, cpy, regs.p.x), +eor_addr(0x4d, eor, regs.p.m), +lda_addr(0xad, lda, regs.p.m), +ldx_addr(0xae, ldx, regs.p.x), +ldy_addr(0xac, ldy, regs.p.x), +ora_addr(0x0d, ora, regs.p.m), +sbc_addr(0xed, sbc, regs.p.m) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:if($2)last_cycle(); + rd.l = op_readdbr(aa.w); + if($2) { op_$1_b(); end; } +4:last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_$1_w(); +} + +adc_addrx(0x7d, adc, regs.p.m), +and_addrx(0x3d, and, regs.p.m), +bit_addrx(0x3c, bit, regs.p.m), +cmp_addrx(0xdd, cmp, regs.p.m), +eor_addrx(0x5d, eor, regs.p.m), +lda_addrx(0xbd, lda, regs.p.m), +ldy_addrx(0xbc, ldy, regs.p.x), +ora_addrx(0x1d, ora, regs.p.m), +sbc_addrx(0xfd, sbc, regs.p.m) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io_cond4(aa.w, aa.w + regs.x.w); +4:if($2)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_$1_w(); +} + +adc_addry(0x79, adc, regs.p.m), +and_addry(0x39, and, regs.p.m), +cmp_addry(0xd9, cmp, regs.p.m), +eor_addry(0x59, eor, regs.p.m), +lda_addry(0xb9, lda, regs.p.m), +ldx_addry(0xbe, ldx, regs.p.x), +ora_addry(0x19, ora, regs.p.m), +sbc_addry(0xf9, sbc, regs.p.m) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io_cond4(aa.w, aa.w + regs.y.w); +4:if($2)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_$1_w(); +} + +adc_long(0x6f, adc, regs.p.m), +and_long(0x2f, and, regs.p.m), +cmp_long(0xcf, cmp, regs.p.m), +eor_long(0x4f, eor, regs.p.m), +lda_long(0xaf, lda, regs.p.m), +ora_long(0x0f, ora, regs.p.m), +sbc_long(0xef, sbc, regs.p.m) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:aa.b = op_readpc(); +4:if($2)last_cycle(); + rd.l = op_readlong(aa.d); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_$1_w(); +} + +adc_longx(0x7f, adc, regs.p.m), +and_longx(0x3f, and, regs.p.m), +cmp_longx(0xdf, cmp, regs.p.m), +eor_longx(0x5f, eor, regs.p.m), +lda_longx(0xbf, lda, regs.p.m), +ora_longx(0x1f, ora, regs.p.m), +sbc_longx(0xff, sbc, regs.p.m) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:aa.b = op_readpc(); +4:if($2)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_$1_w(); +} + +adc_dp(0x65, adc, regs.p.m), +and_dp(0x25, and, regs.p.m), +bit_dp(0x24, bit, regs.p.m), +cmp_dp(0xc5, cmp, regs.p.m), +cpx_dp(0xe4, cpx, regs.p.x), +cpy_dp(0xc4, cpy, regs.p.x), +eor_dp(0x45, eor, regs.p.m), +lda_dp(0xa5, lda, regs.p.m), +ldx_dp(0xa6, ldx, regs.p.x), +ldy_dp(0xa4, ldy, regs.p.x), +ora_dp(0x05, ora, regs.p.m), +sbc_dp(0xe5, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:if($2)last_cycle(); + rd.l = op_readdp(dp); + if($2) { op_$1_b(); end; } +4:last_cycle(); + rd.h = op_readdp(dp + 1); + op_$1_w(); +} + +adc_dpx(0x75, adc, regs.p.m), +and_dpx(0x35, and, regs.p.m), +bit_dpx(0x34, bit, regs.p.m), +cmp_dpx(0xd5, cmp, regs.p.m), +eor_dpx(0x55, eor, regs.p.m), +lda_dpx(0xb5, lda, regs.p.m), +ldy_dpx(0xb4, ldy, regs.p.x), +ora_dpx(0x15, ora, regs.p.m), +sbc_dpx(0xf5, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:if($2)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_$1_w(); +} + +ldx_dpy(0xb6, ldx, regs.p.x) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:if($2)last_cycle(); + rd.l = op_readdp(dp + regs.y.w); + if($2) { op_$1_b(); end; } +5:last_cycle(); + rd.h = op_readdp(dp + regs.y.w + 1); + op_$1_w(); +} + +adc_idp(0x72, adc, regs.p.m), +and_idp(0x32, and, regs.p.m), +cmp_idp(0xd2, cmp, regs.p.m), +eor_idp(0x52, eor, regs.p.m), +lda_idp(0xb2, lda, regs.p.m), +ora_idp(0x12, ora, regs.p.m), +sbc_idp(0xf2, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:if($2)last_cycle(); + rd.l = op_readdbr(aa.w); + if($2) { op_$1_b(); end; } +6:last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_$1_w(); +} + +adc_idpx(0x61, adc, regs.p.m), +and_idpx(0x21, and, regs.p.m), +cmp_idpx(0xc1, cmp, regs.p.m), +eor_idpx(0x41, eor, regs.p.m), +lda_idpx(0xa1, lda, regs.p.m), +ora_idpx(0x01, ora, regs.p.m), +sbc_idpx(0xe1, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:aa.l = op_readdp(dp + regs.x.w); +5:aa.h = op_readdp(dp + regs.x.w + 1); +6:if($2)last_cycle(); + rd.l = op_readdbr(aa.w); + if($2) { op_$1_b(); end; } +7:last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_$1_w(); +} + +adc_idpy(0x71, adc, regs.p.m), +and_idpy(0x31, and, regs.p.m), +cmp_idpy(0xd1, cmp, regs.p.m), +eor_idpy(0x51, eor, regs.p.m), +lda_idpy(0xb1, lda, regs.p.m), +ora_idpy(0x11, ora, regs.p.m), +sbc_idpy(0xf1, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:op_io_cond4(aa.w, aa.w + regs.y.w); +6:if($2)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if($2) { op_$1_b(); end; } +7:last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_$1_w(); +} + +adc_ildp(0x67, adc, regs.p.m), +and_ildp(0x27, and, regs.p.m), +cmp_ildp(0xc7, cmp, regs.p.m), +eor_ildp(0x47, eor, regs.p.m), +lda_ildp(0xa7, lda, regs.p.m), +ora_ildp(0x07, ora, regs.p.m), +sbc_ildp(0xe7, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:aa.b = op_readdp(dp + 2); +6:if($2)last_cycle(); + rd.l = op_readlong(aa.d); + if($2) { op_$1_b(); end; } +7:last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_$1_w(); +} + +adc_ildpy(0x77, adc, regs.p.m), +and_ildpy(0x37, and, regs.p.m), +cmp_ildpy(0xd7, cmp, regs.p.m), +eor_ildpy(0x57, eor, regs.p.m), +lda_ildpy(0xb7, lda, regs.p.m), +ora_ildpy(0x17, ora, regs.p.m), +sbc_ildpy(0xf7, sbc, regs.p.m) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:aa.b = op_readdp(dp + 2); +6:if($2)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if($2) { op_$1_b(); end; } +7:last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_$1_w(); +} + +adc_sr(0x63, adc, regs.p.m), +and_sr(0x23, and, regs.p.m), +cmp_sr(0xc3, cmp, regs.p.m), +eor_sr(0x43, eor, regs.p.m), +lda_sr(0xa3, lda, regs.p.m), +ora_sr(0x03, ora, regs.p.m), +sbc_sr(0xe3, sbc, regs.p.m) { +1:sp = op_readpc(); +2:op_io(); +3:if($2)last_cycle(); + rd.l = op_readsp(sp); + if($2) { op_$1_b(); end; } +4:last_cycle(); + rd.h = op_readsp(sp + 1); + op_$1_w(); +} + +adc_isry(0x73, adc), +and_isry(0x33, and), +cmp_isry(0xd3, cmp), +eor_isry(0x53, eor), +lda_isry(0xb3, lda), +ora_isry(0x13, ora), +sbc_isry(0xf3, sbc) { +1:sp = op_readpc(); +2:op_io(); +3:aa.l = op_readsp(sp); +4:aa.h = op_readsp(sp + 1); +5:op_io(); +6:if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_$1_b(); end; } +7:last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_$1_w(); +} + +bit_const(0x89) { +1:if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { + regs.p.z = ((rd.l & regs.a.l) == 0); + end; + } +2:last_cycle(); + rd.h = op_readpc(); + regs.p.z = ((rd.w & regs.a.w) == 0); +} diff --git a/src/cpu/scpu/core/op_read.cpp b/src/cpu/scpu/core/op_read.cpp new file mode 100644 index 00000000..fee2eda8 --- /dev/null +++ b/src/cpu/scpu/core/op_read.cpp @@ -0,0 +1,1651 @@ +//adc_const +case 0x69: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_adc_w(); +} break; + +//and_const +case 0x29: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_and_w(); +} break; + +//cmp_const +case 0xc9: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_cmp_w(); +} break; + +//cpx_const +case 0xe0: { + if(regs.p.x)last_cycle(); + rd.l = op_readpc(); + if(regs.p.x) { op_cpx_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_cpx_w(); +} break; + +//cpy_const +case 0xc0: { + if(regs.p.x)last_cycle(); + rd.l = op_readpc(); + if(regs.p.x) { op_cpy_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_cpy_w(); +} break; + +//eor_const +case 0x49: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_eor_w(); +} break; + +//lda_const +case 0xa9: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_lda_w(); +} break; + +//ldx_const +case 0xa2: { + if(regs.p.x)last_cycle(); + rd.l = op_readpc(); + if(regs.p.x) { op_ldx_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_ldx_w(); +} break; + +//ldy_const +case 0xa0: { + if(regs.p.x)last_cycle(); + rd.l = op_readpc(); + if(regs.p.x) { op_ldy_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_ldy_w(); +} break; + +//ora_const +case 0x09: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_ora_w(); +} break; + +//sbc_const +case 0xe9: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readpc(); + op_sbc_w(); +} break; + +//adc_addr +case 0x6d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_adc_w(); +} break; + +//and_addr +case 0x2d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_and_w(); +} break; + +//bit_addr +case 0x2c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_bit_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_bit_w(); +} break; + +//cmp_addr +case 0xcd: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_cmp_w(); +} break; + +//cpx_addr +case 0xec: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.x) { op_cpx_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_cpx_w(); +} break; + +//cpy_addr +case 0xcc: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.x) { op_cpy_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_cpy_w(); +} break; + +//eor_addr +case 0x4d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_eor_w(); +} break; + +//lda_addr +case 0xad: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_lda_w(); +} break; + +//ldx_addr +case 0xae: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.x) { op_ldx_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_ldx_w(); +} break; + +//ldy_addr +case 0xac: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.x) { op_ldy_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_ldy_w(); +} break; + +//ora_addr +case 0x0d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_ora_w(); +} break; + +//sbc_addr +case 0xed: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_sbc_w(); +} break; + +//adc_addrx +case 0x7d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_adc_w(); +} break; + +//and_addrx +case 0x3d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_and_w(); +} break; + +//bit_addrx +case 0x3c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_bit_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_bit_w(); +} break; + +//cmp_addrx +case 0xdd: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_cmp_w(); +} break; + +//eor_addrx +case 0x5d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_eor_w(); +} break; + +//lda_addrx +case 0xbd: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_lda_w(); +} break; + +//ldy_addrx +case 0xbc: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.x) { op_ldy_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_ldy_w(); +} break; + +//ora_addrx +case 0x1d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_ora_w(); +} break; + +//sbc_addrx +case 0xfd: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_sbc_w(); +} break; + +//adc_addry +case 0x79: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_adc_w(); +} break; + +//and_addry +case 0x39: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_and_w(); +} break; + +//cmp_addry +case 0xd9: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_cmp_w(); +} break; + +//eor_addry +case 0x59: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_eor_w(); +} break; + +//lda_addry +case 0xb9: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_lda_w(); +} break; + +//ldx_addry +case 0xbe: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.x)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.x) { op_ldx_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_ldx_w(); +} break; + +//ora_addry +case 0x19: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_ora_w(); +} break; + +//sbc_addry +case 0xf9: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_sbc_w(); +} break; + +//adc_long +case 0x6f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_adc_w(); +} break; + +//and_long +case 0x2f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_and_w(); +} break; + +//cmp_long +case 0xcf: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_cmp_w(); +} break; + +//eor_long +case 0x4f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_eor_w(); +} break; + +//lda_long +case 0xaf: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_lda_w(); +} break; + +//ora_long +case 0x0f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_ora_w(); +} break; + +//sbc_long +case 0xef: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_sbc_w(); +} break; + +//adc_longx +case 0x7f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_adc_w(); +} break; + +//and_longx +case 0x3f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_and_w(); +} break; + +//cmp_longx +case 0xdf: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_cmp_w(); +} break; + +//eor_longx +case 0x5f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_eor_w(); +} break; + +//lda_longx +case 0xbf: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_lda_w(); +} break; + +//ora_longx +case 0x1f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_ora_w(); +} break; + +//sbc_longx +case 0xff: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.x.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.x.w + 1); + op_sbc_w(); +} break; + +//adc_dp +case 0x65: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_adc_w(); +} break; + +//and_dp +case 0x25: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_and_w(); +} break; + +//bit_dp +case 0x24: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_bit_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_bit_w(); +} break; + +//cmp_dp +case 0xc5: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_cmp_w(); +} break; + +//cpx_dp +case 0xe4: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.x) { op_cpx_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_cpx_w(); +} break; + +//cpy_dp +case 0xc4: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.x) { op_cpy_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_cpy_w(); +} break; + +//eor_dp +case 0x45: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_eor_w(); +} break; + +//lda_dp +case 0xa5: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_lda_w(); +} break; + +//ldx_dp +case 0xa6: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.x) { op_ldx_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_ldx_w(); +} break; + +//ldy_dp +case 0xa4: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.x) { op_ldy_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_ldy_w(); +} break; + +//ora_dp +case 0x05: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_ora_w(); +} break; + +//sbc_dp +case 0xe5: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + 1); + op_sbc_w(); +} break; + +//adc_dpx +case 0x75: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_adc_w(); +} break; + +//and_dpx +case 0x35: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_and_w(); +} break; + +//bit_dpx +case 0x34: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_bit_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_bit_w(); +} break; + +//cmp_dpx +case 0xd5: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_cmp_w(); +} break; + +//eor_dpx +case 0x55: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_eor_w(); +} break; + +//lda_dpx +case 0xb5: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_lda_w(); +} break; + +//ldy_dpx +case 0xb4: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.x) { op_ldy_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_ldy_w(); +} break; + +//ora_dpx +case 0x15: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_ora_w(); +} break; + +//sbc_dpx +case 0xf5: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdp(dp + regs.x.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.x.w + 1); + op_sbc_w(); +} break; + +//ldx_dpy +case 0xb6: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.x)last_cycle(); + rd.l = op_readdp(dp + regs.y.w); + if(regs.p.x) { op_ldx_b(); break; } + last_cycle(); + rd.h = op_readdp(dp + regs.y.w + 1); + op_ldx_w(); +} break; + +//adc_idp +case 0x72: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_adc_w(); +} break; + +//and_idp +case 0x32: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_and_w(); +} break; + +//cmp_idp +case 0xd2: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_cmp_w(); +} break; + +//eor_idp +case 0x52: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_eor_w(); +} break; + +//lda_idp +case 0xb2: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_lda_w(); +} break; + +//ora_idp +case 0x12: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_ora_w(); +} break; + +//sbc_idp +case 0xf2: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_sbc_w(); +} break; + +//adc_idpx +case 0x61: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_adc_w(); +} break; + +//and_idpx +case 0x21: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_and_w(); +} break; + +//cmp_idpx +case 0xc1: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_cmp_w(); +} break; + +//eor_idpx +case 0x41: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_eor_w(); +} break; + +//lda_idpx +case 0xa1: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_lda_w(); +} break; + +//ora_idpx +case 0x01: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_ora_w(); +} break; + +//sbc_idpx +case 0xe1: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + 1); + op_sbc_w(); +} break; + +//adc_idpy +case 0x71: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_adc_w(); +} break; + +//and_idpy +case 0x31: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_and_w(); +} break; + +//cmp_idpy +case 0xd1: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_cmp_w(); +} break; + +//eor_idpy +case 0x51: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_eor_w(); +} break; + +//lda_idpy +case 0xb1: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_lda_w(); +} break; + +//ora_idpy +case 0x11: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_ora_w(); +} break; + +//sbc_idpy +case 0xf1: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_sbc_w(); +} break; + +//adc_ildp +case 0x67: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_adc_w(); +} break; + +//and_ildp +case 0x27: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_and_w(); +} break; + +//cmp_ildp +case 0xc7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_cmp_w(); +} break; + +//eor_ildp +case 0x47: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_eor_w(); +} break; + +//lda_ildp +case 0xa7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_lda_w(); +} break; + +//ora_ildp +case 0x07: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_ora_w(); +} break; + +//sbc_ildp +case 0xe7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + 1); + op_sbc_w(); +} break; + +//adc_ildpy +case 0x77: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_adc_w(); +} break; + +//and_ildpy +case 0x37: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_and_w(); +} break; + +//cmp_ildpy +case 0xd7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_cmp_w(); +} break; + +//eor_ildpy +case 0x57: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_eor_w(); +} break; + +//lda_ildpy +case 0xb7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_lda_w(); +} break; + +//ora_ildpy +case 0x17: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_ora_w(); +} break; + +//sbc_ildpy +case 0xf7: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + rd.l = op_readlong(aa.d + regs.y.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readlong(aa.d + regs.y.w + 1); + op_sbc_w(); +} break; + +//adc_sr +case 0x63: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_adc_w(); +} break; + +//and_sr +case 0x23: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_and_w(); +} break; + +//cmp_sr +case 0xc3: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_cmp_w(); +} break; + +//eor_sr +case 0x43: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_eor_w(); +} break; + +//lda_sr +case 0xa3: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_lda_w(); +} break; + +//ora_sr +case 0x03: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_ora_w(); +} break; + +//sbc_sr +case 0xe3: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readsp(sp); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readsp(sp + 1); + op_sbc_w(); +} break; + +//adc_isry +case 0x73: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_adc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_adc_w(); +} break; + +//and_isry +case 0x33: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_and_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_and_w(); +} break; + +//cmp_isry +case 0xd3: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_cmp_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_cmp_w(); +} break; + +//eor_isry +case 0x53: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_eor_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_eor_w(); +} break; + +//lda_isry +case 0xb3: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_lda_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_lda_w(); +} break; + +//ora_isry +case 0x13: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_ora_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_ora_w(); +} break; + +//sbc_isry +case 0xf3: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + rd.l = op_readdbr(aa.w + regs.y.w); + if(regs.p.m) { op_sbc_b(); break; } + last_cycle(); + rd.h = op_readdbr(aa.w + regs.y.w + 1); + op_sbc_w(); +} break; + +//bit_const +case 0x89: { + if(regs.p.m)last_cycle(); + rd.l = op_readpc(); + if(regs.p.m) { + regs.p.z = ((rd.l & regs.a.l) == 0); + break; + } + last_cycle(); + rd.h = op_readpc(); + regs.p.z = ((rd.w & regs.a.w) == 0); +} break; + diff --git a/src/cpu/scpu/core/op_rmw.b b/src/cpu/scpu/core/op_rmw.b new file mode 100644 index 00000000..d3b8b2f1 --- /dev/null +++ b/src/cpu/scpu/core/op_rmw.b @@ -0,0 +1,181 @@ +inc(0x1a, regs.p.m, a), +inx(0xe8, regs.p.x, x), +iny(0xc8, regs.p.x, y) { +1:last_cycle(); + op_io(); + if($1) { + regs.$2.l++; + regs.p.n = !!(regs.$2.l & 0x80); + regs.p.z = (regs.$2.l == 0); + } else { + regs.$2.w++; + regs.p.n = !!(regs.$2.w & 0x8000); + regs.p.z = (regs.$2.w == 0); + } +} + +dec(0x3a, regs.p.m, a), +dex(0xca, regs.p.x, x), +dey(0x88, regs.p.x, y) { +1:last_cycle(); + op_io(); + if($1) { + regs.$2.l--; + regs.p.n = !!(regs.$2.l & 0x80); + regs.p.z = (regs.$2.l == 0); + } else { + regs.$2.w--; + regs.p.n = !!(regs.$2.w & 0x8000); + regs.p.z = (regs.$2.w == 0); + } +} + +asl(0x0a) { +1:last_cycle(); + op_io(); + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +lsr(0x4a) { +1:last_cycle(); + op_io(); + if(regs.p.m) { + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +rol(0x2a) { +1:last_cycle(); + op_io(); + uint16 c = regs.p.c; + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +ror(0x6a) { +1:last_cycle(); + op_io(); + uint16 c; + if(regs.p.m) { + c = (regs.p.c)?0x80:0; + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + c = (regs.p.c)?0x8000:0; + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} + +inc_addr(0xee, inc), +dec_addr(0xce, dec), +asl_addr(0x0e, asl), +lsr_addr(0x4e, lsr), +rol_addr(0x2e, rol), +ror_addr(0x6e, ror), +trb_addr(0x1c, trb), +tsb_addr(0x0c, tsb) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:rd.l = op_readdbr(aa.w); +4:if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); +5:op_io(); + if(regs.p.m) { op_$1_b(); } + else { op_$1_w(); +6:op_writedbr(aa.w + 1, rd.h); } +7:last_cycle(); + op_writedbr(aa.w, rd.l); +} + +inc_addrx(0xfe, inc), +dec_addrx(0xde, dec), +asl_addrx(0x1e, asl), +lsr_addrx(0x5e, lsr), +rol_addrx(0x3e, rol), +ror_addrx(0x7e, ror) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io(); +4:rd.l = op_readdbr(aa.w + regs.x.w); +5:if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); +6:op_io(); + if(regs.p.m) { op_$1_b(); } + else { op_$1_w(); +7:op_writedbr(aa.w + regs.x.w + 1, rd.h); } +8:last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} + +inc_dp(0xe6, inc), +dec_dp(0xc6, dec), +asl_dp(0x06, asl), +lsr_dp(0x46, lsr), +rol_dp(0x26, rol), +ror_dp(0x66, ror), +trb_dp(0x14, trb), +tsb_dp(0x04, tsb) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:rd.l = op_readdp(dp); +4:if(!regs.p.m)rd.h = op_readdp(dp + 1); +5:op_io(); + if(regs.p.m) { op_$1_b(); } + else { op_$1_w(); +6:op_writedp(dp + 1, rd.h); } +7:last_cycle(); + op_writedp(dp, rd.l); +} + +inc_dpx(0xf6, inc), +dec_dpx(0xd6, dec), +asl_dpx(0x16, asl), +lsr_dpx(0x56, lsr), +rol_dpx(0x36, rol), +ror_dpx(0x76, ror) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:rd.l = op_readdp(dp + regs.x.w); +5:if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); +6:op_io(); + if(regs.p.m) { op_$1_b(); } + else { op_$1_w(); +7:op_writedp(dp + regs.x.w + 1, rd.h); } +8:last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} diff --git a/src/cpu/scpu/core/op_rmw.cpp b/src/cpu/scpu/core/op_rmw.cpp new file mode 100644 index 00000000..7924a1ab --- /dev/null +++ b/src/cpu/scpu/core/op_rmw.cpp @@ -0,0 +1,570 @@ +//inc +case 0x1a: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.a.l++; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w++; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//inx +case 0xe8: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l++; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w++; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} break; + +//iny +case 0xc8: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.y.l++; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w++; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} break; + +//dec +case 0x3a: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.a.l--; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.a.w--; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//dex +case 0xca: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.x.l--; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); + } else { + regs.x.w--; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); + } +} break; + +//dey +case 0x88: { + last_cycle(); + op_io(); + if(regs.p.x) { + regs.y.l--; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); + } else { + regs.y.w--; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); + } +} break; + +//asl +case 0x0a: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//lsr +case 0x4a: { + last_cycle(); + op_io(); + if(regs.p.m) { + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//rol +case 0x2a: { + last_cycle(); + op_io(); + uint16 c = regs.p.c; + if(regs.p.m) { + regs.p.c = !!(regs.a.l & 0x80); + regs.a.l <<= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + regs.p.c = !!(regs.a.w & 0x8000); + regs.a.w <<= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//ror +case 0x6a: { + last_cycle(); + op_io(); + uint16 c; + if(regs.p.m) { + c = (regs.p.c)?0x80:0; + regs.p.c = regs.a.l & 1; + regs.a.l >>= 1; + regs.a.l |= c; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); + } else { + c = (regs.p.c)?0x8000:0; + regs.p.c = regs.a.w & 1; + regs.a.w >>= 1; + regs.a.w |= c; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); + } +} break; + +//inc_addr +case 0xee: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_inc_b(); } + else { op_inc_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//dec_addr +case 0xce: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_dec_b(); } + else { op_dec_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//asl_addr +case 0x0e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_asl_b(); } + else { op_asl_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//lsr_addr +case 0x4e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_lsr_b(); } + else { op_lsr_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//rol_addr +case 0x2e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_rol_b(); } + else { op_rol_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//ror_addr +case 0x6e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_ror_b(); } + else { op_ror_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//trb_addr +case 0x1c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_trb_b(); } + else { op_trb_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//tsb_addr +case 0x0c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + rd.l = op_readdbr(aa.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + 1); + op_io(); + if(regs.p.m) { op_tsb_b(); } + else { op_tsb_w(); + op_writedbr(aa.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w, rd.l); +} break; + +//inc_addrx +case 0xfe: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_inc_b(); } + else { op_inc_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//dec_addrx +case 0xde: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_dec_b(); } + else { op_dec_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//asl_addrx +case 0x1e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_asl_b(); } + else { op_asl_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//lsr_addrx +case 0x5e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_lsr_b(); } + else { op_lsr_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//rol_addrx +case 0x3e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_rol_b(); } + else { op_rol_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//ror_addrx +case 0x7e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io(); + rd.l = op_readdbr(aa.w + regs.x.w); + if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_ror_b(); } + else { op_ror_w(); + op_writedbr(aa.w + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedbr(aa.w + regs.x.w, rd.l); +} break; + +//inc_dp +case 0xe6: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_inc_b(); } + else { op_inc_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//dec_dp +case 0xc6: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_dec_b(); } + else { op_dec_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//asl_dp +case 0x06: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_asl_b(); } + else { op_asl_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//lsr_dp +case 0x46: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_lsr_b(); } + else { op_lsr_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//rol_dp +case 0x26: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_rol_b(); } + else { op_rol_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//ror_dp +case 0x66: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_ror_b(); } + else { op_ror_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//trb_dp +case 0x14: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_trb_b(); } + else { op_trb_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//tsb_dp +case 0x04: { + dp = op_readpc(); + op_io_cond2(); + rd.l = op_readdp(dp); + if(!regs.p.m)rd.h = op_readdp(dp + 1); + op_io(); + if(regs.p.m) { op_tsb_b(); } + else { op_tsb_w(); + op_writedp(dp + 1, rd.h); } + last_cycle(); + op_writedp(dp, rd.l); +} break; + +//inc_dpx +case 0xf6: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_inc_b(); } + else { op_inc_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + +//dec_dpx +case 0xd6: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_dec_b(); } + else { op_dec_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + +//asl_dpx +case 0x16: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_asl_b(); } + else { op_asl_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + +//lsr_dpx +case 0x56: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_lsr_b(); } + else { op_lsr_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + +//rol_dpx +case 0x36: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_rol_b(); } + else { op_rol_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + +//ror_dpx +case 0x76: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + rd.l = op_readdp(dp + regs.x.w); + if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1); + op_io(); + if(regs.p.m) { op_ror_b(); } + else { op_ror_w(); + op_writedp(dp + regs.x.w + 1, rd.h); } + last_cycle(); + op_writedp(dp + regs.x.w, rd.l); +} break; + diff --git a/src/cpu/scpu/core/op_write.b b/src/cpu/scpu/core/op_write.b new file mode 100644 index 00000000..a962d5d7 --- /dev/null +++ b/src/cpu/scpu/core/op_write.b @@ -0,0 +1,181 @@ +sta_addr(0x8d, regs.p.m, regs.a.w), +stx_addr(0x8e, regs.p.x, regs.x.w), +sty_addr(0x8c, regs.p.x, regs.y.w), +stz_addr(0x9c, regs.p.m, 0x0000) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:if($1)last_cycle(); + op_writedbr(aa.w, $2); + if($1)end; +4:last_cycle(); + op_writedbr(aa.w + 1, $2 >> 8); +} + +sta_addrx(0x9d, regs.p.m, regs.a.w), +stz_addrx(0x9e, regs.p.m, 0x0000) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io_cond4(aa.w, aa.w + regs.x.w); +4:if($1)last_cycle(); + op_writedbr(aa.w + regs.x.w, $2); + if($1)end; +5:last_cycle(); + op_writedbr(aa.w + regs.x.w + 1, $2 >> 8); +} + +sta_addry(0x99) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:op_io_cond4(aa.w, aa.w + regs.y.w); +4:if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +5:last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} + +sta_long(0x8f) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:aa.b = op_readpc(); +4:if(regs.p.m)last_cycle(); + op_writelong(aa.d, regs.a.l); + if(regs.p.m)end; +5:last_cycle(); + op_writelong(aa.d + 1, regs.a.h); +} + +sta_longx(0x9f) { +1:aa.l = op_readpc(); +2:aa.h = op_readpc(); +3:aa.b = op_readpc(); +4:if(regs.p.m)last_cycle(); + op_writelong(aa.d + regs.x.w, regs.a.l); + if(regs.p.m)end; +5:last_cycle(); + op_writelong(aa.d + regs.x.w + 1, regs.a.h); +} + +sta_dp(0x85, regs.p.m, regs.a.w), +stx_dp(0x86, regs.p.x, regs.x.w), +sty_dp(0x84, regs.p.x, regs.y.w), +stz_dp(0x64, regs.p.m, 0x0000) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:if($1)last_cycle(); + op_writedp(dp, $2); + if($1)end; +4:last_cycle(); + op_writedp(dp + 1, $2 >> 8); +} + +sta_dpx(0x95, regs.p.m, regs.a.w), +sty_dpx(0x94, regs.p.x, regs.y.w), +stz_dpx(0x74, regs.p.m, 0x0000) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:if($1)last_cycle(); + op_writedp(dp + regs.x.w, $2); + if($1)end; +5:last_cycle(); + op_writedp(dp + regs.x.w + 1, $2 >> 8); +} + +stx_dpy(0x96) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:if(regs.p.x)last_cycle(); + op_writedp(dp + regs.y.w, regs.x.l); + if(regs.p.x)end; +5:last_cycle(); + op_writedp(dp + regs.y.w + 1, regs.x.h); +} + +sta_idp(0x92) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:if(regs.p.m)last_cycle(); + op_writedbr(aa.w, regs.a.l); + if(regs.p.m)end; +6:last_cycle(); + op_writedbr(aa.w + 1, regs.a.h); +} + +sta_ildp(0x87) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:aa.b = op_readdp(dp + 2); +6:if(regs.p.m)last_cycle(); + op_writelong(aa.d, regs.a.l); + if(regs.p.m)end; +7:last_cycle(); + op_writelong(aa.d + 1, regs.a.h); +} + +sta_idpx(0x81) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:op_io(); +4:aa.l = op_readdp(dp + regs.x.w); +5:aa.h = op_readdp(dp + regs.x.w + 1); +6:if(regs.p.m)last_cycle(); + op_writedbr(aa.w, regs.a.l); + if(regs.p.m)end; +7:last_cycle(); + op_writedbr(aa.w + 1, regs.a.h); +} + +sta_idpy(0x91) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:op_io_cond4(aa.w, aa.w + regs.y.w); +6:if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} + +sta_ildpy(0x97) { +1:dp = op_readpc(); +2:op_io_cond2(); +3:aa.l = op_readdp(dp); +4:aa.h = op_readdp(dp + 1); +5:aa.b = op_readdp(dp + 2); +6:if(regs.p.m)last_cycle(); + op_writelong(aa.d + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:last_cycle(); + op_writelong(aa.d + regs.y.w + 1, regs.a.h); +} + +sta_sr(0x83) { +1:sp = op_readpc(); +2:op_io(); +3:if(regs.p.m)last_cycle(); + op_writesp(sp, regs.a.l); + if(regs.p.m)end; +4:last_cycle(); + op_writesp(sp + 1, regs.a.h); +} + +sta_isry(0x93) { +1:sp = op_readpc(); +2:op_io(); +3:aa.l = op_readsp(sp); +4:aa.h = op_readsp(sp + 1); +5:op_io(); +6:if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)end; +7:last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} diff --git a/src/cpu/scpu/core/op_write.cpp b/src/cpu/scpu/core/op_write.cpp new file mode 100644 index 00000000..64cb6336 --- /dev/null +++ b/src/cpu/scpu/core/op_write.cpp @@ -0,0 +1,290 @@ +//sta_addr +case 0x8d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w, regs.a.w); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + 1, regs.a.w >> 8); +} break; + +//stx_addr +case 0x8e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + op_writedbr(aa.w, regs.x.w); + if(regs.p.x)break; + last_cycle(); + op_writedbr(aa.w + 1, regs.x.w >> 8); +} break; + +//sty_addr +case 0x8c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.x)last_cycle(); + op_writedbr(aa.w, regs.y.w); + if(regs.p.x)break; + last_cycle(); + op_writedbr(aa.w + 1, regs.y.w >> 8); +} break; + +//stz_addr +case 0x9c: { + aa.l = op_readpc(); + aa.h = op_readpc(); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w, 0x0000); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + 1, 0x0000 >> 8); +} break; + +//sta_addrx +case 0x9d: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.x.w, regs.a.w); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8); +} break; + +//stz_addrx +case 0x9e: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.x.w); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.x.w, 0x0000); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8); +} break; + +//sta_addry +case 0x99: { + aa.l = op_readpc(); + aa.h = op_readpc(); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} break; + +//sta_long +case 0x8f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + op_writelong(aa.d, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writelong(aa.d + 1, regs.a.h); +} break; + +//sta_longx +case 0x9f: { + aa.l = op_readpc(); + aa.h = op_readpc(); + aa.b = op_readpc(); + if(regs.p.m)last_cycle(); + op_writelong(aa.d + regs.x.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writelong(aa.d + regs.x.w + 1, regs.a.h); +} break; + +//sta_dp +case 0x85: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + op_writedp(dp, regs.a.w); + if(regs.p.m)break; + last_cycle(); + op_writedp(dp + 1, regs.a.w >> 8); +} break; + +//stx_dp +case 0x86: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + op_writedp(dp, regs.x.w); + if(regs.p.x)break; + last_cycle(); + op_writedp(dp + 1, regs.x.w >> 8); +} break; + +//sty_dp +case 0x84: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.x)last_cycle(); + op_writedp(dp, regs.y.w); + if(regs.p.x)break; + last_cycle(); + op_writedp(dp + 1, regs.y.w >> 8); +} break; + +//stz_dp +case 0x64: { + dp = op_readpc(); + op_io_cond2(); + if(regs.p.m)last_cycle(); + op_writedp(dp, 0x0000); + if(regs.p.m)break; + last_cycle(); + op_writedp(dp + 1, 0x0000 >> 8); +} break; + +//sta_dpx +case 0x95: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + op_writedp(dp + regs.x.w, regs.a.w); + if(regs.p.m)break; + last_cycle(); + op_writedp(dp + regs.x.w + 1, regs.a.w >> 8); +} break; + +//sty_dpx +case 0x94: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.x)last_cycle(); + op_writedp(dp + regs.x.w, regs.y.w); + if(regs.p.x)break; + last_cycle(); + op_writedp(dp + regs.x.w + 1, regs.y.w >> 8); +} break; + +//stz_dpx +case 0x74: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.m)last_cycle(); + op_writedp(dp + regs.x.w, 0x0000); + if(regs.p.m)break; + last_cycle(); + op_writedp(dp + regs.x.w + 1, 0x0000 >> 8); +} break; + +//stx_dpy +case 0x96: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + if(regs.p.x)last_cycle(); + op_writedp(dp + regs.y.w, regs.x.l); + if(regs.p.x)break; + last_cycle(); + op_writedp(dp + regs.y.w + 1, regs.x.h); +} break; + +//sta_idp +case 0x92: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + 1, regs.a.h); +} break; + +//sta_ildp +case 0x87: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + op_writelong(aa.d, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writelong(aa.d + 1, regs.a.h); +} break; + +//sta_idpx +case 0x81: { + dp = op_readpc(); + op_io_cond2(); + op_io(); + aa.l = op_readdp(dp + regs.x.w); + aa.h = op_readdp(dp + regs.x.w + 1); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + 1, regs.a.h); +} break; + +//sta_idpy +case 0x91: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + op_io_cond4(aa.w, aa.w + regs.y.w); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} break; + +//sta_ildpy +case 0x97: { + dp = op_readpc(); + op_io_cond2(); + aa.l = op_readdp(dp); + aa.h = op_readdp(dp + 1); + aa.b = op_readdp(dp + 2); + if(regs.p.m)last_cycle(); + op_writelong(aa.d + regs.y.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writelong(aa.d + regs.y.w + 1, regs.a.h); +} break; + +//sta_sr +case 0x83: { + sp = op_readpc(); + op_io(); + if(regs.p.m)last_cycle(); + op_writesp(sp, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writesp(sp + 1, regs.a.h); +} break; + +//sta_isry +case 0x93: { + sp = op_readpc(); + op_io(); + aa.l = op_readsp(sp); + aa.h = op_readsp(sp + 1); + op_io(); + if(regs.p.m)last_cycle(); + op_writedbr(aa.w + regs.y.w, regs.a.l); + if(regs.p.m)break; + last_cycle(); + op_writedbr(aa.w + regs.y.w + 1, regs.a.h); +} break; + diff --git a/src/cpu/scpu/core/opfn.cpp b/src/cpu/scpu/core/opfn.cpp new file mode 100644 index 00000000..d14252e2 --- /dev/null +++ b/src/cpu/scpu/core/opfn.cpp @@ -0,0 +1,377 @@ +//op_read +inline void sCPU::op_adc_b() { +int32 r = regs.a.l + rd.l + regs.p.c; + if(regs.p.d) { + uint8 n0 = (regs.a.l ) & 15; + uint8 n1 = (regs.a.l >> 4) & 15; + n0 += ((rd.l) & 15) + regs.p.c; + if(n0 > 9) { + n0 -= 10; + n0 &= 15; + n1++; + } + n1 += ((rd.l >> 4) & 15); + if(n1 > 9) { + n1 -= 10; + n1 &= 15; + regs.p.c = 1; + } else { + regs.p.c = 0; + } + r = (n1 << 4) | (n0); + } else { + r = regs.a.l + rd.l + regs.p.c; + regs.p.c = (r > 0xff); + } + regs.p.n = !!(r & 0x80); + regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); + regs.p.z = ((uint8)r == 0); + regs.a.l = r; +} + +inline void sCPU::op_adc_w() { +int32 r; + if(regs.p.d) { + uint8 n0 = (regs.a.w ) & 15; + uint8 n1 = (regs.a.w >> 4) & 15; + uint8 n2 = (regs.a.w >> 8) & 15; + uint8 n3 = (regs.a.w >> 12) & 15; + n0 += ((rd.w) & 15) + regs.p.c; + if(n0 > 9) { + n0 -= 10; + n0 &= 15; + n1++; + } + n1 += ((rd.w >> 4) & 15); + if(n1 > 9) { + n1 -= 10; + n1 &= 15; + n2++; + } + n2 += ((rd.w >> 8) & 15); + if(n2 > 9) { + n2 -= 10; + n2 &= 15; + n3++; + } + n3 += ((rd.w >> 12) & 15); + if(n3 > 9) { + n3 -= 10; + n3 &= 15; + regs.p.c = 1; + } else { + regs.p.c = 0; + } + r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0); + } else { + r = regs.a.w + rd.w + regs.p.c; + regs.p.c = (r > 0xffff); + } + regs.p.n = !!(r & 0x8000); + regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.a.w = r; +} + +inline void sCPU::op_and_b() { + regs.a.l &= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void sCPU::op_and_w() { + regs.a.w &= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void sCPU::op_bit_b() { + regs.p.n = !!(rd.l & 0x80); + regs.p.v = !!(rd.l & 0x40); + regs.p.z = ((rd.l & regs.a.l) == 0); +} + +inline void sCPU::op_bit_w() { + regs.p.n = !!(rd.w & 0x8000); + regs.p.v = !!(rd.w & 0x4000); + regs.p.z = ((rd.w & regs.a.w) == 0); +} + +inline void sCPU::op_cmp_b() { +int32 r = regs.a.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_cmp_w() { +int32 r = regs.a.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_cpx_b() { +int32 r = regs.x.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_cpx_w() { +int32 r = regs.x.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_cpy_b() { +int32 r = regs.y.l - rd.l; + regs.p.n = !!(r & 0x80); + regs.p.z = ((uint8)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_cpy_w() { +int32 r = regs.y.w - rd.w; + regs.p.n = !!(r & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.p.c = (r >= 0); +} + +inline void sCPU::op_eor_b() { + regs.a.l ^= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void sCPU::op_eor_w() { + regs.a.w ^= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void sCPU::op_lda_b() { + regs.a.l = rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void sCPU::op_lda_w() { + regs.a.w = rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void sCPU::op_ldx_b() { + regs.x.l = rd.l; + regs.p.n = !!(regs.x.l & 0x80); + regs.p.z = (regs.x.l == 0); +} + +inline void sCPU::op_ldx_w() { + regs.x.w = rd.w; + regs.p.n = !!(regs.x.w & 0x8000); + regs.p.z = (regs.x.w == 0); +} + +inline void sCPU::op_ldy_b() { + regs.y.l = rd.l; + regs.p.n = !!(regs.y.l & 0x80); + regs.p.z = (regs.y.l == 0); +} + +inline void sCPU::op_ldy_w() { + regs.y.w = rd.w; + regs.p.n = !!(regs.y.w & 0x8000); + regs.p.z = (regs.y.w == 0); +} + +inline void sCPU::op_ora_b() { + regs.a.l |= rd.l; + regs.p.n = !!(regs.a.l & 0x80); + regs.p.z = (regs.a.l == 0); +} + +inline void sCPU::op_ora_w() { + regs.a.w |= rd.w; + regs.p.n = !!(regs.a.w & 0x8000); + regs.p.z = (regs.a.w == 0); +} + +inline void sCPU::op_sbc_b() { +int32 r; + if(regs.p.d) { + uint8 n0 = (regs.a.l ) & 15; + uint8 n1 = (regs.a.l >> 4) & 15; + n0 -= ((rd.l ) & 15) + !regs.p.c; + n1 -= ((rd.l >> 4) & 15); + if(n0 > 9) { + n0 += 10; + n1--; + } + if(n1 > 9) { + n1 += 10; + regs.p.c = 0; + } else { + regs.p.c = 1; + } + r = (n1 << 4) | (n0); + } else { + r = regs.a.l - rd.l - !regs.p.c; + regs.p.c = (r >= 0); + } + regs.p.n = !!(r & 0x80); + regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); + regs.p.z = ((uint8)r == 0); + regs.a.l = r; +} + +inline void sCPU::op_sbc_w() { +int32 r; + if(regs.p.d) { + uint8 n0 = (regs.a.w ) & 15; + uint8 n1 = (regs.a.w >> 4) & 15; + uint8 n2 = (regs.a.w >> 8) & 15; + uint8 n3 = (regs.a.w >> 12) & 15; + n0 -= ((rd.w ) & 15) + !regs.p.c; + n1 -= ((rd.w >> 4) & 15); + n2 -= ((rd.w >> 8) & 15); + n3 -= ((rd.w >> 12) & 15); + if(n0 > 9) { + n0 += 10; + n1--; + } + if(n1 > 9) { + n1 += 10; + n2--; + } + if(n2 > 9) { + n2 += 10; + n3--; + } + if(n3 > 9) { + n3 += 10; + regs.p.c = 0; + } else { + regs.p.c = 1; + } + r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0); + } else { + r = regs.a.w - rd.w - !regs.p.c; + regs.p.c = (r >= 0); + } + regs.p.n = !!(r & 0x8000); + regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); + regs.p.z = ((uint16)r == 0); + regs.a.w = r; +} + +//op_rmw +inline void sCPU::op_inc_b() { + rd.l++; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_inc_w() { + rd.w++; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_dec_b() { + rd.l--; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_dec_w() { + rd.w--; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_asl_b() { + regs.p.c = !!(rd.l & 0x80); + rd.l <<= 1; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_asl_w() { + regs.p.c = !!(rd.w & 0x8000); + rd.w <<= 1; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_lsr_b() { + regs.p.c = rd.l & 1; + rd.l >>= 1; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_lsr_w() { + regs.p.c = rd.w & 1; + rd.w >>= 1; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_rol_b() { +uint16 c = regs.p.c; + regs.p.c = !!(rd.l & 0x80); + rd.l <<= 1; + rd.l |= c; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_rol_w() { +uint16 c = regs.p.c; + regs.p.c = !!(rd.w & 0x8000); + rd.w <<= 1; + rd.w |= c; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_ror_b() { +uint16 c = (regs.p.c)?0x80:0; + regs.p.c = rd.l & 1; + rd.l >>= 1; + rd.l |= c; + regs.p.n = !!(rd.l & 0x80); + regs.p.z = (rd.l == 0); +} + +inline void sCPU::op_ror_w() { +uint16 c = (regs.p.c)?0x8000:0; + regs.p.c = rd.w & 1; + rd.w >>= 1; + rd.w |= c; + regs.p.n = !!(rd.w & 0x8000); + regs.p.z = (rd.w == 0); +} + +inline void sCPU::op_trb_b() { + regs.p.z = ((rd.l & regs.a.l) == 0); + rd.l &= ~regs.a.l; +} + +inline void sCPU::op_trb_w() { + regs.p.z = ((rd.w & regs.a.w) == 0); + rd.w &= ~regs.a.w; +} + +inline void sCPU::op_tsb_b() { + regs.p.z = ((rd.l & regs.a.l) == 0); + rd.l |= regs.a.l; +} + +inline void sCPU::op_tsb_w() { + regs.p.z = ((rd.w & regs.a.w) == 0); + rd.w |= regs.a.w; +} diff --git a/src/cpu/scpu/core/scpugen.cpp b/src/cpu/scpu/core/scpugen.cpp new file mode 100644 index 00000000..2047cecd --- /dev/null +++ b/src/cpu/scpu/core/scpugen.cpp @@ -0,0 +1,18 @@ +#define CLASS_NAME "sCPU" +#include "../../../lib/opgen_s.cpp" + +int main() { +//fph = fopen("op.h", "wb"); +//fpt = fopen("optable.cpp", "wb"); + + generate("op_read.cpp", "op_read.b"); + generate("op_write.cpp", "op_write.b"); + generate("op_rmw.cpp", "op_rmw.b"); + generate("op_pc.cpp", "op_pc.b"); + generate("op_misc.cpp", "op_misc.b"); + +//fclose(fph); +//fclose(fpt); + + return 0; +} diff --git a/src/cpu/scpu/dma/dma.cpp b/src/cpu/scpu/dma/dma.cpp new file mode 100644 index 00000000..fdb3838d --- /dev/null +++ b/src/cpu/scpu/dma/dma.cpp @@ -0,0 +1,252 @@ +/***** + * used by both DMA and HDMA + * prevents transfer across same bus (a->a or b->b) + * + * DMA address bus a cannot read from or write to the following addresses : + * $[00-3f|80-bf]:21[00-ff]

+ * $[00-3f|80-bf]:43[00-7f] + * $[00-3f|80-bf]:420b + * $[00-3f|80-bf]:420c + * + * DMA address bus b cannot read from $2180 + *****/ +void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) { +uint8 r; + if(direction == 0) { //a->b + if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 || + (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) { + r = r_cpu->regs.mdr; //invalid reads return open bus + } else { + r = r_mem->read(abus); + } + r_mem->write(0x2100 | bbus, r); + } else { //b->a + uint8 r = (bbus == 0x80) ? r_cpu->regs.mdr : r_mem->read(0x2100 | bbus); + if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 || + (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return; + r_mem->write(abus, r); + } + + add_clocks(8); + co_return(); + cycle_edge(); +} + +/***** + * address calculation functions + *****/ + +uint8 sCPU::dma_bbus(uint8 i, uint8 index) { + switch(channel[i].xfermode) { + default: + case 0: return (channel[i].destaddr); break; //0 + case 1: return (channel[i].destaddr + (index & 1)); break; //0,1 + case 2: return (channel[i].destaddr); break; //0,0 + case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 + case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3 + case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1 + case 6: return (channel[i].destaddr); break; //0,0 [2] + case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3] + } +} + +uint32 sCPU::dma_addr(uint8 i) { +uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr); + + if(channel[i].fixedxfer == false) { + if(channel[i].reversexfer == false) { + channel[i].srcaddr++; + } else { + channel[i].srcaddr--; + } + } + + return r; +} + +uint32 sCPU::hdma_addr(uint8 i) { + return (channel[i].srcbank << 16) | (channel[i].hdma_addr++); +} + +uint32 sCPU::hdma_iaddr(uint8 i) { + return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++); +} + +/***** + * DMA functions + *****/ + +void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) { + if(cartridge.cart.sdd1 == true && sdd1->dma_active() == true) { + r_mem->write(0x2100 | bbus, sdd1->dma_read()); + } else { + dma_transfer(0, bbus, dma_addr(i)); + } + channel[i].xfersize--; +} + +void sCPU::dma_transfertobusa(uint8 i, uint8 bbus) { + dma_transfer(1, bbus, dma_addr(i)); + channel[i].xfersize--; +} + +void sCPU::dma_write(uint8 i, uint8 index) { +//cannot use dma_transfer() directly, +//due to current S-DD1 implementation + if(channel[i].direction == 0) { + dma_transfertobusb(i, index); + } else { + dma_transfertobusa(i, index); + } +} + +void sCPU::dma_run() { + add_clocks(18); + + for(int i = 0; i < 8; i++) { + if(channel[i].dma_enabled == false)continue; + + if(cartridge.cart.sdd1 == true) { + sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), + channel[i].xfersize); + } + + uint index = 0; + do { + dma_write(i, dma_bbus(i, index++)); + } while(channel[i].xfersize); + + channel[i].dma_enabled = false; + } +} + +/***** + * HDMA functions + *****/ + +bool sCPU::hdma_active(uint8 i) { + return (channel[i].hdma_enabled && !channel[i].hdma_completed); +} + +uint8 sCPU::hdma_enabled_channels() { +uint8 r = 0; + for(int i = 0; i < 8; i++) { + if(channel[i].hdma_enabled)r++; + } + return r; +} + +uint8 sCPU::hdma_active_channels() { +uint8 r = 0; + for(int i = 0; i < 8; i++) { + if(hdma_active(i) == true)r++; + } + return r; +} + +void sCPU::hdma_update(uint8 i) { + channel[i].hdma_line_counter = r_mem->read(hdma_addr(i)); + add_clocks(8); + + if(channel[i].hdma_indirect) { + channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8; + add_clocks(8); + } + + if(channel[i].hdma_line_counter == 0) { + channel[i].hdma_completed = true; + channel[i].hdma_do_transfer = false; + return; + } + + channel[i].hdma_do_transfer = true; + + if(channel[i].hdma_indirect) { + channel[i].hdma_iaddr >>= 8; + channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8; + add_clocks(8); + } +} + +void sCPU::hdma_run() { + if(hdma_active_channels() == 0)return; + + add_clocks(18); + +static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 }; + for(int i = 0; i < 8; i++) { + if(hdma_active(i) == false)continue; + + if(channel[i].hdma_do_transfer) { + int xferlen = hdma_xferlen[channel[i].xfermode]; + for(int index = 0; index < xferlen; index++) { + if(bool(config::cpu.hdma_enable) == true) { + dma_transfer(channel[i].direction, dma_bbus(i, index), + !channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i)); + } else { + add_clocks(8); + co_return(); + cycle_edge(); + } + } + } + + channel[i].hdma_line_counter--; + channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80); + if((channel[i].hdma_line_counter & 0x7f) == 0) { + hdma_update(i); + } + } +} + +void sCPU::hdma_init() { + for(int i = 0; i < 8; i++) { + channel[i].hdma_completed = false; + channel[i].hdma_do_transfer = false; + } + + if(hdma_enabled_channels() == 0)return; + + add_clocks(18); + + for(int i = 0; i < 8; i++) { + if(!channel[i].hdma_enabled)continue; + + channel[i].hdma_addr = channel[i].srcaddr; + hdma_update(i); + } +} + +/***** + * power / reset functions + *****/ + +void sCPU::dma_reset() { + for(int i = 0; i < 8; i++) { + channel[i].dma_enabled = false; + channel[i].hdma_enabled = false; + + channel[i].dmap = 0xff; + channel[i].direction = 1; + channel[i].hdma_indirect = true; + channel[i].reversexfer = true; + channel[i].fixedxfer = true; + channel[i].xfermode = 7; + + channel[i].destaddr = 0xff; + + channel[i].srcaddr = 0xffff; + channel[i].srcbank = 0xff; + + channel[i].xfersize = 0xffff; + //channel[i].hdma_iaddr = 0xffff; //union with xfersize + channel[i].hdma_ibank = 0xff; + + channel[i].hdma_addr = 0xffff; + channel[i].hdma_line_counter = 0xff; + channel[i].unknown = 0xff; + + channel[i].hdma_completed = false; + channel[i].hdma_do_transfer = false; + } +} diff --git a/src/cpu/scpu/dma/dma.h b/src/cpu/scpu/dma/dma.h new file mode 100644 index 00000000..fa8fc6f4 --- /dev/null +++ b/src/cpu/scpu/dma/dma.h @@ -0,0 +1,67 @@ +struct { +//$420b + bool dma_enabled; + +//$420c + bool hdma_enabled; + +//$43x0 + uint8 dmap; + bool direction; + bool hdma_indirect; + bool reversexfer; + bool fixedxfer; + uint8 xfermode; + +//$43x1 + uint8 destaddr; + +//$43x2-$43x3 + uint16 srcaddr; + +//$43x4 + uint8 srcbank; + +//$43x5-$43x6 + union { + uint16 xfersize; + uint16 hdma_iaddr; + }; + +//$43x7 + uint8 hdma_ibank; + +//$43x8-$43x9 + uint16 hdma_addr; + +//$43xa + uint8 hdma_line_counter; + +//$43xb/$43xf + uint8 unknown; + +//internal variables + bool hdma_completed; + bool hdma_do_transfer; +} channel[8]; + + void dma_transfer(bool direction, uint8 bbus, uint32 abus); + + uint8 dma_bbus(uint8 i, uint8 index); + uint32 dma_addr(uint8 i); + uint32 hdma_addr(uint8 i); + uint32 hdma_iaddr(uint8 i); + + void dma_transfertobusb(uint8 i, uint8 bbus); + void dma_transfertobusa(uint8 i, uint8 bbus); + void dma_write(uint8 i, uint8 index); + void dma_run(); + + bool hdma_active(uint8 i); + uint8 hdma_enabled_channels(); + uint8 hdma_active_channels(); + void hdma_update(uint8 i); + void hdma_run(); + void hdma_init(); + + void dma_reset(); diff --git a/src/cpu/scpu/memory/memory.cpp b/src/cpu/scpu/memory/memory.cpp new file mode 100644 index 00000000..c48de22e --- /dev/null +++ b/src/cpu/scpu/memory/memory.cpp @@ -0,0 +1,38 @@ +/***** + * These 3 functions control bus timing for the CPU. + * cpu_io is an I/O cycle, and always 6 clock cycles long. + * mem_read / mem_write indicate memory access bus cycles. + * they are either 6, 8, or 12 bus cycles long, depending + * both on location and the $420d.d0 FastROM enable bit. + *****/ + +void sCPU::op_io() { + status.clock_count = 6; + add_clocks(6); +//co_return(); + cycle_edge(); +} + +uint8 sCPU::op_read(uint32 addr) { + status.clock_count = r_mem->speed(addr); + add_clocks(status.clock_count - 4); +#ifdef FAVOR_ACCURACY + co_return(); +#endif + regs.mdr = r_mem->read(addr); + add_clocks(4); + cycle_edge(); + return regs.mdr; +} + +void sCPU::op_write(uint32 addr, uint8 data) { + status.clock_count = r_mem->speed(addr); + add_clocks(status.clock_count); +#ifdef FAVOR_ACCURACY + co_return(); +#endif +//below needs to be verified on hardware +//regs.mdr = data; + r_mem->write(addr, data); + cycle_edge(); +} diff --git a/src/cpu/scpu/memory/memory.h b/src/cpu/scpu/memory/memory.h new file mode 100644 index 00000000..96e9592b --- /dev/null +++ b/src/cpu/scpu/memory/memory.h @@ -0,0 +1,33 @@ +/***** + * CPU<>APU communication ports + *****/ +uint8 apu_port[4]; + uint8 port_read (uint8 port) { return apu_port[port & 3]; } + void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; } + +/***** + * core CPU bus functions + *****/ + void op_io(); + uint8 op_read (uint32 addr); + void op_write(uint32 addr, uint8 data); + +/***** + * helper memory addressing functions used by CPU core + *****/ + uint8 op_readpc () { return op_read((regs.pc.b << 16) + regs.pc.w++); } + uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); } + uint8 op_readaddr (uint32 addr) { return op_read(uclip<16>(addr)); } + uint8 op_readlong (uint32 addr) { return op_read(uclip<24>(addr)); } + uint8 op_readdbr (uint32 addr) { return op_read(uclip<24>((regs.db << 16) + addr)); } + uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + uclip<16>(addr)); } + uint8 op_readdp (uint32 addr) { return op_read(uclip<16>(regs.d + uclip<16>(addr))); } + uint8 op_readsp (uint32 addr) { return op_read(uclip<16>(regs.s + uclip<16>(addr))); } + + void op_writestack(uint8 data) { op_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; } + void op_writeaddr (uint32 addr, uint8 data) { op_write(uclip<16>(addr), data); } + void op_writelong (uint32 addr, uint8 data) { op_write(uclip<24>(addr), data); } + void op_writedbr (uint32 addr, uint8 data) { op_write(uclip<24>((regs.db << 16) + addr), data); } + void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + uclip<16>(addr), data); } + void op_writedp (uint32 addr, uint8 data) { op_write(uclip<16>(regs.d + uclip<16>(addr)), data); } + void op_writesp (uint32 addr, uint8 data) { op_write(uclip<16>(regs.s + uclip<16>(addr)), data); } diff --git a/src/cpu/scpu/mmio/mmio.cpp b/src/cpu/scpu/mmio/mmio.cpp new file mode 100644 index 00000000..7d15c294 --- /dev/null +++ b/src/cpu/scpu/mmio/mmio.cpp @@ -0,0 +1,669 @@ +uint8 sCPU::pio_status() { + return status.pio; +} + +/***** + * WRAM data registers + *****/ + +//WMDATA +uint8 sCPU::mmio_r2180() { +uint8 r = r_mem->read(0x7e0000 | status.wram_addr++); + status.wram_addr &= 0x01ffff; + return r; +} + +//WMDATA +void sCPU::mmio_w2180(uint8 data) { + r_mem->write(0x7e0000 | status.wram_addr++, data); + status.wram_addr &= 0x01ffff; +} + +//WMADDL +void sCPU::mmio_w2181(uint8 data) { + status.wram_addr = (status.wram_addr & 0xffff00) | (data); + status.wram_addr &= 0x01ffff; +} + +//WMADDM +void sCPU::mmio_w2182(uint8 data) { + status.wram_addr = (status.wram_addr & 0xff00ff) | (data << 8); + status.wram_addr &= 0x01ffff; +} + +//WMADDH +void sCPU::mmio_w2183(uint8 data) { + status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16); + status.wram_addr &= 0x01ffff; +} + +/***** + * Joypad registers + *****/ + +//JOYSER0 +//7-2 = MDR +//1-0 = Joypad serial data +/***** + * The joypad contains a small bit shifter that has 16 bits. + * Reading from 4016 reads one bit from this buffer, then moves + * the buffer left one, and adds a '1' to the rightmost bit. + * Writing a one to $4016 will fill the buffer with the current + * joypad button states, and lock the bit shifter at position + * zero. All reads will be the first buffer state, or 'B'. + * A zero must be written back to $4016 to unlock the buffer, + * so that reads will increment the bit shifting position. + *****/ +uint8 sCPU::mmio_r4016() { +uint8 r = regs.mdr & 0xfc; + if(status.joypad_strobe_latch == 1) { + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B)); + } else { + switch(status.joypad1_read_pos) { + case 0: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B)); break; + case 1: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y)); break; + case 2: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT)); break; + case 3: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START)); break; + case 4: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP)); break; + case 5: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN)); break; + case 6: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT)); break; + case 7: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT)); break; + case 8: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A)); break; + case 9: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X)); break; + case 10: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L)); break; + case 11: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R)); break; + case 12: break; + case 13: break; + case 14: break; + case 15: break; //bits 12-15 always return 0 + //all subsequent reads return joypad connection status + case 16: r |= 1; break; //joypad connected bit + } + if(++status.joypad1_read_pos > 16)status.joypad1_read_pos = 16; + } + + return r; +} + +//JOYSER1 +//7-5 = MDR +//4-2 = Always 1 (pins are connected to GND) +//1-0 = Joypad serial data +uint8 sCPU::mmio_r4017() { +uint8 r = (regs.mdr & 0xe0) | 0x1c; + if(status.joypad_strobe_latch == 1) { + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B)); + } else { + switch(status.joypad2_read_pos) { + case 0: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B)); break; + case 1: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y)); break; + case 2: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT)); break; + case 3: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START)); break; + case 4: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP)); break; + case 5: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN)); break; + case 6: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT)); break; + case 7: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT)); break; + case 8: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A)); break; + case 9: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X)); break; + case 10: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L)); break; + case 11: r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R)); break; + case 12: break; + case 13: break; + case 14: break; + case 15: break; //bits 12-15 always return 0 + //all subsequent reads return joypad connection status + case 16: r |= 1; break; //joypad connected bit + } + if(++status.joypad2_read_pos > 16)status.joypad2_read_pos = 16; + } + + return r; +} + +//JOY1L +//TODO: handle reads during joypad polling (v=225-227) +uint8 sCPU::mmio_r4218() { +uint8 r = 0x00; + if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A)) << 7; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X)) << 6; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L)) << 5; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R)) << 4; + return r; +} + +//JOY1H +uint8 sCPU::mmio_r4219() { +uint8 r = 0x00; + if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B)) << 7; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y)) << 6; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT)) << 5; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START)) << 4; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP)) << 3; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN)) << 2; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT)) << 1; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT)); + return r; +} + +//JOY2L +uint8 sCPU::mmio_r421a() { +uint8 r = 0x00; + if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A)) << 7; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X)) << 6; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L)) << 5; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R)) << 4; + return r; +} + +//JOY2H +uint8 sCPU::mmio_r421b() { +uint8 r = 0x00; + if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B)) << 7; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y)) << 6; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT)) << 5; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START)) << 4; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP)) << 3; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN)) << 2; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT)) << 1; + r |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT)); + return r; +} + +//JOYSER0 +//bit 0 is shared between JOYSER0 and JOYSER1, therefore +//strobing $4016.d0 affects both controller port latches. +//$4017 bit 0 writes are ignored. +void sCPU::mmio_w4016(uint8 data) { + status.joypad_strobe_latch = bool(data & 1); + + if(status.joypad_strobe_latch == 1) { + snes->poll_input(SNES::DEV_JOYPAD1); + snes->poll_input(SNES::DEV_JOYPAD2); + status.joypad1_read_pos = 0; + status.joypad2_read_pos = 0; + } +} + +/***** + * NMI / IRQ registers + *****/ + +//RDNMI +//7 = NMI acknowledge +//6-4 = MDR +//3-0 = CPU (5a22) version +uint8 sCPU::mmio_r4210() { +uint8 r = (regs.mdr & 0x70); + r |= uint8(!status.nmi_read) << 7; + + if(!nmi_read_pos_match(0) && !nmi_read_pos_match(2)) { + status.nmi_read = 1; + } + + r |= (cpu_version & 0x0f); + return r; +} + +//TIMEUP +//7 = IRQ acknowledge +//6-0 = MDR +uint8 sCPU::mmio_r4211() { +uint8 r = (regs.mdr & 0x7f); + r |= uint8(!status.irq_read) << 7; + + if(!irq_read_pos_match(0) && !irq_read_pos_match(2)) { + status.irq_read = 1; + status.irq_line = 1; + status.irq_transition = 0; + } + + return r; +} + +//HVBJOY +//7 = VBLANK acknowledge +//6 = HBLANK acknowledge +//5-1 = MDR +//0 = JOYPAD acknowledge +uint8 sCPU::mmio_r4212() { +uint8 r = (regs.mdr & 0x3e); +uint16 vs = !overscan() ? 225 : 240; + +//auto joypad polling + if(status.hclock >= vs && status.hclock <= (vs + 2))r |= 0x01; + +//hblank + if(status.hclock <= 2 || status.hclock >= 1096)r |= 0x40; + +//vblank + if(status.vcounter >= vs)r |= 0x80; + + return r; +} + +//NMITIMEN +void sCPU::mmio_w4200(uint8 data) { + status.nmi_enabled = bool(data & 0x80); + status.virq_enabled = bool(data & 0x20); + status.hirq_enabled = bool(data & 0x10); + status.auto_joypad_poll = bool(data & 0x01); + + if(status.nmi_read == 0) { + if(status.nmi_line == 1 && !status.nmi_enabled == 0) { + status.nmi_transition = 1; + } + status.nmi_line = !status.nmi_enabled; + } + + if(status.virq_enabled == false && status.hirq_enabled == false) { + status.irq_line = 1; + status.irq_read = 1; + status.irq_transition = 0; + } + + update_interrupts(); +} + +//HTIMEL +void sCPU::mmio_w4207(uint8 data) { + status.hirq_pos = (status.hirq_pos & 0xff00) | (data); + update_interrupts(); +} + +//HTIMEH +void sCPU::mmio_w4208(uint8 data) { + status.hirq_pos = (status.hirq_pos & 0x00ff) | (data << 8); + update_interrupts(); +} + +//VTIMEL +void sCPU::mmio_w4209(uint8 data) { + status.virq_pos = (status.virq_pos & 0xff00) | (data); + update_interrupts(); +} + +//VTIMEH +void sCPU::mmio_w420a(uint8 data) { + status.virq_pos = (status.virq_pos & 0x00ff) | (data << 8); + update_interrupts(); +} + +/***** + * I/O registers + ****/ + +//RDIO +uint8 sCPU::mmio_r4213() { + return status.pio; +} + +//WRIO +void sCPU::mmio_w4201(uint8 data) { + if((status.pio & 0x80) && !(data & 0x80)) { + r_ppu->latch_counters(); + } + status.pio = data; +} + +/***** + * Math registers (multiplication and division) + *****/ + +//RDDIVL +uint8 sCPU::mmio_r4214() { + return status.r4214; +} + +//RDDIVH +uint8 sCPU::mmio_r4215() { + return status.r4214 >> 8; +} + +//RDMPYL +uint8 sCPU::mmio_r4216() { + return status.r4216; +} + +//RDMPYH +uint8 sCPU::mmio_r4217() { + return status.r4216 >> 8; +} + +//WRMPYA +void sCPU::mmio_w4202(uint8 data) { + status.mul_a = data; +} + +//WRMPYB +void sCPU::mmio_w4203(uint8 data) { + status.mul_b = data; + status.r4216 = status.mul_a * status.mul_b; +} + +//WRDIVL +void sCPU::mmio_w4204(uint8 data) { + status.div_a = (status.div_a & 0xff00) | (data); +} + +//WRDIVH +void sCPU::mmio_w4205(uint8 data) { + status.div_a = (status.div_a & 0x00ff) | (data << 8); +} + +//WRDIVB +void sCPU::mmio_w4206(uint8 data) { + status.div_b = data; + status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff; + status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a; +} + +/***** + * DMA / HDMA registers + *****/ + +//DMAPx +uint8 sCPU::mmio_r43x0(uint8 i) { + return channel[i].dmap; +} + +//BBADx +uint8 sCPU::mmio_r43x1(uint8 i) { + return channel[i].destaddr; +} + +//A1TxL +uint8 sCPU::mmio_r43x2(uint8 i) { + return channel[i].srcaddr; +} + +//A1TxH +uint8 sCPU::mmio_r43x3(uint8 i) { + return channel[i].srcaddr >> 8; +} + +//A1Bx +uint8 sCPU::mmio_r43x4(uint8 i) { + return channel[i].srcbank; +} + +//DASxL +//union { uint16 xfersize; uint16 hdma_iaddr; }; +uint8 sCPU::mmio_r43x5(uint8 i) { + return channel[i].xfersize; +} + +//DASxH +//union { uint16 xfersize; uint16 hdma_iaddr; }; +uint8 sCPU::mmio_r43x6(uint8 i) { + return channel[i].xfersize >> 8; +} + +//DASBx +uint8 sCPU::mmio_r43x7(uint8 i) { + return channel[i].hdma_ibank; +} + +//A2AxL +uint8 sCPU::mmio_r43x8(uint8 i) { + return channel[i].hdma_addr; +} + +//A2AxH +uint8 sCPU::mmio_r43x9(uint8 i) { + return channel[i].hdma_addr >> 8; +} + +//NTRLx +uint8 sCPU::mmio_r43xa(uint8 i) { + return channel[i].hdma_line_counter; +} + +//??? +uint8 sCPU::mmio_r43xb(uint8 i) { + return channel[i].unknown; +} + +//DMAEN +//Note: DMA enable does not disable active HDMA channels +void sCPU::mmio_w420b(uint8 data) { + for(int i = 0; i < 8; i++) { + channel[i].dma_enabled = bool(data & (1 << i)); + } + if(data)dma_run(); //temporary +} + +//HDMAEN +void sCPU::mmio_w420c(uint8 data) { + for(int i = 0; i < 8; i++) { + channel[i].hdma_enabled = bool(data & (1 << i)); + } +} + +//MEMSEL +void sCPU::mmio_w420d(uint8 data) { + r_mem->set_speed(data & 1); +} + +//DMAPx +void sCPU::mmio_w43x0(uint8 i, uint8 data) { + channel[i].dmap = data; + channel[i].direction = bool(data & 0x80); + channel[i].hdma_indirect = bool(data & 0x40); + channel[i].reversexfer = bool(data & 0x10); + channel[i].fixedxfer = bool(data & 0x08); + channel[i].xfermode = data & 7; +} + +//DDBADx +void sCPU::mmio_w43x1(uint8 i, uint8 data) { + channel[i].destaddr = data; +} + +//A1TxL +void sCPU::mmio_w43x2(uint8 i, uint8 data) { + channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | (data); +} + +//A1TxH +void sCPU::mmio_w43x3(uint8 i, uint8 data) { + channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (data << 8); +} + +//A1Bx +void sCPU::mmio_w43x4(uint8 i, uint8 data) { + channel[i].srcbank = data; +} + +//DASxL +//union { uint16 xfersize; uint16 hdma_iaddr; }; +void sCPU::mmio_w43x5(uint8 i, uint8 data) { + channel[i].xfersize = (channel[i].xfersize & 0xff00) | (data); +} + +//DASxH +//union { uint16 xfersize; uint16 hdma_iaddr; }; +void sCPU::mmio_w43x6(uint8 i, uint8 data) { + channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (data << 8); +} + +//DASBx +void sCPU::mmio_w43x7(uint8 i, uint8 data) { + channel[i].hdma_ibank = data; +} + +//A2AxL +void sCPU::mmio_w43x8(uint8 i, uint8 data) { + channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data); +} + +//A2AxH +void sCPU::mmio_w43x9(uint8 i, uint8 data) { + channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (data << 8); +} + +//NTRLx +void sCPU::mmio_w43xa(uint8 i, uint8 data) { + channel[i].hdma_line_counter = data; +} + +//??? +void sCPU::mmio_w43xb(uint8 i, uint8 data) { + channel[i].unknown = data; +} + +/***** + * reset / read / write + *****/ + +void sCPU::mmio_reset() { +//$2181-$2183 + status.wram_addr = 0x000000; + +//$4016-$4017 + status.joypad_strobe_latch = 0; + status.joypad1_read_pos = 0; + status.joypad2_read_pos = 0; + +//$4200 + status.nmi_enabled = false; + status.hirq_enabled = false; + status.virq_enabled = false; + status.auto_joypad_poll = false; + +//$4201 + status.pio = 0xff; + +//$4202-$4203 + status.mul_a = 0xff; + status.mul_b = 0xff; + +//$4204-$4206 + status.div_a = 0xffff; + status.div_b = 0xff; + +//$4207-$420a + status.hirq_pos = 0x01ff; + status.virq_pos = 0x01ff; + +//$4214-$4217 + status.r4214 = 0x0000; + status.r4216 = 0x0000; +} + +uint8 sCPU::mmio_read(uint16 addr) { +//APU + if((addr & 0xffc0) == 0x2140) { //$2140-$217f + #ifdef FAVOR_SPEED + co_return(); + #endif + return r_apu->port_read(addr & 3); + } + +//DMA + if((addr & 0xff80) == 0x4300) { //$4300-$437f + uint i = (addr >> 4) & 7; + switch(addr & 0xf) { + case 0x0: return mmio_r43x0(i); + case 0x1: return mmio_r43x1(i); + case 0x2: return mmio_r43x2(i); + case 0x3: return mmio_r43x3(i); + case 0x4: return mmio_r43x4(i); + case 0x5: return mmio_r43x5(i); + case 0x6: return mmio_r43x6(i); + case 0x7: return mmio_r43x7(i); + case 0x8: return mmio_r43x8(i); + case 0x9: return mmio_r43x9(i); + case 0xa: return mmio_r43xa(i); + case 0xb: return mmio_r43xb(i); + case 0xc: return regs.mdr; //unmapped + case 0xd: return regs.mdr; //unmapped + case 0xe: return regs.mdr; //unmapped + case 0xf: return mmio_r43xb(i); //mirror of $43xb + } + } + + switch(addr) { + case 0x2180: return mmio_r2180(); + case 0x4016: return mmio_r4016(); + case 0x4017: return mmio_r4017(); + case 0x4210: return mmio_r4210(); + case 0x4211: return mmio_r4211(); + case 0x4212: return mmio_r4212(); + case 0x4213: return mmio_r4213(); + case 0x4214: return mmio_r4214(); + case 0x4215: return mmio_r4215(); + case 0x4216: return mmio_r4216(); + case 0x4217: return mmio_r4217(); + case 0x4218: return mmio_r4218(); + case 0x4219: return mmio_r4219(); + case 0x421a: return mmio_r421a(); + case 0x421b: return mmio_r421b(); + case 0x421c: return 0x00; + case 0x421d: return 0x00; + case 0x421e: return 0x00; + case 0x421f: return 0x00; + } + + return regs.mdr; +} + +void sCPU::mmio_write(uint16 addr, uint8 data) { +//APU + if((addr & 0xffc0) == 0x2140) { //$2140-$217f + #ifdef FAVOR_SPEED + co_return(); + #endif + port_write(addr & 3, data); + return; + } + +//DMA + if((addr & 0xff80) == 0x4300) { //$4300-$437f + uint i = (addr >> 4) & 7; + switch(addr & 0xf) { + case 0x0: mmio_w43x0(i, data); return; + case 0x1: mmio_w43x1(i, data); return; + case 0x2: mmio_w43x2(i, data); return; + case 0x3: mmio_w43x3(i, data); return; + case 0x4: mmio_w43x4(i, data); return; + case 0x5: mmio_w43x5(i, data); return; + case 0x6: mmio_w43x6(i, data); return; + case 0x7: mmio_w43x7(i, data); return; + case 0x8: mmio_w43x8(i, data); return; + case 0x9: mmio_w43x9(i, data); return; + case 0xa: mmio_w43xa(i, data); return; + case 0xb: mmio_w43xb(i, data); return; + case 0xc: return; //unmapped + case 0xd: return; //unmapped + case 0xe: return; //unmapped + case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb + } + } + + switch(addr) { + case 0x2180: mmio_w2180(data); return; + case 0x2181: mmio_w2181(data); return; + case 0x2182: mmio_w2182(data); return; + case 0x2183: mmio_w2183(data); return; + case 0x4016: mmio_w4016(data); return; + case 0x4017: return; //unmapped + case 0x4200: mmio_w4200(data); return; + case 0x4201: mmio_w4201(data); return; + case 0x4202: mmio_w4202(data); return; + case 0x4203: mmio_w4203(data); return; + case 0x4204: mmio_w4204(data); return; + case 0x4205: mmio_w4205(data); return; + case 0x4206: mmio_w4206(data); return; + case 0x4207: mmio_w4207(data); return; + case 0x4208: mmio_w4208(data); return; + case 0x4209: mmio_w4209(data); return; + case 0x420a: mmio_w420a(data); return; + case 0x420b: mmio_w420b(data); return; + case 0x420c: mmio_w420c(data); return; + case 0x420d: mmio_w420d(data); return; + } +} diff --git a/src/cpu/scpu/mmio/mmio.h b/src/cpu/scpu/mmio/mmio.h new file mode 100644 index 00000000..5de8a113 --- /dev/null +++ b/src/cpu/scpu/mmio/mmio.h @@ -0,0 +1,65 @@ + void mmio_reset(); + uint8 mmio_read (uint16 addr); + void mmio_write(uint16 addr, uint8 data); + + uint8 pio_status(); + + uint8 mmio_r2180(); + uint8 mmio_r4016(); + uint8 mmio_r4017(); + uint8 mmio_r4210(); + uint8 mmio_r4211(); + uint8 mmio_r4212(); + uint8 mmio_r4213(); + uint8 mmio_r4214(); + uint8 mmio_r4215(); + uint8 mmio_r4216(); + uint8 mmio_r4217(); + uint8 mmio_r4218(); + uint8 mmio_r4219(); + uint8 mmio_r421a(); + uint8 mmio_r421b(); + uint8 mmio_r43x0(uint8 i); + uint8 mmio_r43x1(uint8 i); + uint8 mmio_r43x2(uint8 i); + uint8 mmio_r43x3(uint8 i); + uint8 mmio_r43x4(uint8 i); + uint8 mmio_r43x5(uint8 i); + uint8 mmio_r43x6(uint8 i); + uint8 mmio_r43x7(uint8 i); + uint8 mmio_r43x8(uint8 i); + uint8 mmio_r43x9(uint8 i); + uint8 mmio_r43xa(uint8 i); + uint8 mmio_r43xb(uint8 i); + + void mmio_w2180(uint8 data); + void mmio_w2181(uint8 data); + void mmio_w2182(uint8 data); + void mmio_w2183(uint8 data); + void mmio_w4016(uint8 data); + void mmio_w4200(uint8 data); + void mmio_w4201(uint8 data); + void mmio_w4202(uint8 data); + void mmio_w4203(uint8 data); + void mmio_w4204(uint8 data); + void mmio_w4205(uint8 data); + void mmio_w4206(uint8 data); + void mmio_w4207(uint8 data); + void mmio_w4208(uint8 data); + void mmio_w4209(uint8 data); + void mmio_w420a(uint8 data); + void mmio_w420b(uint8 data); + void mmio_w420c(uint8 data); + void mmio_w420d(uint8 data); + void mmio_w43x0(uint8 i, uint8 data); + void mmio_w43x1(uint8 i, uint8 data); + void mmio_w43x2(uint8 i, uint8 data); + void mmio_w43x3(uint8 i, uint8 data); + void mmio_w43x4(uint8 i, uint8 data); + void mmio_w43x5(uint8 i, uint8 data); + void mmio_w43x6(uint8 i, uint8 data); + void mmio_w43x7(uint8 i, uint8 data); + void mmio_w43x8(uint8 i, uint8 data); + void mmio_w43x9(uint8 i, uint8 data); + void mmio_w43xa(uint8 i, uint8 data); + void mmio_w43xb(uint8 i, uint8 data); diff --git a/src/cpu/scpu/scpu.cpp b/src/cpu/scpu/scpu.cpp new file mode 100644 index 00000000..0f4cedcf --- /dev/null +++ b/src/cpu/scpu/scpu.cpp @@ -0,0 +1,64 @@ +#include "../../base.h" + +#include "core/core.cpp" +#include "dma/dma.cpp" +#include "memory/memory.cpp" +#include "mmio/mmio.cpp" +#include "timing/timing.cpp" + +void scpu_entry_point() { + r_cpu->main(); +} + +void sCPU::run() { + co_call(thread); +} + +void sCPU::power() { + status.region = bool(snes->region()); + + regs.a = regs.x = regs.y = 0x0000; + regs.s = 0x01ff; + reset(); +} + +void sCPU::reset() { + if(thread)co_delete(thread); + thread = co_create(scpu_entry_point, 65536); + + regs.pc.d = 0x000000; + regs.pc.l = r_mem->read(0xfffc); + regs.pc.h = r_mem->read(0xfffd); + +//some registers are not fully reset by SNES + regs.x.h = 0x00; + regs.y.h = 0x00; + regs.s.h = 0x01; + regs.d = 0x0000; + regs.db = 0x00; + regs.p = 0x34; + regs.e = 1; + regs.mdr = 0x00; + + event.wai = false; + event.irq = false; + event.irq_vector = 0xfffc; //reset vector address + + mmio_reset(); + dma_reset(); + timing_reset(); + + apu_port[0] = 0x00; + apu_port[1] = 0x00; + apu_port[2] = 0x00; + apu_port[3] = 0x00; +} + +sCPU::sCPU() { +//#include "core/optable.cpp" + thread = 0; +} + +sCPU::~sCPU() { + if(thread)co_delete(thread); +} diff --git a/src/cpu/scpu/scpu.h b/src/cpu/scpu/scpu.h new file mode 100644 index 00000000..cf00c438 --- /dev/null +++ b/src/cpu/scpu/scpu.h @@ -0,0 +1,84 @@ +class sCPU : public CPU { +public: +#include "core/core.h" +#include "dma/dma.h" +#include "memory/memory.h" +#include "mmio/mmio.h" +#include "timing/timing.h" + +thread_t thread; + +struct { + bool wai; + bool irq; + uint16 irq_vector; +} event; + +struct { +//core + uint8 opcode; + bool in_opcode; + + uint clock_count; + uint clocks_executed; + +//timing + bool region; + uint16 region_scanlines; + uint16 vcounter, hcounter, hclock; + bool interlace, interlace_field; + bool overscan; + uint16 field_lines, line_clocks; + + bool line_rendered; + bool dram_refreshed; + bool hdmainit_triggered; + bool hdma_triggered; + + int16 nmi_read_pos, nmi_line_pos; + bool nmi_read, nmi_line, nmi_transition; + bool nmi_pending; + + int16 irq_read_pos, irq_line_pos; + bool irq_read, irq_line, irq_transition; + bool irq_pending; + +//mmio + +//$2181-$2183 + uint32 wram_addr; + +//$4016-$4017 + bool joypad_strobe_latch; + uint8 joypad1_read_pos, joypad2_read_pos; + +//$4200 + bool nmi_enabled; + bool hirq_enabled, virq_enabled; + bool auto_joypad_poll; + +//$4201 + uint8 pio; + +//$4202-$4203 + uint8 mul_a, mul_b; + +//$4204-$4206 + uint16 div_a; + uint8 div_b; + +//$4207-$420a + uint16 hirq_pos, virq_pos; + +//$4214-$4217 + uint16 r4214; + uint16 r4216; +} status; + + void run(); + void power(); + void reset(); + + sCPU(); + ~sCPU(); +}; diff --git a/src/cpu/scpu/timing/irq.cpp b/src/cpu/scpu/timing/irq.cpp new file mode 100644 index 00000000..187bf015 --- /dev/null +++ b/src/cpu/scpu/timing/irq.cpp @@ -0,0 +1,162 @@ +void sCPU::update_interrupts() { + if(status.vcounter == (!overscan() ? 225 : 240)) { + status.nmi_read_pos = 2; + status.nmi_line_pos = 6; + } else { + status.nmi_read_pos = -64; + status.nmi_line_pos = -64; + } + + if(irq_pos_valid() == false) { + status.irq_read_pos = -64; + status.irq_line_pos = -64; + return; + } + +uint vpos = status.virq_pos; +uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0; + hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10; + if(hpos >= status.line_clocks) { + hpos -= status.line_clocks; + if(++vpos >= status.field_lines) { + vpos = 0; + } + } + + if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) { + status.irq_read_pos = hpos; + } else { + status.irq_read_pos = -64; + } + + hpos += 4; + if(hpos >= status.line_clocks) { + hpos -= status.line_clocks; + if(++vpos >= status.field_lines) { + vpos = 0; + } + } + + if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) { + status.irq_line_pos = hpos; + } else { + status.irq_line_pos = -64; + } +} + +void sCPU::poll_interrupts(int clocks) { +int16 start, end; + if(status.hclock == 0) { + start = -1; + end = clocks; + } else { + start = status.hclock; + end = status.hclock + clocks; + } + +//NMI read test + if(start < status.nmi_read_pos && status.nmi_read_pos <= end) { + //nmi_read lowers even when NMI interrupts are disabled via $4200.d7 + status.nmi_read = 0; + } + +//NMI line test + if(start < status.nmi_line_pos && status.nmi_line_pos <= end) { + if(status.nmi_enabled == true) { + if(status.nmi_line == 1) { + status.nmi_transition = 1; + } + status.nmi_line = 0; + } + } + +//IRQ read test + if(start < status.irq_read_pos && status.irq_read_pos <= end) { + if(status.virq_enabled == true || status.hirq_enabled == true) { + status.irq_read = 0; + } + } + +//IRQ line test + if(start < status.irq_line_pos && status.irq_line_pos <= end) { + if(status.virq_enabled == true || status.hirq_enabled == true) { + status.irq_line = 0; + status.irq_transition = 1; + } + } +} + +bool sCPU::nmi_read_pos_match(uint offset) { +uint16 v = !overscan() ? 225 : 240; +uint16 h = 2 + offset; + return (status.vcounter == v && status.hclock == h); +} + +bool sCPU::irq_read_pos_match(uint offset) { + if(irq_pos_valid() == false)return false; + +uint vpos = status.virq_pos; +uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0; + hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10; + hpos += offset; + if(hpos >= status.line_clocks) { + hpos -= status.line_clocks; + if(++vpos >= status.field_lines) { + vpos = 0; + } + } + + if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) { + return (status.hclock == hpos); + } + + return false; +} + +bool sCPU::irq_pos_valid() { +uint vpos = status.virq_pos; +uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0; +uint vlimit = region_scanlines() >> 1; +//positions that can never be latched +//vlimit = 262/NTSC, 312/PAL +//PAL results are unverified on hardware + if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)return false; + if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)return false; + if(vpos == vlimit && interlace() == false)return false; + if(vpos == vlimit && hpos == 339)return false; + if(vpos > vlimit)return false; + if(hpos > 339)return false; + + return true; +} + +bool sCPU::nmi_test() { + if(status.nmi_transition == 0)return false; + + status.nmi_transition = 0; + event.wai = false; + return true; +} + +bool sCPU::irq_test() { + if(status.irq_transition == 1)goto irq_trigger; + + if(status.irq_read == 0) { + if(status.irq_line == 1 && (irq_read_pos_match(0) || irq_read_pos_match(2))) { + return false; + } + goto irq_trigger; + } + + if(status.irq_line == 0) { + status.irq_line = 1; + goto irq_trigger; + } + + return false; + +irq_trigger: + status.irq_transition = 0; + event.wai = false; + return (regs.p.i) ? false : true; +} diff --git a/src/cpu/scpu/timing/timing.cpp b/src/cpu/scpu/timing/timing.cpp new file mode 100644 index 00000000..f2b43980 --- /dev/null +++ b/src/cpu/scpu/timing/timing.cpp @@ -0,0 +1,206 @@ +#define ntsc_color_burst_phase_shift_scanline() \ + (status.region == SNES::NTSC && status.vcounter == 240 && \ + status.interlace == false && status.interlace_field == 1) + +#include "irq.cpp" + +uint16 sCPU::vcounter() { return status.vcounter; } +uint16 sCPU::hcycles() { return status.hclock; } + +bool sCPU::interlace() { return status.interlace; } +bool sCPU::interlace_field() { return status.interlace_field; } +bool sCPU::overscan() { return status.overscan; } +uint16 sCPU::region_scanlines() { return status.region_scanlines; } + +void sCPU::set_interlace(bool r) { status.interlace = r; update_interrupts(); } +void sCPU::set_overscan (bool r) { status.overscan = r; update_interrupts(); } + +/***** + * One PPU dot = 4 CPU clocks + * + * PPU dots 323 and 327 are 6 CPU clocks long. + * This does not apply to NTSC non-interlace scanline 240 on odd fields. This is + * because the PPU skips one dot to alter the color burst phase of the video signal. + * + * Dot 323 range = { 1292, 1294, 1296 } + * Dot 327 range = { 1310, 1312, 1314 } + *****/ +uint16 sCPU::hcounter() { + if(ntsc_color_burst_phase_shift_scanline() == true) { + return (status.hclock >> 2); + } + return (status.hclock - ((status.hclock > 1292) << 1) - ((status.hclock > 1310) << 1)) >> 2; +} + +void sCPU::add_clocks(uint clocks) { + status.clocks_executed += clocks; + poll_interrupts(clocks); + + if(status.hclock + clocks >= status.line_clocks) { + clocks = (status.hclock + clocks) - status.line_clocks; + status.hclock = 0; + scanline(); + poll_interrupts(clocks); + } + + status.hclock += clocks; + + if(status.dram_refreshed == false) { + if(status.hclock >= 530) { + status.dram_refreshed = true; + add_clocks(40); + return; + } + } +} + +void sCPU::scanline() { + if(++status.vcounter >= status.field_lines) { + frame(); + } + + status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360; + +//dram refresh occurs once every scanline + status.dram_refreshed = false; + +//hdma triggers once every visible scanline + status.line_rendered = + status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true; + + r_ppu->scanline(); + snes->scanline(); + + update_interrupts(); + + if(status.vcounter == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) { + snes->poll_input(SNES::DEV_JOYPAD1); + snes->poll_input(SNES::DEV_JOYPAD2); + //When the SNES auto-polls the joypads, it writes 1, then 0 to + //$4016, then reads from each 16 times to get the joypad state + //information. As a result, the joypad read positions are set + //to 16 after such a poll. Position 16 is the controller + //connected status bit. + status.joypad1_read_pos = 16; + status.joypad2_read_pos = 16; + } +} + +void sCPU::frame() { + status.nmi_read = 1; + status.nmi_line = 1; + status.nmi_transition = 0; + + status.vcounter = 0; + status.interlace_field ^= 1; + status.field_lines = (status.region_scanlines >> 1); +//interlaced even fields have one extra scanline +//(263+262=525 NTSC, 313+312=625 PAL) + if(status.interlace == true && status.interlace_field == 0)status.field_lines++; + status.hdmainit_triggered = false; + + r_ppu->frame(); + snes->frame(); +} + +/***** + * opcode_edge() + *****/ +void sCPU::opcode_edge() { +#ifdef FAVOR_SPEED + co_return(); +#endif + if(status.line_rendered == false) { + if(status.hclock >= 128) { + status.line_rendered = true; + r_ppu->render_scanline(); + } + } +} + +/***** + * cycle_edge() + * + * Used to test for HDMA, which can trigger on the edge of every opcode cycle. + *****/ +void sCPU::cycle_edge() { + if(status.hdmainit_triggered == false) { + if(status.hclock >= 12 || status.vcounter) { + status.hdmainit_triggered = true; + hdma_init(); + } + } + + if(status.hdma_triggered == false) { + if(status.hclock >= 1106) { + status.hdma_triggered = true; + hdma_run(); + } + } +} + +/***** + * last_cycle() + * + * Used to test for NMI/IRQ, which can trigger on the edge of every opcode. + * Test one cycle early to simulate two-stage pipeline of x816 CPU. + *****/ +void sCPU::last_cycle() { + status.nmi_pending |= nmi_test(); + status.irq_pending |= irq_test(); + + event.irq = (status.nmi_pending || status.irq_pending); +} + +/***** + * clocks_executed() + * + * Return number of clocks executed since last call to this function. + * Used by class SNES to control CPU<>APU synchronization. + *****/ +uint32 sCPU::clocks_executed() { +uint32 r = status.clocks_executed; + status.clocks_executed = 0; + return r; +} + +void sCPU::timing_reset() { + status.clock_count = 0; + status.clocks_executed = 0; + + status.vcounter = 0; + status.hcounter = 0; + status.hclock = 0; + + status.interlace = 0; + status.interlace_field = 0; + status.overscan = false; + status.region_scanlines = (status.region == SNES::NTSC) ? 525 : 625; + + status.field_lines = status.region_scanlines >> 1; + status.line_clocks = 1364; + + status.line_rendered = false; + status.dram_refreshed = false; + status.hdmainit_triggered = false; + status.hdma_triggered = false; + + status.nmi_read = 1; + status.nmi_line = 1; + status.nmi_transition = 0; + status.nmi_pending = false; + + status.irq_read = 1; + status.irq_line = 1; + status.irq_transition = 0; + status.irq_pending = false; + + update_interrupts(); + +//initial latch values for $213c/$213d +//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137] +//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137] + add_clocks(186); +} + +#undef ntsc_color_burst_phase_shift_scanline diff --git a/src/cpu/scpu/timing/timing.h b/src/cpu/scpu/timing/timing.h new file mode 100644 index 00000000..4cd2d322 --- /dev/null +++ b/src/cpu/scpu/timing/timing.h @@ -0,0 +1,30 @@ + uint16 vcounter(); + uint16 hcounter(); + uint16 hcycles(); + + bool interlace(); + bool interlace_field(); + bool overscan(); + uint16 region_scanlines(); + + void set_interlace(bool r); + void set_overscan(bool r); + + void add_clocks(uint clocks); + void scanline(); + void frame(); + + void opcode_edge(); + void cycle_edge(); + void last_cycle(); + uint32 clocks_executed(); + void timing_reset(); + +//irq.cpp + void update_interrupts(); + void poll_interrupts(int clocks); + bool nmi_read_pos_match(uint offset); + bool irq_read_pos_match(uint offset); + bool irq_pos_valid(); + bool nmi_test(); + bool irq_test(); diff --git a/src/dsp/bdsp/bdsp.cpp b/src/dsp/bdsp/bdsp.cpp index a6a546a8..2a0d1c4e 100644 --- a/src/dsp/bdsp/bdsp.cpp +++ b/src/dsp/bdsp/bdsp.cpp @@ -19,143 +19,132 @@ void bDSP::writew(uint16 addr, uint16 data) { } uint8 bDSP::read(uint8 addr) { -int i, v, n; addr &= 127; - v = addr >> 4; - n = addr & 15; +int v = addr >> 4; +int n = addr & 15; switch(addr) { - case 0x00:case 0x10:case 0x20:case 0x30: - case 0x40:case 0x50:case 0x60:case 0x70: + case 0x00: case 0x10: case 0x20: case 0x30: + case 0x40: case 0x50: case 0x60: case 0x70: return voice[v].VOLL; - case 0x01:case 0x11:case 0x21:case 0x31: - case 0x41:case 0x51:case 0x61:case 0x71: + case 0x01: case 0x11: case 0x21: case 0x31: + case 0x41: case 0x51: case 0x61: case 0x71: return voice[v].VOLR; - case 0x02:case 0x12:case 0x22:case 0x32: - case 0x42:case 0x52:case 0x62:case 0x72: - return voice[v].PITCH >> 8; - case 0x03:case 0x13:case 0x23:case 0x33: - case 0x43:case 0x53:case 0x63:case 0x73: + case 0x02: case 0x12: case 0x22: case 0x32: + case 0x42: case 0x52: case 0x62: case 0x72: return voice[v].PITCH; - case 0x04:case 0x14:case 0x24:case 0x34: - case 0x44:case 0x54:case 0x64:case 0x74: + case 0x03: case 0x13: case 0x23: case 0x33: + case 0x43: case 0x53: case 0x63: case 0x73: + return voice[v].PITCH >> 8; + case 0x04: case 0x14: case 0x24: case 0x34: + case 0x44: case 0x54: case 0x64: case 0x74: return voice[v].SRCN; - case 0x05:case 0x15:case 0x25:case 0x35: - case 0x45:case 0x55:case 0x65:case 0x75: + case 0x05: case 0x15: case 0x25: case 0x35: + case 0x45: case 0x55: case 0x65: case 0x75: return voice[v].ADSR1; - case 0x06:case 0x16:case 0x26:case 0x36: - case 0x46:case 0x56:case 0x66:case 0x76: + case 0x06: case 0x16: case 0x26: case 0x36: + case 0x46: case 0x56: case 0x66: case 0x76: return voice[v].ADSR2; - case 0x07:case 0x17:case 0x27:case 0x37: - case 0x47:case 0x57:case 0x67:case 0x77: + case 0x07: case 0x17: case 0x27: case 0x37: + case 0x47: case 0x57: case 0x67: case 0x77: return voice[v].GAIN; - case 0x08:case 0x18:case 0x28:case 0x38: - case 0x48:case 0x58:case 0x68:case 0x78: + case 0x08: case 0x18: case 0x28: case 0x38: + case 0x48: case 0x58: case 0x68: case 0x78: return voice[v].ENVX; - case 0x09:case 0x19:case 0x29:case 0x39: - case 0x49:case 0x59:case 0x69:case 0x79: + case 0x09: case 0x19: case 0x29: case 0x39: + case 0x49: case 0x59: case 0x69: case 0x79: return voice[v].OUTX; - case 0x0f:case 0x1f:case 0x2f:case 0x3f: - case 0x4f:case 0x5f:case 0x6f:case 0x7f: + case 0x0f: case 0x1f: case 0x2f: case 0x3f: + case 0x4f: case 0x5f: case 0x6f: case 0x7f: return status.FIR[v]; - case 0x0c:return status.MVOLL; - case 0x1c:return status.MVOLR; - case 0x2c:return status.EVOLL; - case 0x3c:return status.EVOLR; - case 0x4c:return status.KON; - case 0x5c:return status.KOFF; - case 0x6c:return status.FLG; - case 0x7c:return status.ENDX; + case 0x0c: return status.MVOLL; + case 0x1c: return status.MVOLR; + case 0x2c: return status.EVOLL; + case 0x3c: return status.EVOLR; + case 0x4c: return status.KON; + case 0x5c: return status.KOFF; + case 0x6c: return status.FLG; + case 0x7c: return status.ENDX; - case 0x0d:return status.EFB; - case 0x2d:return status.PMON; - case 0x3d:return status.NON; - case 0x4d:return status.EON; - case 0x5d:return status.DIR; - case 0x6d:return status.ESA; - case 0x7d:return status.EDL; + case 0x0d: return status.EFB; + case 0x2d: return status.PMON; + case 0x3d: return status.NON; + case 0x4d: return status.EON; + case 0x5d: return status.DIR; + case 0x6d: return status.ESA; + case 0x7d: return status.EDL; } return dspram[addr]; } void bDSP::write(uint8 addr, uint8 data) { -int i, v, n; //0x80-0xff is a read-only mirror of 0x00-0x7f if(addr & 0x80)return; - v = addr >> 4; - n = addr & 15; +int v = addr >> 4; +int n = addr & 15; switch(addr) { - case 0x00:case 0x10:case 0x20:case 0x30: - case 0x40:case 0x50:case 0x60:case 0x70: + case 0x00: case 0x10: case 0x20: case 0x30: + case 0x40: case 0x50: case 0x60: case 0x70: voice[v].VOLL = data; break; - case 0x01:case 0x11:case 0x21:case 0x31: - case 0x41:case 0x51:case 0x61:case 0x71: + case 0x01: case 0x11: case 0x21: case 0x31: + case 0x41: case 0x51: case 0x61: case 0x71: voice[v].VOLR = data; break; - case 0x02:case 0x12:case 0x22:case 0x32: - case 0x42:case 0x52:case 0x62:case 0x72: + case 0x02: case 0x12: case 0x22: case 0x32: + case 0x42: case 0x52: case 0x62: case 0x72: voice[v].PITCH &= 0xff00; voice[v].PITCH |= data; break; - case 0x03:case 0x13:case 0x23:case 0x33: - case 0x43:case 0x53:case 0x63:case 0x73: + case 0x03: case 0x13: case 0x23: case 0x33: + case 0x43: case 0x53: case 0x63: case 0x73: voice[v].PITCH &= 0x00ff; voice[v].PITCH |= data << 8; break; - case 0x04:case 0x14:case 0x24:case 0x34: - case 0x44:case 0x54:case 0x64:case 0x74: + case 0x04: case 0x14: case 0x24: case 0x34: + case 0x44: case 0x54: case 0x64: case 0x74: voice[v].SRCN = data; break; - //below is anomie's code, but TRAC says writing SRCN doesn't affect anything until a - //BRR-with-end block is encountered, where it loads the loop address from the new SRCN - //anomie's code breaks MK2 sound completely... - if(voice[v].SRCN != data) { - voice[v].SRCN = data; - voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped) ? 2 : 0)); - voice[v].brr_index = 0; - } - break; - case 0x05:case 0x15:case 0x25:case 0x35: - case 0x45:case 0x55:case 0x65:case 0x75: + case 0x05: case 0x15: case 0x25: case 0x35: + case 0x45: case 0x55: case 0x65: case 0x75: voice[v].ADSR1 = data; voice[v].AdjustEnvelope(); break; - case 0x06:case 0x16:case 0x26:case 0x36: - case 0x46:case 0x56:case 0x66:case 0x76: + case 0x06: case 0x16: case 0x26: case 0x36: + case 0x46: case 0x56: case 0x66: case 0x76: voice[v].ADSR2 = data; //sustain_level = 0-7, 7 is a special case handled by ATTACK envx mode voice[v].env_sustain = (voice[v].ADSR_sus_level() + 1) << 8; voice[v].AdjustEnvelope(); break; - case 0x07:case 0x17:case 0x27:case 0x37: - case 0x47:case 0x57:case 0x67:case 0x77: + case 0x07: case 0x17: case 0x27: case 0x37: + case 0x47: case 0x57: case 0x67: case 0x77: voice[v].GAIN = data; voice[v].AdjustEnvelope(); break; - case 0x08:case 0x18:case 0x28:case 0x38: - case 0x48:case 0x58:case 0x68:case 0x78: + case 0x08: case 0x18: case 0x28: case 0x38: + case 0x48: case 0x58: case 0x68: case 0x78: voice[v].ENVX = data; break; - case 0x09:case 0x19:case 0x29:case 0x39: - case 0x49:case 0x59:case 0x69:case 0x79: + case 0x09: case 0x19: case 0x29: case 0x39: + case 0x49: case 0x59: case 0x69: case 0x79: voice[v].OUTX = data; break; - case 0x0f:case 0x1f:case 0x2f:case 0x3f: - case 0x4f:case 0x5f:case 0x6f:case 0x7f: + case 0x0f: case 0x1f: case 0x2f: case 0x3f: + case 0x4f: case 0x5f: case 0x6f: case 0x7f: status.FIR[v] = data; break; - case 0x0c:status.MVOLL = data;break; - case 0x1c:status.MVOLR = data;break; - case 0x2c:status.EVOLL = data;break; - case 0x3c:status.EVOLR = data;break; + case 0x0c: status.MVOLL = data; break; + case 0x1c: status.MVOLR = data; break; + case 0x2c: status.EVOLL = data; break; + case 0x3c: status.EVOLR = data; break; case 0x4c: status.KON = data; @@ -179,12 +168,12 @@ int i, v, n; status.ENDX = 0; break; - case 0x0d:status.EFB = data;break; - case 0x2d:status.PMON = data;break; - case 0x3d:status.NON = data;break; - case 0x4d:status.EON = data;break; - case 0x5d:status.DIR = data;break; - case 0x6d:status.ESA = data;break; + case 0x0d: status.EFB = data; break; + case 0x2d: status.PMON = data; break; + case 0x3d: status.NON = data; break; + case 0x4d: status.EON = data; break; + case 0x5d: status.DIR = data; break; + case 0x6d: status.ESA = data; break; case 0x7d: status.EDL = data; @@ -196,11 +185,10 @@ int i, v, n; } void bDSP::power() { -int v; spcram = r_apu->get_spcram_handle(); memset(dspram, 0x00, 128); - for(v=0;v<8;v++) { + for(int v = 0; v < 8; v++) { voice[v].VOLL = 0; voice[v].VOLR = 0; voice[v].PITCH = 0; @@ -230,7 +218,6 @@ int v; } void bDSP::reset() { -int v; status.KON = 0x00; status.KOFF = 0x00; status.FLG |= 0xe0; @@ -245,7 +232,7 @@ int v; status.echo_index = 0; status.fir_buffer_index = 0; - for(v=0;v<8;v++) { + for(int v = 0; v < 8; v++) { voice[v].ENVX = 0; voice[v].OUTX = 0; @@ -273,28 +260,7 @@ int v; dsp_counter = 0; } -int32 bDSP::clamp(int32 bits, int32 x) { -int32 b = 1 << (bits - 1); - if(x > (b - 1)) { - return (b - 1); - } else if(x < -b) { - return -b; - } else { - return x; - } -} - -int32 bDSP::clip(int32 bits, int32 x) { -int32 b = 1 << (bits - 1); - if(x & b) { - return x | ~(b - 1); - } else { - return x & (b - 1); - } -} - uint32 bDSP::run() { -int v, d; uint8 pmon; int32 sample; int32 msamplel, msampler; @@ -302,10 +268,8 @@ int32 esamplel, esampler; int32 fir_samplel, fir_sampler; pmon = status.PMON & ~status.NON & ~1; -//if(!(dsp_counter++ & 1) && status.key_flag) { -//TRAC believes KON/KOFF is polled every sample. further testing is needed - if(status.key_flag) { - for(v=0;v<8;v++) { + if(!(dsp_counter++ & 1) && status.key_flag) { + for(int v = 0; v < 8; v++) { uint8 mask = 1 << v; if(status.soft_reset()) { if(voice[v].env_state != SILENCE) { @@ -318,7 +282,6 @@ int32 fir_samplel, fir_sampler; voice[v].AdjustEnvelope(); } } else if(status.kon & mask) { - //new KON code status.ENDX &= ~mask; status.kon &= ~mask; @@ -334,9 +297,6 @@ int32 fir_samplel, fir_sampler; voice[v].AdjustEnvelope(); } } -//old KON code, breaks sound effects in DL / SFA2 -// status.ENDX &= ~status.kon; -// status.kon = 0; status.key_flag = false; } @@ -351,7 +311,7 @@ int32 fir_samplel, fir_sampler; msamplel = msampler = 0; esamplel = esampler = 0; - for(v=0;v<8;v++) { + for(int v = 0; v < 8; v++) { if(voice[v].brr_index < -1) { voice[v].brr_index++; voice[v].OUTX = voice[v].outx = 0; @@ -380,11 +340,6 @@ int32 fir_samplel, fir_sampler; if(voice[v].brr_index == 0) { voice[v].brr_header = readb(voice[v].brr_ptr); -//moving status.ENDX bit set into == BRR_END condition per DMV27 - //if(voice[v].brr_header_flags() & BRR_END) { - // status.ENDX |= (1 << v); - //} - if(voice[v].brr_header_flags() == BRR_END) { status.ENDX |= (1 << v); voice[v].env_state = SILENCE; @@ -396,9 +351,9 @@ int32 fir_samplel, fir_sampler; if(voice[v].env_state != SILENCE) { sample = readb(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1)); if(voice[v].brr_index & 1) { - sample = clip(4, sample); + sample = sclip<4>(sample); } else { - sample = clip(4, sample >> 4); + sample = sclip<4>(sample >> 4); } if(voice[v].brr_header_shift() <= 12) { @@ -423,7 +378,7 @@ int32 fir_samplel, fir_sampler; break; } - S(0) = sample = clip(15, clamp(16, sample)); + S(0) = sample = sclip<15>(sclamp<16>(sample)); } else { S(0) = sample = 0; } @@ -431,7 +386,6 @@ int32 fir_samplel, fir_sampler; if(++voice[v].brr_index > 15) { voice[v].brr_index = 0; if(voice[v].brr_header_flags() & BRR_END) { - //below condition added by DMV27 if(voice[v].brr_header_flags() & BRR_LOOP) { status.ENDX |= (1 << v); } @@ -502,7 +456,7 @@ int32 fir_samplel, fir_sampler; if(voice[v].envx >= 0x7ff) { voice[v].envx = 0x7ff; - //attack raises to max. envx, if sustain is also set to max. envx, skip decay phase + //attack raises to max envx. if sustain is also set to max envx, skip decay phase voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY); voice[v].AdjustEnvelope(); } @@ -521,15 +475,15 @@ int32 fir_samplel, fir_sampler; //gaussian interpolation / noise if(status.NON & (1 << v)) { - sample = clip(15, status.noise_sample); + sample = sclip<15>(status.noise_sample); } else { - d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1 + int32 d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1 sample = ((GaussTable[ -1-d] * S(-3)) >> 11); sample += ((GaussTable[255-d] * S(-2)) >> 11); sample += ((GaussTable[512+d] * S(-1)) >> 11); - sample = clip (15, sample); + sample = sclip <15>(sample); sample += ((GaussTable[256+d] * S( 0)) >> 11); - sample = clamp(15, sample); + sample = sclamp<15>(sample); } #undef S @@ -579,8 +533,8 @@ int32 fir_samplel, fir_sampler; esamplel += (fir_samplel * status.EFB) >> 14; esampler += (fir_sampler * status.EFB) >> 14; - esamplel = clamp(16, esamplel); - esampler = clamp(16, esampler); + esamplel = sclamp<16>(esamplel); + esampler = sclamp<16>(esampler); writew((status.ESA << 8) + status.echo_index, esamplel); writew((status.ESA << 8) + status.echo_index + 2, esampler); @@ -600,11 +554,11 @@ int32 fir_samplel, fir_sampler; msamplel += (fir_samplel * status.EVOLL) >> 14; msampler += (fir_sampler * status.EVOLR) >> 14; - msamplel = clamp(16, msamplel); - msampler = clamp(16, msampler); + msamplel = sclamp<16>(msamplel); + msampler = sclamp<16>(msampler); } - return (uint32)(((uint16)msamplel) | ((uint16)msampler << 16)); + return uint32( uint16(msamplel) | (uint16(msampler) << 16) ); } bDSP::bDSP() {} diff --git a/src/dsp/bdsp/bdsp.h b/src/dsp/bdsp/bdsp.h index bc07632a..3570827b 100644 --- a/src/dsp/bdsp/bdsp.h +++ b/src/dsp/bdsp/bdsp.h @@ -5,10 +5,7 @@ uint8 *spcram; uint32 dsp_counter; -enum { - BRR_END = 1, - BRR_LOOP = 2 -}; +enum { BRR_END = 1, BRR_LOOP = 2 }; uint8 readb (uint16 addr); uint16 readw (uint16 addr); @@ -74,9 +71,9 @@ struct Status { uint8 fir_buffer_index; //functions - bool soft_reset() { return !!(FLG & 0x80); } - bool mute() { return !!(FLG & 0x40); } - bool echo_write() { return !(FLG & 0x20); } + bool soft_reset() { return bool(FLG & 0x80); } + bool mute() { return bool(FLG & 0x40); } + bool echo_write() { return !(FLG & 0x20); } } status; struct Voice { @@ -116,7 +113,7 @@ struct Voice { uint8 brr_header_filter() { return (brr_header >> 2) & 3; } uint8 brr_header_flags() { return brr_header & 3; } - bool ADSR_enabled() { return !!(ADSR1 & 0x80); } + bool ADSR_enabled() { return bool(ADSR1 & 0x80); } uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; } uint8 ADSR_attack() { return ADSR1 & 15; } uint8 ADSR_sus_level() { return ADSR2 >> 5; } @@ -147,10 +144,10 @@ struct Voice { } } else if(GAIN & 0x80) { switch(GAIN & 0x60) { - case 0x00:env_mode = LINEAR_DEC; break; - case 0x20:env_mode = EXP_DEC; break; - case 0x40:env_mode = LINEAR_INC; break; - case 0x60:env_mode = BENT_INC; break; + case 0x00: env_mode = LINEAR_DEC; break; + case 0x20: env_mode = EXP_DEC; break; + case 0x40: env_mode = LINEAR_INC; break; + case 0x60: env_mode = BENT_INC; break; } env_rate = RateTable[GAIN & 0x1f]; } else { @@ -161,8 +158,6 @@ struct Voice { } } voice[8]; - int32 clamp(int32 bits, int32 x); - int32 clip (int32 bits, int32 x); public: uint8 read (uint8 addr); void write(uint8 addr, uint8 data); diff --git a/src/interface.h b/src/interface.h index ed50cd3c..d91e9bbc 100644 --- a/src/interface.h +++ b/src/interface.h @@ -19,9 +19,11 @@ #include "memory/bmemory/bmemory.h" #include "cpu/cpu.h" +#include "cpu/scpu/scpu.h" #include "cpu/bcpu/bcpu.h" #include "apu/apu.h" +#include "apu/sapu/sapu.h" #include "apu/bapu/bapu.h" #include "dsp/dsp.h" @@ -35,6 +37,7 @@ #include "chip/srtc/srtc.h" #include "chip/sdd1/sdd1.h" #include "chip/c4/c4.h" +#include "chip/dsp1/dsp1.h" #include "chip/dsp2/dsp2.h" #include "chip/obc1/obc1.h" @@ -51,12 +54,13 @@ extern MMIO mmio_unmapped; extern APUCORE deref(apu); extern DSPCORE deref(dsp); extern PPUCORE deref(ppu); - #endif +#endif extern SNES *snes; extern SRTC *srtc; extern SDD1 *sdd1; extern C4 *c4; +extern DSP1 *dsp1; extern DSP2 *dsp2; extern OBC1 *obc1; @@ -85,6 +89,7 @@ SNES *snes; SRTC *srtc; SDD1 *sdd1; C4 *c4; +DSP1 *dsp1; DSP2 *dsp2; OBC1 *obc1; diff --git a/src/lib/libbase.h b/src/lib/libbase.h index a829a38d..a8de1d46 100644 --- a/src/lib/libbase.h +++ b/src/lib/libbase.h @@ -1,10 +1,29 @@ /* - libbase : version 0.07 ~byuu (04/21/06) + libbase : version 0.08 ~byuu (07/08/06) */ #ifndef __LIBBASE #define __LIBBASE +#ifdef _MSC_VER +//disable libc deprecation warnings in MSVC 2k5+ +#pragma warning(disable:4996) +#endif + +/***** + * inline expansion + *****/ + +#ifdef _MSC_VER + #define noinline __declspec(noinline) + #define inline inline + #define forceinline __forceinline +#else + #define noinline + #define inline inline + #define forceinline inline +#endif + #include #include #include @@ -17,14 +36,19 @@ #endif #ifndef TRUE -#define TRUE 1 +#define TRUE !FALSE #endif #define SafeFree(__n) if(__n) { free(__n); __n = 0; } #define SafeDelete(__n) if(__n) { delete(__n); __n = 0; } #define SafeRelease(__n) if(__n) { __n->Release(); __n = 0; } +/***** + * typedefs + *****/ + typedef unsigned int uint; +typedef signed int sint; typedef unsigned char byte; typedef unsigned short word; @@ -42,16 +66,151 @@ typedef signed short int16; typedef signed long int32; typedef signed long long int64; -template void swap(T &x, T &y) { + +/***** + * templates + *****/ + +template inline void swap(T &x, T &y) { T z = x; x = y; y = z; } -template T bound_range(T &x, Targ min, Targ max) { +template inline T minmax(const T x) { return (x < T(min)) ? T(min) : (x > T(max)) ? T(max) : x; } +template inline unsigned uclamp(const unsigned x) { +enum { m = (1 << bits) - 1 }; + return (x > m) ? m : x; +} + +template inline unsigned uclip(const unsigned x) { +enum { m = (1 << bits) - 1 }; + return (x & m); +} + +template inline signed sclamp(const signed x) { +enum { b = 1 << (bits - 1), m = (1 << (bits - 1)) - 1 }; + return (x > m) ? m : (x < -b) ? -b : x; +} + +//requires compiler SAR (shift arithmetic right) support +template inline signed sclip(const signed x) { +enum { s = sizeof(x) * 8 - bits }; + return (x << s) >> s; +} + +//use this if compiler uses SLR (shift logical right) +//template inline signed sclip(const signed x) { +//enum { b = 1 << (bits - 1), m = (1 << (bits - 1)) - 1 }; +// return (x & b) ? (x | ~m) : (x & m); +//} + +template class uint_t { +private: +base data; + +public: + inline operator unsigned() const { return data; } + inline unsigned operator ++(int) { base r = data; data = uclip(data + 1); return r; } + inline unsigned operator --(int) { base r = data; data = uclip(data - 1); return r; } + inline unsigned operator ++() { data = uclip(data + 1); return data; } + inline unsigned operator --() { data = uclip(data - 1); return data; } + template inline unsigned operator =(const T i) { data = uclip(i); return data; } + template inline unsigned operator |=(const T i) { data = uclip(data | i); return data; } + template inline unsigned operator ^=(const T i) { data = uclip(data ^ i); return data; } + template inline unsigned operator &=(const T i) { data = uclip(data & i); return data; } + template inline unsigned operator<<=(const T i) { data = uclip(data << i); return data; } + template inline unsigned operator>>=(const T i) { data = uclip(data >> i); return data; } + template inline unsigned operator +=(const T i) { data = uclip(data + i); return data; } + template inline unsigned operator -=(const T i) { data = uclip(data - i); return data; } + template inline unsigned operator *=(const T i) { data = uclip(data * i); return data; } + template inline unsigned operator /=(const T i) { data = uclip(data / i); return data; } + template inline unsigned operator %=(const T i) { data = uclip(data % i); return data; } + + inline uint_t() : data(0) {} + inline uint_t(const base i) : data(uclip(i)) {} +}; + +template class int_t { +private: +base data; + +public: + inline operator signed() const { return data; } + inline signed operator ++(int) { base r = data; data = sclip(data + 1); return r; } + inline signed operator --(int) { base r = data; data = sclip(data - 1); return r; } + inline signed operator ++() { data = sclip(data + 1); return data; } + inline signed operator --() { data = sclip(data - 1); return data; } + template inline signed operator =(const T i) { data = sclip(i); return data; } + template inline signed operator |=(const T i) { data = sclip(data | i); return data; } + template inline signed operator ^=(const T i) { data = sclip(data ^ i); return data; } + template inline signed operator &=(const T i) { data = sclip(data & i); return data; } + template inline signed operator<<=(const T i) { data = sclip(data << i); return data; } + template inline signed operator>>=(const T i) { data = sclip(data >> i); return data; } + template inline signed operator +=(const T i) { data = sclip(data + i); return data; } + template inline signed operator -=(const T i) { data = sclip(data - i); return data; } + template inline signed operator *=(const T i) { data = sclip(data * i); return data; } + template inline signed operator /=(const T i) { data = sclip(data / i); return data; } + template inline signed operator %=(const T i) { data = sclip(data % i); return data; } + + inline int_t() : data(0) {} + inline int_t(const base i) : data(sclip(i)) {} +}; + +typedef uint_t<24> uint24; +typedef int_t<24> int24; +typedef uint_t<48, uint64> uint48; +typedef int_t<48, int64> int48; + +/***** + * endian wrappers + *****/ + +#ifndef ARCH_MSB +//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } = 0x04030201 +#define order_lsb2(a,b) a,b +#define order_lsb3(a,b,c) a,b,c +#define order_lsb4(a,b,c,d) a,b,c,d +#define order_lsb5(a,b,c,d,e) a,b,c,d,e +#define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f +#define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g +#define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h +#define order_msb2(a,b) b,a +#define order_msb3(a,b,c) c,b,a +#define order_msb4(a,b,c,d) d,c,b,a +#define order_msb5(a,b,c,d,e) e,d,c,b,a +#define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a +#define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a +#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a +#define order_lsbit8(b0,b1,b2,b3,b4,b5,b6,b7) b7:1,b6:1,b5:1,b4:1,b3:1,b2:1,b1:1,b0:1 +#define order_msbit8(b7,b6,b5,b4,b3,b2,b1,b0) b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1 +#else +//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } = 0x01020304 +#define order_lsb2(a,b) b,a +#define order_lsb3(a,b,c) c,b,a +#define order_lsb4(a,b,c,d) d,c,b,a +#define order_lsb5(a,b,c,d,e) e,d,c,b,a +#define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a +#define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a +#define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a +#define order_msb2(a,b) a,b +#define order_msb3(a,b,c) a,b,c +#define order_msb4(a,b,c,d) a,b,c,d +#define order_msb5(a,b,c,d,e) a,b,c,d,e +#define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f +#define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g +#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h +#define order_lsbit8(b7,b6,b5,b4,b3,b2,b1,b0) b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1 +#define order_msbit8(b0,b1,b2,b3,b4,b5,b6,b7) b7:1,b6:1,b5:1,b4:1,b3:1,b2:1,b1:1,b0:1 +#endif + +/***** + * libc extensions + *****/ + inline bool fexists(const char *fn) { FILE *fp = fopen(fn, "rb"); if(!fp)return false; @@ -79,6 +238,11 @@ uint32 size = ftell(fp); return size; } +/***** + * crc32 calculation + * TODO: create libhash and move this code there + *****/ + const uint32 crc32_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, diff --git a/src/lib/libco_win32.cpp b/src/lib/libco_win32.cpp new file mode 100644 index 00000000..c6fbaf1b --- /dev/null +++ b/src/lib/libco_win32.cpp @@ -0,0 +1,68 @@ +/* + libco_win32 : version 0.04 ~byuu (05/11/06) + win32-x86 implementation of libco +*/ + +#define WINVER 0x0400 +#define _WIN32_WINNT 0x0400 +#include + +#include "libco.h" + +namespace libco_win32 { + bool co_enabled = false; + int co_stackptr = 0; + thread_t co_stack[4096]; + + void __stdcall coentry_proc(void *coentry) { + thread_p main = (thread_p)coentry; + main(); + } +}; + +extern "C" void co_init() { + if(libco_win32::co_enabled == true)return; + libco_win32::co_enabled = true; + + ConvertThreadToFiber(0); +} + +extern "C" void co_term() { +/***** +//ConverFiberToThread() only exists in WinXP+ + + if(libco_win32::co_enabled == false)return; + libco_win32::co_enabled = false; + + ConvertFiberToThread(); +*****/ +} + +extern "C" thread_t co_active() { + if(libco_win32::co_enabled == false)co_init(); + + return GetCurrentFiber(); +} + +extern "C" thread_t co_create(thread_p coentry, unsigned int heapsize) { + if(libco_win32::co_enabled == false)co_init(); + + return CreateFiber(heapsize, libco_win32::coentry_proc, (void*)coentry); +} + +extern "C" void co_delete(thread_t cothread) { + DeleteFiber(cothread); +} + +extern "C" void co_jump(thread_t cothread) { + SwitchToFiber(cothread); +} + +extern "C" void co_call(thread_t cothread) { + libco_win32::co_stack[libco_win32::co_stackptr++] = co_active(); + co_jump(cothread); +} + +extern "C" void co_return() { + co_jump(libco_win32::co_stack[--libco_win32::co_stackptr]); +} diff --git a/src/lib/libco_x86.asm b/src/lib/libco_x86.asm new file mode 100644 index 00000000..dfb9a2a8 --- /dev/null +++ b/src/lib/libco_x86.asm @@ -0,0 +1,215 @@ +;***** +;libco_x86 : version 0.06 ~byuu (05/21/06) +;cross-platform x86 implementation of libco +; +;context save/restore adheres to c/c++ ABI +;for x86 win32, linux and freebsd +; +;context saves esp+ebp+esi+edi+ebx +;context ignores eax+ecx+edx +;context ignores st([0-7])+xmm[0-15] +;context ignores all else +;***** + +section .data + +align 4 +co_initialized dd 0 +co_active_context dd 0 + +section .code + +;***** +;linker-specific name decorations +;***** +%define malloc _malloc +%define free _free + +%define co_init @co_init@0 +%define co_term @co_term@0 +%define co_active @co_active@0 +%define co_create @co_create@8 +%define co_delete @co_delete@4 +%define co_jump @co_jump@4 +%define co_call @co_call@4 +%define co_return @co_return@0 + +extern malloc +extern free + +global co_init +global co_term +global co_active +global co_create +global co_delete +global co_jump +global co_call +global co_return + +;***** +;extern "C" void __fastcall co_init(); +;***** + +align 16 +co_init: + cmp dword[co_initialized],0 ;only run co_init once + jne .end + inc dword[co_initialized] + +;create context for main thread + mov ecx,0 ;entry point for main thread is not needed + mov edx,256 ;main thread uses default program stack + call co_create + mov dword[co_active_context],eax +.end + ret + +;***** +;extern "C" void __fastcall co_term(); +;***** + +align 16 +co_term: + ret + +;***** +;extern "C" thread_t __fastcall co_active(); +;return = eax +;***** + +align 16 +co_active: + cmp dword[co_initialized],0 ;make sure co_init has been called + jne .next + call co_init +.next: + mov eax,dword[co_active_context] + ret + +;***** +;extern "C" thread_t __fastcall co_create(thread_p coentry, unsigned int heapsize); +;ecx = coentry +;edx = heapsize +;return = eax +;***** + +align 16 +co_create: + cmp dword[co_initialized],0 ;make sure co_init has been called + jne .next + push ecx + push edx + call co_init + pop edx + pop ecx +.next: + +;create heap space (stack + register storage) + add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align) + push ecx + push edx + call malloc + pop edx + pop ecx + + add edx,eax ;set edx to point to top of stack heap + and edx,0xfffffff0 ;force 16-byte alignment of stack heap + +;store thread entry point + registers so that first call to co_jump will go to coentry + mov dword[edx-4],ecx ;edx=*stack,ecx=coentry + mov dword[edx-8],0 + mov dword[edx-12],0 + mov dword[edx-16],0 + mov dword[edx-20],0 + sub edx,20 + +;initialize context memory heap + mov dword[eax],edx ;thread_t[0-3] = stack heap pointer (esp) + mov dword[eax+4],0 ;thread_t[4-7] = (null) pointer to prev_call_context + + ret ;return allocated memory block as thread handle + +;***** +;extern "C" void __fastcall co_delete(thread_t cothread); +;ecx = cothread +;***** + +align 16 +co_delete: + push ecx + call free + add esp,4 + ret + +;***** +;extern "C" void __fastcall co_jump(thread_t cothread); +;ecx = cothread +;***** + +align 16 +co_jump: + mov eax,dword[co_active_context] ;backup current context + mov dword[co_active_context],ecx ;set new active context + + push ebp + push esi + push edi + push ebx + mov dword[eax],esp + + mov esp,dword[ecx] + pop ebx + pop edi + pop esi + pop ebp + + ret + +;***** +;extern "C" void __fastcall co_call(thread_t cothread); +;ecx = cothread +;***** + +align 16 +co_call: + mov eax,dword[co_active_context] ;backup current context + mov dword[co_active_context],ecx ;set new active context + mov dword[ecx+4],eax + + push ebp + push esi + push edi + push ebx + mov dword[eax],esp + + mov esp,dword[ecx] + pop ebx + pop edi + pop esi + pop ebp + + ret + +;***** +;extern "C" void __fastcall co_return(); +;***** + +align 16 +co_return: + mov eax,dword[co_active_context] ;backup current context + mov ecx,dword[eax+4] ;restore pre-call context + mov dword[co_active_context],ecx ;set new active context + + push ebp + push esi + push edi + push ebx + mov dword[eax],esp + + mov esp,dword[ecx] + pop ebx + pop edi + pop esi + pop ebp + + ret diff --git a/src/lib/libco_x86.h b/src/lib/libco_x86.h new file mode 100644 index 00000000..dba5d185 --- /dev/null +++ b/src/lib/libco_x86.h @@ -0,0 +1,15 @@ +/* + libco_x86 : version 0.06 ~byuu (05/21/2006) +*/ + +typedef void (*thread_t); +typedef void (*thread_p)(); + +extern "C" void __fastcall co_init(); +extern "C" void __fastcall co_term(); +extern "C" thread_t __fastcall co_active(); +extern "C" thread_t __fastcall co_create(thread_p coentry, unsigned int heapsize); +extern "C" void __fastcall co_delete(thread_t cothread); +extern "C" void __fastcall co_jump(thread_t cothread); +extern "C" void __fastcall co_call(thread_t cothread); +extern "C" void __fastcall co_return(); diff --git a/src/lib/libconfig.h b/src/lib/libconfig.h index 380b2cb1..c7c2fa5f 100644 --- a/src/lib/libconfig.h +++ b/src/lib/libconfig.h @@ -1,5 +1,5 @@ /* - libconfig : version 0.07 ~byuu (02/10/06) + libconfig : version 0.08 ~byuu (07/02/06) */ #ifndef __LIBCONFIG @@ -19,17 +19,7 @@ class Config; // class T : public Setting { public: SettingOperators(T); } t; // t = 0; // -> t.set(0); #define SettingOperators(__name) \ - inline __name &operator=(const bool _data) { set((uint)_data); return *this; } \ - inline __name &operator=(const uint _data) { set(_data); return *this; } \ - inline __name &operator=(const uint8 _data) { set(_data); return *this; } \ - inline __name &operator=(const uint16 _data) { set(_data); return *this; } \ - inline __name &operator=(const uint32 _data) { set(_data); return *this; } \ - inline __name &operator=(const int _data) { set(_data); return *this; } \ - inline __name &operator=(const int8 _data) { set(_data); return *this; } \ - inline __name &operator=(const int16 _data) { set(_data); return *this; } \ - inline __name &operator=(const int32 _data) { set(_data); return *this; } \ - inline __name &operator=(const float _data) { set((uint)_data); return *this; } \ - inline __name &operator=(const double _data) { set((uint)_data); return *this; } \ + template inline __name &operator=(const T x) { set(T(x)); return *this; } \ void toggle() { data ^= 1; set(data); } \ __name(Config *_parent, char *_name, char *_desc, uint _data, uint _type) : \ Setting(_parent, _name, _desc, _data, _type) {} \ @@ -44,17 +34,19 @@ uint data, type, def; public: enum { - TRUE_FALSE, - ENABLED_DISABLED, - ON_OFF, - YES_NO, - DEC, - HEX, - HEX8, - HEX16, - HEX24, - HEX32, - STR + BOOL = 0, + BOOLEAN = 0, + TRUE_FALSE = 0, + ENABLED_DISABLED = 1, + ON_OFF = 2, + YES_NO = 3, + DEC = 4, + HEX = 5, + HEX8 = 6, + HEX16 = 7, + HEX24 = 8, + HEX32 = 9, + STR = 10, }; char *name, *desc; substring char_data, char_def; @@ -68,29 +60,14 @@ substring char_data, char_def; Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type); Setting(Config *_parent, char *_name, char *_desc, char *_data); - inline operator bool() { return (bool)get(); } - inline operator uint() { return get(); } - inline operator uint8() { return get(); } - inline operator uint16() { return get(); } - inline operator uint32() { return get(); } - inline operator int() { return get(); } - inline operator int8() { return get(); } - inline operator int16() { return get(); } - inline operator int32() { return get(); } - inline operator float() { return (float) get(); } - inline operator double() { return (double)get(); } - - inline Setting &operator=(const bool _data) { set((uint)_data); return *this; } - inline Setting &operator=(const uint _data) { set(_data); return *this; } - inline Setting &operator=(const uint8 _data) { set(_data); return *this; } - inline Setting &operator=(const uint16 _data) { set(_data); return *this; } - inline Setting &operator=(const uint32 _data) { set(_data); return *this; } - inline Setting &operator=(const int _data) { set(_data); return *this; } - inline Setting &operator=(const int8 _data) { set(_data); return *this; } - inline Setting &operator=(const int16 _data) { set(_data); return *this; } - inline Setting &operator=(const int32 _data) { set(_data); return *this; } - inline Setting &operator=(const float _data) { set((uint)_data); return *this; } - inline Setting &operator=(const double _data) { set((uint)_data); return *this; } + template inline operator T() { return T(get()); } + template inline Setting &operator=(const T x) { set(T(x)); return *this; } + template inline bool operator==(const T x) { return T(get()) == x; } + template inline bool operator!=(const T x) { return T(get()) != x; } + template inline bool operator>=(const T x) { return T(get()) >= x; } + template inline bool operator> (const T x) { return T(get()) > x; } + template inline bool operator<=(const T x) { return T(get()) <= x; } + template inline bool operator< (const T x) { return T(get()) < x; } }; class Config { diff --git a/src/lib/libstring.cpp b/src/lib/libstring.cpp index eb0893d9..712beb63 100644 --- a/src/lib/libstring.cpp +++ b/src/lib/libstring.cpp @@ -8,10 +8,7 @@ substring::substring() { } substring::~substring() { - if(s) { - free(s); - s = 0; - } + SafeFree(s); } void string::addto(uint num) { @@ -32,8 +29,7 @@ string::string() { } string::~string() { -int i; - for(i=listcount-1;i>=0;i--) { + for(int i = listcount - 1; i >= 0; i--) { delete((substring*)list[i]); } } @@ -65,7 +61,7 @@ int strcmp(const char *dest, substring &src) { return strcmp(dest, strptr(src)); int strcmp(substring &dest, substring &src) { return strcmp(strptr(dest), strptr(src)); } int __stricmp(const char *dest, const char *src) { - while(*dest && *src) { + while(*dest) { if(chrlower(*dest) != chrlower(*src))break; dest++; src++; @@ -86,6 +82,12 @@ bool strimatch(substring &dest, const char *src) { return strimatch(strptr(dest) bool strimatch(const char *dest, substring &src) { return strimatch(dest, strptr(src)); } bool strimatch(substring &dest, substring &src) { return strimatch(strptr(dest), strptr(src)); } +void strcpy(substring &dest, const char src) { + if(1 > dest.size) { strresize(dest, 1); } + dest.s[0] = src; + dest.s[1] = 0; +} + void strcpy(substring &dest, const char *src) { int srclen = strlen(src); if(srclen > dest.size) { strresize(dest, srclen); } @@ -106,15 +108,20 @@ int srclen = strlen(src); void strncpy(substring &dest, substring &src, uint32 length) { strncpy(dest, strptr(src), length); } void strset(substring &dest, uint pos, uint8 c) { -char *s; if(pos > dest.size) { strresize(dest, pos); } dest.s[pos] = c; } +void strcat(substring &dest, const char src) { +int length = strlen(dest); + if(length + 1 > dest.size) { strresize(dest, length + 1); } + dest.s[length] = src; + dest.s[length + 1] = 0; +} + void strcat(substring &dest, const char *src) { -int srclen, destlen; - srclen = strlen(src); - destlen = strlen(dest.s); +int srclen = strlen(src); +int destlen = strlen(dest); if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); } strcat(dest.s, src); } @@ -143,26 +150,30 @@ int i, sl = strlen(dest.s); s[i] = 0; } -void strlower(char *str) { - while(*str) { - *str = chrlower(*str); - str++; +char *strlower(char *str) { +uint i = 0; + while(str[i]) { + str[i] = chrlower(str[i]); + i++; } + return str; } -void strlower(substring &str) { strlower(strptr(str)); } +substring &strlower(substring &str) { strlower(strptr(str)); return str; } -void strupper(char *str) { - while(*str) { - *str = chrupper(*str); - str++; +char *strupper(char *str) { +uint i = 0; + while(str[i]) { + str[i] = chrupper(str[i]); + i++; } + return str; } -void strupper(substring &str) { strupper(strptr(str)); } +substring &strupper(substring &str) { strupper(strptr(str)); return str; } bool strpos(const char *str, const char *key, uint &pos) { -int i, ssl = strlen(str), ksl = strlen(key); +int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl)return false; - for(i = 0; i <= ssl - ksl; i++) { + for(int i = 0; i <= ssl - ksl; i++) { if(!memcmp(str + i, key, ksl)) { pos = i; return true; @@ -175,13 +186,12 @@ bool strpos(const char *str, substring &key, uint &pos) { return strpos(str, str bool strpos(substring &str, substring &key, uint &pos) { return strpos(strptr(str), strptr(key), pos); } bool qstrpos(const char *str, const char *key, uint &pos) { -int i, z, ssl = strlen(str), ksl = strlen(key); -uint8 x; +int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl)return false; - for(i = 0; i <= ssl - ksl;) { - x = str[i]; + for(int i = 0; i <= ssl - ksl;) { + uint8 x = str[i]; if(x == '\"' || x == '\'') { - z = i++; + uint8 z = i++; while(str[i] != x && i < ssl)i++; if(i >= ssl)i = z; } @@ -220,9 +230,9 @@ int i, ssl = strlen(str), ksl = strlen(key); bool strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); } bool stribegin(const char *str, const char *key) { -int i, ssl = strlen(str), ksl = strlen(key); +int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl)return false; - for(i=0;i= 'A' && str[i] <= 'Z') { if(str[i] != key[i] && str[i]+0x20 != key[i])return false; } else if(str[i] >= 'a' && str[i] <= 'z') { @@ -236,16 +246,16 @@ int i, ssl = strlen(str), ksl = strlen(key); bool stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); } bool strend(const char *str, const char *key) { -int i, ssl = strlen(str), ksl = strlen(key); +int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl)return false; return (!memcmp(str + ssl - ksl, key, ksl)); } bool strend(substring &str, const char *key) { return strend(strptr(str), key); } bool striend(const char *str, const char *key) { -int i, z, ssl = strlen(str), ksl = strlen(key); +int ssl = strlen(str), ksl = strlen(key); if(ksl > ssl)return false; - for(i=ssl-ksl, z=0;i= 'A' && str[i] <= 'Z') { if(str[i] != key[z] && str[i]+0x20 != key[z])return false; } else if(str[i] >= 'a' && str[i] <= 'z') { @@ -298,7 +308,7 @@ void strirtrim(substring &str, const char *key) { strirtrim(strptr(str), key); } //does not work on type char* because function increases string length void strquote(substring &str) { -static string t; +static substring t; strcpy(t, "\""); strcat(t, str); strcat(t, "\""); @@ -316,7 +326,7 @@ int i, ssl = strlen(str); else return false; //now remove them - for(i=0;i num)mask /= 10; + while(mask > 1) { + str[0] = '0'; + while(num >= mask) { str[0]++; num -= mask; } + str++; + mask /= 10; + } + str[0] = '0' + num; + str++; + str[0] = 0; + return pstr; +} + +substring &utoa(substring &str, uint num) { + if(str.size < 16) { strresize(str, 16); } + utoa(strptr(str), num); + return str; +} + +char *itoa(char *str, uint num) { +char *pstr = str; + if(num < 0) { + str[0] = '-'; + str++; + num = abs(int(num)); + } + utoa(str, num); + return pstr; +} + +substring &itoa(substring &str, uint num) { + if(str.size < 16) { strresize(str, 16); } + itoa(strptr(str), num); + return str; +} + +char *htoa(char *str, uint num) { +char *pstr = str; +uint mask = 28, r; + while(mask && ((num >> mask) & 15) == 0)mask -= 4; + while(mask) { + r = (num >> mask) & 15; + str[0] = (r < 10) ? ('0' + r) : ('a' + r - 10); + str++; + mask -= 4; + } + r = num & 15; + str[0] = (r < 10) ? ('0' + r) : ('a' + r - 10); + str++; + str[0] = 0; + return pstr; +} + +substring &htoa(substring &str, uint num) { + if(str.size < 16) { strresize(str, 16); } + htoa(strptr(str), num); + return str; +} + +char *uhtoa(char *str, uint num) { +char *pstr = str; +uint mask = 28, r; + while(mask && ((num >> mask) & 15) == 0)mask -= 4; + while(mask) { + r = (num >> mask) & 15; + str[0] = (r < 10) ? ('0' + r) : ('A' + r - 10); + str++; + mask -= 4; + } + r = num & 15; + str[0] = (r < 10) ? ('0' + r) : ('A' + r - 10); + str++; + str[0] = 0; + return pstr; +} + +substring &uhtoa(substring &str, uint num) { + if(str.size < 16) { strresize(str, 16); } + uhtoa(strptr(str), num); + return str; +} + +char *btoa(char *str, uint num) { +char *pstr = str; +uint mask = 0x80000000; + while(mask && (num & mask) == 0)mask >>= 1; + while(mask > 1) { + str[0] = (num & mask) ? '1' : '0'; + str++; + mask >>= 1; + } + str[0] = (num & mask) ? '1' : '0'; + str++; + str[0] = 0; + return pstr; +} + +substring &btoa(substring &str, uint num) { + if(str.size < 48) { strresize(str, 48); } + btoa(strptr(str), num); + return str; +} + #include "libstring_math.cpp" #include "libstring_split.cpp" #include "libstring_replace.cpp" diff --git a/src/lib/libstring.h b/src/lib/libstring.h index 933687e6..52e93558 100644 --- a/src/lib/libstring.h +++ b/src/lib/libstring.h @@ -1,5 +1,5 @@ /* - libstring : version 0.10 ~byuu (03/05/06) + libstring : version 0.11 ~byuu (07/02/06) */ #ifndef __LIBSTRING @@ -51,6 +51,7 @@ void strncpy(substring &dest, substring &src, uint32 length); void strset(substring &dest, uint pos, uint8 c); +void strcat(substring &dest, const char src); void strcat(substring &dest, const char *src); void strcat(substring &dest, substring &src); @@ -59,11 +60,11 @@ void strinsert(substring &dest, substring &src, uint pos); void strremove(substring &dest, uint start, uint length = 0); -void strlower(char *str); -void strlower(substring &str); +char *strlower(char *str); +substring &strlower(substring &str); -void strupper(char *str); -void strupper(substring &str); +char *strupper(char *str); +substring &strupper(substring &str); bool strpos(const char *str, const char *key, uint &pos); bool strpos(substring &str, const char *key, uint &pos); @@ -125,17 +126,32 @@ uint strbin(substring &str); int sstrbin(const char *str); int sstrbin(substring &str); +char *utoa(char *str, uint num); +substring &utoa(substring &str, uint num); + +char *itoa(char *str, uint num); +substring &itoa(substring &str, uint num); + +char *htoa(char *str, uint num); +substring &htoa(substring &str, uint num); + +char *uhtoa(char *str, uint num); +substring &uhtoa(substring &str, uint num); + +char *btoa(char *str, uint num); +substring &btoa(substring &str, uint num); + uint strmath(const char *in_str); uint strmath(substring &in_str); bool strmathentity(const char *str); bool strmathentity(substring &str); -void replace(substring &str, const char *key, const char *token); -void replace(substring &str, const char *key, substring &token); +substring &replace(substring &str, const char *key, const char *token); +substring &replace(substring &str, const char *key, substring &token); -void qreplace(substring &str, const char *key, const char *token); -void qreplace(substring &str, const char *key, substring &token); +substring &qreplace(substring &str, const char *key, const char *token); +substring &qreplace(substring &str, const char *key, substring &token); void split(string &dest, const char *key, const char *src); void split(string &dest, const char *key, substring &src); @@ -143,7 +159,8 @@ void split(string &dest, const char *key, substring &src); void qsplit(string &dest, const char *key, const char *src); void qsplit(string &dest, const char *key, substring &src); -void sprintf(substring &str, const char *s, ...); +uint vsprintf(substring &str, const char *s, va_list args); +uint sprintf(substring &str, const char *s, ...); class substring { public: @@ -175,14 +192,7 @@ uint listcount, count; //inline char* operator*() { return strptr(str(0)); } //inline operator char*() { return str(0).s; } inline operator substring&() { return str(0); } - inline substring& operator[](uint i) { return str(i); } - inline substring& operator[](uint8 i) { return str(i); } - inline substring& operator[](uint16 i) { return str(i); } - inline substring& operator[](uint32 i) { return str(i); } - inline substring& operator[](int i) { return str(i); } - inline substring& operator[](int8 i) { return str(i); } - inline substring& operator[](int16 i) { return str(i); } - inline substring& operator[](int32 i) { return str(i); } + template inline substring& operator[](T i) { return str(i); } string(); ~string(); diff --git a/src/lib/libstring_replace.cpp b/src/lib/libstring_replace.cpp index 88df3c91..39290656 100644 --- a/src/lib/libstring_replace.cpp +++ b/src/lib/libstring_replace.cpp @@ -1,8 +1,8 @@ -void replace(substring &str, const char *key, const char *token) { +substring &replace(substring &str, const char *key, const char *token) { int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); uint replace_count = 0, size = ssl; char *data; - if(ksl > ssl)return; + if(ksl > ssl)return str; if(tsl > ksl) { //the new string may be longer than the old string... for(i=0;i<=ssl-ksl;) { //so let's find out how big of a string we'll need... if(!memcmp(str.s + i, key, ksl)) { @@ -26,15 +26,16 @@ char *data; data[z] = 0; strcpy(str, data); free(data); + return str; } -void replace(substring &str, const char *key, substring &token) { replace(str, key, strptr(token)); } +substring &replace(substring &str, const char *key, substring &token) { return replace(str, key, strptr(token)); } -void qreplace(substring &str, const char *key, const char *token) { +substring &qreplace(substring &str, const char *key, const char *token) { int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); uint replace_count = 0, size = ssl; uint8 x; char *data; - if(ksl > ssl)return; + if(ksl > ssl)return str; if(tsl > ksl) { for(i=0;i<=ssl-ksl;) { x = str.s[i]; @@ -80,5 +81,6 @@ char *data; data[z] = 0; strcpy(str, data); free(data); + return str; } -void qreplace(substring &str, const char *key, substring &token) { qreplace(str, key, strptr(token)); } +substring &qreplace(substring &str, const char *key, substring &token) { return qreplace(str, key, strptr(token)); } diff --git a/src/lib/libstring_sprintf.cpp b/src/lib/libstring_sprintf.cpp index 0844a2b7..956fec31 100644 --- a/src/lib/libstring_sprintf.cpp +++ b/src/lib/libstring_sprintf.cpp @@ -1,69 +1,202 @@ -void numtobin(char *s, uint num) { -uint mask = 0x80000000, len = 0, z = 0; - for(;mask;mask>>=1,len++) { if(num&mask)break; } - len = 32 - len; - do { - if(num&(1<<(len-1)))s[z++] = '1'; - else s[z++] = '0'; - }while(--len); - s[z] = 0; +uint sprintf(substring &str, const char *s, ...) { +va_list args; + va_start(args, s); +uint length = vsprintf(str, s, args); + va_end(args); + return length; } -void sprintf(substring &str, const char *s, ...) { -va_list args; -char t[2], n[256]; -int i, l, sl, z; -uint8 pad_type, pad_len; -uint32 num; -char *r; - va_start(args, s); +uint vsprintf(substring &str, const char *s, va_list args) { +bool leftalign; +bool showbase; +char positivesign; +char pad; +uint width; +bool useprecision; +uint precision; +char modifier; +char type; + +uint32 vararg32; +uint64 vararg64; +char *varptr; +char varstr[256]; +uint varstrlen; + strcpy(str, ""); - for(i=0;i= '0' && s[i+2] <= '9')) { - pad_type = 1; - if(s[i+3] >= '0' && s[i+3] <= '9') { pad_len = (s[i+2]-'0')*10 + (s[i+3]-'0'); i+=4; } - else { pad_len = (s[i+2]-'0'); i+=3; } - } - else if(s[i] >= '0' && s[i] <= '9') { - pad_type = 2; - if(s[i+1] >= '0' && s[i+1] <= '9') { pad_len = (s[i]-'0')*10 + (s[i+1]-'0'); i+=2; } - else { pad_len = (s[i]-'0'); i+=1; } - } - else { pad_type = 0; } - if(s[i] == 'd') { - num = va_arg(args, uint32); - sprintf(n, "%d", num); - } else if(s[i] == 'x') { - num = va_arg(args, uint32); - sprintf(n, "%x", num); - } else if(s[i] == 'b') { - num = va_arg(args, uint32); - numtobin(n, num); - } else if(s[i] == 's') { - r = va_arg(args, char*); - } + //flags + leftalign = false; + positivesign = 0; + showbase = false; - if(pad_type != 0) { - if(s[i] == 's')sl = strlen(r); - else sl = strlen(n); - if(sl < pad_len) { - while(sl < pad_len) { - strcat(str, (pad_type == 1)?"0":" "); - sl++; - } + while(s[i]) { + if(s[i] == '-') { + leftalign = true; + i++; + } else if(s[i] == '+') { + positivesign = '+'; + i++; + } else if(s[i] == ' ') { + positivesign = ' '; + i++; + } else if(s[i] == '#') { + showbase = true; + i++; + } else { + break; } } - if(s[i] == 's')strcat(str, r); - else strcat(str, n); - } else { - t[0] = s[i]; - t[1] = 0; - strcat(str, t); + //zero padding + if(s[i] == '0') { + pad = '0'; + i++; + } else { + pad = ' '; + } + + //width + width = 0; + if(s[i] == '*') { + width = va_arg(args, uint32); + i++; + } else { + while(s[i]) { + if(s[i] < '0' || s[i] > '9')break; + width *= 10; + width += s[i++] - '0'; + } + } + if(width == 0)width = 1; + + //precision + useprecision = false; + precision = 0; + if(s[i] == '.') { + useprecision = true; + i++; + + if(s[i] == '*') { + precision = va_arg(args, uint32); + i++; + } else { + while(s[i]) { + if(s[i] < '0' || s[i] > '9')break; + precision *= 10; + precision += s[i++] - '0'; + } + } + } + if(precision == 0)precision = 1; + + //modifier + if(s[i] == 'h') { + modifier = 'h'; + i++; + } else if(s[i] == 'l') { + modifier = 'l'; + i++; + } else if(s[i] == 'L') { + modifier = 'L'; + i++; + } + + //type + type = s[i++]; + switch(type) { + + case 'c': { + //character + vararg32 = va_arg(args, uint32); + + if(leftalign == false) { while(width-- > 1)strcat(str, pad); } + strcat(str, char(vararg32)); + if(leftalign == true) { while(width-- > 1)strcat(str, pad); } + } break; + + case 's': { + //string + varptr = va_arg(args, char*); + + varstrlen = strlen(varptr); + if(useprecision && precision < varstrlen)varstrlen = precision; + if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); } + uint index = 0; + //todo: optimize to a fixed-width strcat + while(index < varstrlen)strcat(str, varptr[index++]); + if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); } + } break; + + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': { + //signed integer + vararg32 = va_arg(args, uint32); + + if(type == 'd' || type == 'i') { + itoa(varstr, vararg32); + } else if(type == 'u') { + utoa(varstr, vararg32); + } else if(type == 'x') { + htoa(varstr, vararg32); + } else if(type == 'X') { + uhtoa(varstr, vararg32); + } + + uint basestrlen = strlen(varstr); + varstrlen = (useprecision && precision > basestrlen) ? precision : basestrlen; + + if(type == 'd' || type == 'i') { + if(int32(vararg32) >= 0 && positivesign) { varstrlen++; } + } + + if(type == 'x' || type == 'X') { + if(showbase) { varstrlen += 2; } + } + + if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); } + if(type == 'd' || type == 'i') { + if(int32(vararg32) >= 0 && positivesign) { strcat(str, positivesign); } + } + if(type == 'x' || type == 'X') { + if(showbase)strcat(str, (type == 'x') ? "0x" : "0X"); + } + if(useprecision) { + while(basestrlen < precision) { strcat(str, "0"); basestrlen++; } + } + strcat(str, varstr); + if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); } + } break; + + case 'p': { + //todo: add 64-bit pointer support + vararg32 = va_arg(args, uint32); + + strcpy(varstr, "00000000"); + uint index = 8; + htoa(varstr + index, vararg32); + varstrlen = strlen(varstr + index); + index -= 8 - varstrlen; + + if(leftalign == false) { while(width-- > 8)strcat(str, pad); } + strcat(str, varstr + index); + if(leftalign == true) { while(width-- > 8)strcat(str, pad); } + } break; + + } } } - va_end(args); + return strlen(str); } diff --git a/src/lib/libwin32.cpp b/src/lib/libwin32.cpp index 309878a4..a06c4d40 100644 --- a/src/lib/libwin32.cpp +++ b/src/lib/libwin32.cpp @@ -25,6 +25,9 @@ va_list args; MessageBox(0, str, "bsnes", MB_OK); } +uint GetScreenWidth() { return GetSystemMetrics(SM_CXSCREEN); } +uint GetScreenHeight() { return GetSystemMetrics(SM_CYSCREEN); } + void ShowCursor() { if(global::cursor_visible == false) { global::cursor_visible = true; diff --git a/src/lib/libwin32.h b/src/lib/libwin32.h index 5056c77c..0c3ead34 100644 --- a/src/lib/libwin32.h +++ b/src/lib/libwin32.h @@ -9,6 +9,7 @@ #define WINVER 0x0400 #define _WIN32_WINNT 0x0400 +#define _WIN32_IE 0x0400 #include #include #include @@ -27,6 +28,8 @@ Font font_default; }; void alert(char *s, ...); +uint GetScreenWidth(); +uint GetScreenHeight(); void ShowCursor(); void HideCursor(); void ParseStyleParam(const char *style, string &output); diff --git a/src/lib/opgen_s.cpp b/src/lib/opgen_s.cpp new file mode 100644 index 00000000..af2077cb --- /dev/null +++ b/src/lib/opgen_s.cpp @@ -0,0 +1,135 @@ +#include "libbase.h" +#include "libstring.h" +#include "libstring.cpp" + +FILE *fp; + +string data, line, part, subpart; +string output_op; + +struct _op_list { + string name, arg; +} op_list[64]; + +int32 op_count, line_num; + +void clear_op_list() { + op_count = 0; + for(int i = 0; i < 64; i++) { + strcpy(op_list[i].name, ""); + for(int l = 0; l < 8; l++) { + strcpy(op_list[i].arg[l], ""); + } + } +} + +void gen_begin() { +int i = line_num; +char t[4096]; + clear_op_list(); + while(1) { + int z = op_count++; + strcpy(part, line[i]); + strrtrim(part, "),"); + strrtrim(part, ") {"); + split(subpart, "(", part); + strcpy(op_list[z].name, subpart[0]); + split(part, ", ", subpart[1]); + for(int l = 0; l < count(part); l++) { + strcpy(op_list[z].arg[l], part[l]); + } + if(strend(line[i], " {"))break; + i++; + } + + strcpy(output_op, "//$$\r\ncase $0: {\r\n"); + line_num = i + 1; +} + +void update_line(int i) { + replace(line[i], "end;", "break;"); +} + +void gen_op() { +int i = line_num, n, c; +char t[4096]; + while(1) { + if(strmatch(line[i], "}"))break; + + //remove cycle number + n = strdec(line[i]); + sprintf(t, "%d:", n); + strltrim(line[i], t); + //sprintf(t, "//%d:\r\n", n); + //strcat(output_op, t); + + update_line(i); + if(!strmatch(line[i], "")) { + strcat(output_op, " "); + strcat(output_op, line[i]); + strcat(output_op, "\r\n"); + } + + i++; + while(1) { + if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || strmatch(line[i], "}"))break; + + update_line(i); + strcat(output_op, line[i]); + strcat(output_op, "\r\n"); + + i++; + } + } + + strcat(output_op, "} break;"); + line_num = i + 1; +} + +void gen_end() { +string t; + for(int i = 0; i < op_count; i++) { + strcpy(t, output_op); + replace(t, "$$", op_list[i].name); + replace(t, "$0", op_list[i].arg[0]); + replace(t, "$1", op_list[i].arg[1]); + replace(t, "$2", op_list[i].arg[2]); + replace(t, "$3", op_list[i].arg[3]); + replace(t, "$4", op_list[i].arg[4]); + replace(t, "$5", op_list[i].arg[5]); + replace(t, "$6", op_list[i].arg[6]); + replace(t, "$7", op_list[i].arg[7]); + fprintf(fp, "%s\r\n\r\n", strptr(t)); + } +} + +void generate(char *dest, char *src) { + fp = fopen(src, "rb"); + + fseek(fp, 0, SEEK_END); +int fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); +char *buf = (char*)malloc(fsize + 1); + fread(buf, 1, fsize, fp); + fclose(fp); + buf[fsize] = 0; + + strcpy(data, buf); + free(buf); + replace(data, "\r\n", "\n"); + split(line, "\n", data); + + fp = fopen(dest, "wb"); + + line_num = 0; + while(line_num < count(line)) { + while(strmatch(line[line_num], "") && line_num < count(line))line_num++; + if(line_num >= count(line))break; + + gen_begin(); + gen_op(); + gen_end(); + } + + fclose(fp); +} diff --git a/src/lib/opgen_so.cpp b/src/lib/opgen_so.cpp new file mode 100644 index 00000000..c8acd0a3 --- /dev/null +++ b/src/lib/opgen_so.cpp @@ -0,0 +1,147 @@ +#include "libbase.h" +#include "libstring.h" +#include "libstring.cpp" + +FILE *fp, *fph, *fpt; + +string data, line, part, subpart; +string output_table, output_header, output_op; + +struct _op_list { + string name, arg; +} op_list[64]; + +int32 op_count, line_num; + +void clear_op_list() { + op_count = 0; + for(int i = 0; i < 64; i++) { + strcpy(op_list[i].name, ""); + for(int l = 0; l < 8; l++) { + strcpy(op_list[i].arg[l], ""); + } + } +} + +void gen_header() { +int i = line_num; +char t[4096]; + clear_op_list(); + while(1) { + int z = op_count++; + strcpy(part, line[i]); + strrtrim(part, "),"); + strrtrim(part, ") {"); + split(subpart, "(", part); + strcpy(op_list[z].name, subpart[0]); + split(part, ", ", subpart[1]); + for(int l = 0; l < count(part); l++) { + strcpy(op_list[z].arg[l], part[l]); + } + if(strend(line[i], " {"))break; + i++; + } + + sprintf(output_op, "void " CLASS_NAME "::op_$$() {\r\n"); + sprintf(output_header, "void op_$$();\r\n"); + sprintf(output_table, "optbl[$0] = &" CLASS_NAME "::op_$$;\r\n"); + + line_num = i + 1; +} + +void update_line(int i) { +char t[4096]; + replace(line[i], "end;", "return;"); +} + +void gen_op() { +int i = line_num, n, c; +char t[4096]; + while(1) { + if(strmatch(line[i], "}"))break; + + n = strdec(line[i]); + sprintf(t, "%d:", n); + strltrim(line[i], t); + //sprintf(t, " case %d: {\r\n", n); + //strcat(output_op, t); + + update_line(i); + if(!strmatch(line[i], "")) { + strcat(output_op, " "); + strcat(output_op, line[i]); + strcat(output_op, "\r\n"); + } + + i++; + while(1) { + if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || strmatch(line[i], "}"))break; + + update_line(i); + strcat(output_op, line[i]); + strcat(output_op, "\r\n"); + + i++; + } + } + + strcat(output_op, "}"); + line_num = i + 1; +} + +void gen_final() { +string t; + for(int i = 0; i < op_count; i++) { + strcpy(t, output_op); + replace(t, "$$", op_list[i].name); + replace(t, "$0", op_list[i].arg[0]); + replace(t, "$1", op_list[i].arg[1]); + replace(t, "$2", op_list[i].arg[2]); + replace(t, "$3", op_list[i].arg[3]); + replace(t, "$4", op_list[i].arg[4]); + replace(t, "$5", op_list[i].arg[5]); + replace(t, "$6", op_list[i].arg[6]); + replace(t, "$7", op_list[i].arg[7]); + fprintf(fp, "%s\r\n\r\n", strptr(t)); + + strcpy(t, output_header); + replace(t, "$$", op_list[i].name); + fprintf(fph, "%s", strptr(t)); + + strcpy(t, output_table); + replace(t, "$$", op_list[i].name); + replace(t, "$0", op_list[i].arg[0]); + fprintf(fpt, "%s", strptr(t)); + } +} + +void generate(char *dest, char *src) { + fp = fopen(src, "rb"); + + fseek(fp, 0, SEEK_END); +int fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); +char *buf = (char*)malloc(fsize + 1); + fread(buf, 1, fsize, fp); + fclose(fp); + buf[fsize] = 0; + + strcpy(data, buf); + free(buf); + replace(data, "\r\n", "\n"); + split(line, "\n", data); + + fp = fopen(dest, "wb"); + + line_num = 0; + while(line_num < count(line)) { + while(strmatch(line[line_num], "") && line_num < count(line))line_num++; + if(line_num >= count(line))break; + + gen_header(); + gen_op(); + gen_final(); + } + + fclose(fp); +} diff --git a/src/memory/bmemory/bmemory.cpp b/src/memory/bmemory/bmemory.cpp index 26554b35..f53a637b 100644 --- a/src/memory/bmemory/bmemory.cpp +++ b/src/memory/bmemory/bmemory.cpp @@ -16,19 +16,27 @@ char t[256]; if(cartridge.cart.srtc)strcat(t, "S-RTC, "); if(cartridge.cart.sdd1)strcat(t, "S-DD1, "); if(cartridge.cart.c4) strcat(t, "Cx4, "); + if(cartridge.cart.dsp1)strcat(t, "DSP-1, "); if(cartridge.cart.dsp2)strcat(t, "DSP-2, "); if(cartridge.cart.obc1)strcat(t, "OBC-1, "); strrtrim(t, ", "); dprintf("* Coprocessor(s) : %s", (strlen(t) == 0) ? "None" : t); - dprintf("* Reset:%0.4x NMI:%0.4x IRQ:%0.4x BRK[n]:%0.4x COP[n]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x", - rom[index + 0x3c] | (rom[index + 0x3d] << 8), //Reset - rom[index + 0x2a] | (rom[index + 0x2b] << 8), //NMI - rom[index + 0x2e] | (rom[index + 0x2f] << 8), //IRQ - rom[index + 0x26] | (rom[index + 0x27] << 8), //BRK[n] - rom[index + 0x24] | (rom[index + 0x25] << 8), //COP[n] - rom[index + 0x3e] | (rom[index + 0x3f] << 8), //BRK[e] - rom[index + 0x34] | (rom[index + 0x35] << 8) //COP[e] + dprintf("* Reset:%0.4x NMI[n]:%0.4x IRQ[n]:%0.4x BRK[n]:%0.4x COP[n]:%0.4x", + read16(rom, index + 0x3c), //Reset + read16(rom, index + 0x2a), //NMI + read16(rom, index + 0x2e), //IRQ + read16(rom, index + 0x26), //BRK + read16(rom, index + 0x24) //COP ); +//BRK[e] should be $fff6, however emulation mode brk is technically not supported. +//this needs verification, but I believe brk jumps to IRQ[e] vector. + dprintf("* NMI[e]:%0.4x IRQ[e]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x", + read16(rom, index + 0x3a), //NMI + read16(rom, index + 0x3e), //IRQ + read16(rom, index + 0x3e), //BRK + read16(rom, index + 0x34) //COP + ); + dprintf("* CRC32 : %0.8x", cartridge.cart.crc32); dprintf(""); cart_map_reset(); @@ -46,6 +54,7 @@ char t[256]; if(cartridge.cart.sdd1)cart_map_sdd1(); if(cartridge.cart.c4) cart_map_c4(); + if(cartridge.cart.dsp1)cart_map_dsp1(); if(cartridge.cart.dsp2)cart_map_dsp2(); if(cartridge.cart.obc1)cart_map_obc1(); diff --git a/src/memory/bmemory/bmemory.h b/src/memory/bmemory/bmemory.h index 2485e8e4..fbf519a1 100644 --- a/src/memory/bmemory/bmemory.h +++ b/src/memory/bmemory/bmemory.h @@ -33,6 +33,8 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART }; void write_sdd1 (uint32 addr, uint8 data); uint8 read_c4 (uint32 addr); void write_c4 (uint32 addr, uint8 data); + uint8 read_dsp1 (uint32 addr); + void write_dsp1 (uint32 addr, uint8 data); uint8 read_dsp2 (uint32 addr); void write_dsp2 (uint32 addr, uint8 data); uint8 read_obc1 (uint32 addr); @@ -44,6 +46,7 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART }; void cart_map_sdd1(); void cart_map_c4(); + void cart_map_dsp1(); void cart_map_dsp2(); void cart_map_obc1(); diff --git a/src/memory/bmemory/bmemory_mapper_generic.cpp b/src/memory/bmemory/bmemory_mapper_generic.cpp index 0cda00a8..f4c55914 100644 --- a/src/memory/bmemory/bmemory_mapper_generic.cpp +++ b/src/memory/bmemory/bmemory_mapper_generic.cpp @@ -1,3 +1,19 @@ +/***** + * Generic LoROM / HiROM / ExHiROM / ExLoROM mapping + * + * Must map the following regions : + * $[00-3f]:[6000-ffff] + * $[40-7d]:[0000-ffff] + * $[80-bf]:[6000-ffff] + * $[c0-ff]:[0000-ffff] + * + * The following regions will be ignored / overwritten : + * $[00-3f]:[0000-1fff] WRAM + * $[00-3f]:[2000-5fff] MMIO + * $[7e-7f]:[0000-ffff] WRAM + * $[80-bf]:[0000-1fff] WRAM + * $[80-bf]:[2000-5fff] MMIO + *****/ void bMemBus::cart_map_generic(uint type) { uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size; ROM_size = cartridge.cart.rom_size; @@ -26,6 +42,12 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size; //layout I can create using only ROM header information. Additional accuracy //requires PCB identification. + //Unmapped region + //$[00-1f|80-9f]:[6000-7fff] + if((bank & 0x7f) >= 0x00 && (bank & 0x7f) <= 0x1f && (addr & 0xe000) == 0x6000) { + continue; + } + //HiROM SRAM region //$[20-3f|a0-bf]:[6000-7fff] if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr & 0xe000) == 0x6000) { @@ -41,7 +63,7 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size; //LoROM SRAM region //$[70-7f|f0-ff]:[0000-7fff] - //Note: RAM is remapped over $[7e-7f]:[0000-ffff] + //Note: WRAM is remapped over $[7e-7f]:[0000-ffff] if((bank & 0x7f) >= 0x70 && (bank & 0x7f) <= 0x7f && (addr & 0x8000) == 0x0000) { if(SRAM_size == 0)continue; @@ -118,6 +140,34 @@ void bMemBus::cart_map_c4() { } } +void bMemBus::cart_map_dsp1() { + if(cartridge.cart.dsp1_mapper == Cartridge::DSP1_LOROM_1MB) { + //$[20-3f]:[8000-ffff] + for(uint bank = 0x20; bank <= 0x3f; bank++) { + for(uint page = 0x80; page <= 0xff; page++) { + page_read [(bank << 8) + page] = &bMemBus::read_dsp1; + page_write[(bank << 8) + page] = &bMemBus::write_dsp1; + } + } + } else if(cartridge.cart.dsp1_mapper == Cartridge::DSP1_LOROM_2MB) { + //$[60-6f]:[0000-7fff] + for(uint bank = 0x60; bank <= 0x6f; bank++) { + for(uint page = 0x00; page <= 0x7f; page++) { + page_read [(bank << 8) + page] = &bMemBus::read_dsp1; + page_write[(bank << 8) + page] = &bMemBus::write_dsp1; + } + } + } else if(cartridge.cart.dsp1_mapper == Cartridge::DSP1_HIROM) { + //$[00-1f]:[6000-7fff] + for(uint bank = 0x00; bank <= 0x1f; bank++) { + for(uint page = 0x60; page <= 0x7f; page++) { + page_read [(bank << 8) + page] = &bMemBus::read_dsp1; + page_write[(bank << 8) + page] = &bMemBus::write_dsp1; + } + } + } +} + void bMemBus::cart_map_dsp2() { //$[20-3f]:[6000-6fff|8000-bfff] for(uint bank = 0x20; bank <= 0x3f; bank++) { diff --git a/src/memory/bmemory/bmemory_rw.cpp b/src/memory/bmemory/bmemory_rw.cpp index 4e18d41d..99fac6e8 100644 --- a/src/memory/bmemory/bmemory_rw.cpp +++ b/src/memory/bmemory/bmemory_rw.cpp @@ -54,6 +54,9 @@ void bMemBus::write_sdd1(uint32 addr, uint8 data) { uint8 bMemBus::read_c4 (uint32 addr) { return c4->read(addr); } void bMemBus::write_c4(uint32 addr, uint8 data) { c4->write(addr, data); } +uint8 bMemBus::read_dsp1 (uint32 addr) { return dsp1->read(addr); } +void bMemBus::write_dsp1(uint32 addr, uint8 data) { dsp1->write(addr, data); } + uint8 bMemBus::read_dsp2 (uint32 addr) { return dsp2->read(addr); } void bMemBus::write_dsp2(uint32 addr, uint8 data) { dsp2->write(addr, data); } diff --git a/src/memory/memory.h b/src/memory/memory.h index da6af50f..805f6270 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -29,9 +29,9 @@ private: uint8 *speed_table, speed_table_slowrom[32768], speed_table_fastrom[32768]; - inline uint8 calc_speed(uint32 addr, bool fast); + uint8 calc_speed(uint32 addr, bool fast); public: - inline uint8 speed(uint32 addr) { return speed_table[addr >> 9]; } + uint8 speed(uint32 addr) { return speed_table[addr >> 9]; } void set_speed(bool fast); virtual void load_cart() = 0; diff --git a/src/ppu/bppu/bppu_mmio.cpp b/src/ppu/bppu/bppu_mmio.cpp index d90eddf9..440f9085 100644 --- a/src/ppu/bppu/bppu_mmio.cpp +++ b/src/ppu/bppu/bppu_mmio.cpp @@ -23,18 +23,14 @@ bool bPPU::vram_can_read() { uint16 v = r_cpu->vcounter(); uint16 hc = r_cpu->hcycles(); -uint16 ls; - if(r_cpu->interlace() && !r_cpu->interlace_field()) { - ls = r_cpu->region_scanlines(); - } else { - ls = r_cpu->region_scanlines() - 1; - } +uint16 ls = (r_cpu->region_scanlines() >> 1) - 1; + if(r_cpu->interlace() && !r_cpu->interlace_field())ls++; if(v == ls && hc == 1362)return false; - if(v < (r_cpu->overscan() ? 239 : 224))return false; + if(v < (!r_cpu->overscan() ? 224 : 239))return false; - if(v == (r_cpu->overscan() ? 239 : 224)) { + if(v == (!r_cpu->overscan() ? 224 : 239)) { if(hc == 1362)return true; return false; } diff --git a/src/ppu/bppu/bppu_render.h b/src/ppu/bppu/bppu_render.h index 87bbb79f..7e7de347 100644 --- a/src/ppu/bppu/bppu_render.h +++ b/src/ppu/bppu/bppu_render.h @@ -44,8 +44,9 @@ void build_window_tables(uint8 bg); //bppu_render_bg.cpp struct { - uint16 tw, th; //tile width, height - uint16 mx, my; //screen mask x, y + uint16 tw, th; //tile width, height + uint16 mx, my; //screen mask x, y + uint16 scx, scy; //sc index offsets } bg_info[4]; inline void update_bg_info(); diff --git a/src/ppu/bppu/bppu_render_bg.cpp b/src/ppu/bppu/bppu_render_bg.cpp index f9f99014..d5a7d400 100644 --- a/src/ppu/bppu/bppu_render_bg.cpp +++ b/src/ppu/bppu/bppu_render_bg.cpp @@ -3,26 +3,27 @@ void bPPU::update_bg_info() { for(int bg = 0; bg < 4; bg++) { bg_info[bg].th = (regs.bg_tilesize[bg]) ? 4 : 3; bg_info[bg].tw = (regs.hires) ? 4 : bg_info[bg].th; + bg_info[bg].mx = (bg_info[bg].th == 4) ? (line.width << 1) : line.width; bg_info[bg].my = bg_info[bg].mx; if(regs.bg_scsize[bg] & 0x01)bg_info[bg].mx <<= 1; if(regs.bg_scsize[bg] & 0x02)bg_info[bg].my <<= 1; bg_info[bg].mx--; bg_info[bg].my--; + + bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0; + bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0; + if(regs.bg_scsize[bg] == 3)bg_info[bg].scy <<= 1; } } uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) { -uint16 pos; - x &= bg_info[bg].mx; - y &= bg_info[bg].my; + x = (x & bg_info[bg].mx) >> bg_info[bg].tw; + y = (y & bg_info[bg].my) >> bg_info[bg].th; - x >>= bg_info[bg].tw; - y >>= bg_info[bg].th; - - pos = (regs.bg_scsize[bg] & 2) ? ((y & 0x20) << ((regs.bg_scsize[bg] & 1) ? 6 : 5)) : 0; - pos += (regs.bg_scsize[bg] & 1) ? ((x & 0x20) << 5) : 0; - pos += ((y & 31) << 5) + (x & 31); +uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f); + if(y & 0x20)pos += bg_info[bg].scy; + if(x & 0x20)pos += bg_info[bg].scx; return read16(vram, regs.bg_scaddr[bg] + (pos << 1)); } @@ -56,11 +57,11 @@ void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri bool bg_enabled = regs.bg_enabled[bg]; bool bgsub_enabled = regs.bgsub_enabled[bg]; -uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : ((bg == BG2) ? 0x4000 : 0x0000); +uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : (bg == BG2) ? 0x4000 : 0x0000; uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0; -uint8 pal_size = (color_depth == 2) ? 256 : ((color_depth == 1) ? 16 : 4); -uint16 tile_mask = (color_depth == 2) ? 0x03ff : ((color_depth == 1) ? 0x07ff : 0x0fff); +uint8 pal_size = 2 << color_depth; //<<2 (*4), <<4 (*16), <<8 (*256) +uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff //4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile //index is a tile number count to add to base tile number uint tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth); @@ -95,7 +96,7 @@ uint8 *tile_ptr; uint xpos, ypos; uint16 hoffset, voffset, opt_x, col; bool mirror_x, mirror_y; -bool is_opt_mode = (config::ppu.opt_enable) && (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6); +bool is_opt_mode = (config::ppu.opt_enable == true) && (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6); build_window_tables(bg); uint8 *wt_main = window[bg].main; @@ -170,7 +171,7 @@ int32 prev_x = -1, prev_y = -1; } pal_num = ((t >> 10) & 7); - pal_index = (pal_num * pal_size) + bgpal_index; + pal_index = bgpal_index + (pal_num << pal_size); ypos = mosaic_y & 7; if(mirror_y)ypos ^= 7; //invert y tile pos diff --git a/src/ppu/bppu/bppu_render_mode7.cpp b/src/ppu/bppu/bppu_render_mode7.cpp index a396df8a..6d09416e 100644 --- a/src/ppu/bppu/bppu_render_mode7.cpp +++ b/src/ppu/bppu/bppu_render_mode7.cpp @@ -25,16 +25,15 @@ void bPPU::render_line_mode7(uint8 bg, uint8 pri0_pos, uint8 pri1_pos) { int32 px, py; int32 tx, ty, tile, palette; -int32 a = int32(int16(regs.m7a)); -int32 b = int32(int16(regs.m7b)); -int32 c = int32(int16(regs.m7c)); -int32 d = int32(int16(regs.m7d)); +int32 a = sclip<15>(regs.m7a); //int32(int16(regs.m7a)); +int32 b = sclip<15>(regs.m7b); //int32(int16(regs.m7b)); +int32 c = sclip<15>(regs.m7c); //int32(int16(regs.m7c)); +int32 d = sclip<15>(regs.m7d); //int32(int16(regs.m7d)); -int32 cx = (int32(regs.m7x) << 19) >> 19; -int32 cy = (int32(regs.m7y) << 19) >> 19; -int32 hofs = (int32(regs.m7_hofs) << 19) >> 19; -//+1 breaks FF5 title screen mirror alignment... -int32 vofs = (int32(regs.m7_vofs + 0) << 19) >> 19; +int32 cx = sclip<13>(regs.m7x); //(int32(regs.m7x) << 19) >> 19; +int32 cy = sclip<13>(regs.m7y); //(int32(regs.m7y) << 19) >> 19; +int32 hofs = sclip<13>(regs.m7_hofs); //(int32(regs.m7_hofs) << 19) >> 19; +int32 vofs = sclip<13>(regs.m7_vofs); //(int32(regs.m7_vofs + 0) << 19) >> 19; int _pri, _x; bool _bg_enabled = regs.bg_enabled[bg]; @@ -59,6 +58,10 @@ uint16 *mtable_x, *mtable_y; int32 psx = ((a * CLIP(hofs - cx)) & ~63) + ((b * CLIP(vofs - cy)) & ~63) + ((b * mtable_y[y]) & ~63) + (cx << 8); int32 psy = ((c * CLIP(hofs - cx)) & ~63) + ((d * CLIP(vofs - cy)) & ~63) + ((d * mtable_y[y]) & ~63) + (cy << 8); +//suggestion by TRAC, difference can be no greater than 1 bit (due to rounding) from above, +//but verification would be good... +//int32 psx = ((a * CLIP(hofs - cx)) & ~63) + ((b * (CLIP(vofs - cy) + mtable_y[y])) & ~63) + (cx << 8); +//int32 psy = ((c * CLIP(hofs - cx)) & ~63) + ((d * (CLIP(vofs - cy) + mtable_y[y])) & ~63) + (cy << 8); for(int32 x = 0; x < 256; x++) { px = psx + (a * mtable_x[x]); py = psy + (c * mtable_x[x]); diff --git a/src/ppu/bppu/bppu_render_oam.cpp b/src/ppu/bppu/bppu_render_oam.cpp index 9bb31884..7d71961d 100644 --- a/src/ppu/bppu/bppu_render_oam.cpp +++ b/src/ppu/bppu/bppu_render_oam.cpp @@ -26,9 +26,12 @@ uint8 *tableA = oam, *tableB = oam + 512; break; case 6: sprite_list[i].width = (!size) ? 16 : 32; sprite_list[i].height = (!size) ? 32 : 64; + if(regs.oam_interlace && !size)sprite_list[i].height = 16; + //32x64 height is not affected by oam_interlace setting break; case 7: sprite_list[i].width = (!size) ? 16 : 32; sprite_list[i].height = (!size) ? 32 : 32; + if(regs.oam_interlace && !size)sprite_list[i].height = 16; break; } @@ -48,40 +51,35 @@ uint8 *tableA = oam, *tableB = oam + 512; bool bPPU::is_sprite_on_scanline() { //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, -//then it is not counted. 256 is correct, and not 255 -- as one might first expect - if(spr->x > 256 && (spr->x + spr->width) < 512)return false; - - if(regs.oam_interlace == false) { - if(line.y >= spr->y && line.y < (spr->y + spr->height)) { - return true; - } else if((spr->y + spr->height) >= 256 && line.y < ((spr->y + spr->height) & 255)) { - return true; - } - } else { - if(line.y >= spr->y && line.y < (spr->y + (spr->height >> 1))) { - return true; - } else if((spr->y + (spr->height >> 1)) >= 256 && line.y < ((spr->y + (spr->height >> 1)) & 255)) { - return true; - } - } +//then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. + if(spr->x > 256 && (spr->x + spr->width - 1) < 512)return false; +int spr_height = (regs.oam_interlace == false) ? (spr->height) : (spr->height >> 1); + if(line.y >= spr->y && line.y < (spr->y + spr_height))return true; + if((spr->y + spr_height) >= 256 && line.y < ((spr->y + spr_height) & 255))return true; return false; } void bPPU::load_oam_tiles() { uint16 tile_width = spr->width >> 3; int x = spr->x; -int y = (spr->vflip) ? ((spr->height - 1) - (line.y - spr->y)) : (line.y - spr->y); - -//todo: verify below code is hardware-accurate -//specifically, is interlace_field added for oam_interlace mode? +int y = line.y - spr->y; if(regs.oam_interlace == true) { y <<= 1; - if(line.interlace && line.width == 512) { - y += line.interlace_field; + } + + if(spr->vflip == true) { + if(spr->width == spr->height) { + y = (spr->height - 1) - y; + } else { + y = (y < spr->width) ? ((spr->width - 1) - y) : (spr->width + ((spr->width - 1) - (y - spr->width))); } } + if(regs.oam_interlace == true) { + y = (spr->vflip == false) ? (y + line.interlace_field) : (y - line.interlace_field); + } + x &= 511; y &= 255; @@ -95,47 +93,39 @@ uint16 chry = (spr->character >> 4) & 15; chry &= 15; chry <<= 4; -int i, n, sx, mx, pos; - for(i=0;i= 257 && (sx + 7) < 512)continue; + for(uint tx = 0; tx < tile_width; tx++) { + uint sx = (x + (tx << 3)) & 511; + if(sx > 256 && (sx + 7) < 512)continue; //ignore sprites that are offscreen if(regs.oam_tilecount++ > 34)break; - n = regs.oam_tilecount - 1; + uint n = regs.oam_tilecount - 1; oam_tilelist[n].x = sx; oam_tilelist[n].y = y; oam_tilelist[n].pri = spr->priority; - oam_tilelist[n].pal = (spr->palette << 4) + 128; + oam_tilelist[n].pal = 128 + (spr->palette << 4); oam_tilelist[n].hflip = spr->hflip; - mx = (oam_tilelist[n].hflip) ? ((tile_width - 1) - i) : i; - pos = tdaddr + ((chry + ((chrx + mx) & 15)) << 5); + uint mx = (spr->hflip == false) ? tx : ((tile_width - 1) - tx); + uint pos = tdaddr + ((chry + ((chrx + mx) & 15)) << 5); oam_tilelist[n].tile = (pos >> 5) & 0x07ff; } } void bPPU::render_oam_tile(int tile_num) { -uint8 *oam_td, *oam_td_state, *tile_ptr; -oam_tileitem *t = &oam_tilelist[tile_num]; - oam_td = (uint8*)bg_tiledata[COLORDEPTH_16]; - oam_td_state = (uint8*)bg_tiledata_state[COLORDEPTH_16]; +oam_tileitem *t = &oam_tilelist[tile_num]; +uint8 *oam_td = (uint8*)bg_tiledata[COLORDEPTH_16]; +uint8 *oam_td_state = (uint8*)bg_tiledata_state[COLORDEPTH_16]; if(oam_td_state[t->tile] == 1) { render_bg_tile(COLORDEPTH_16, t->tile); } -int x, sx, col; - sx = t->x; - tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3); - for(x=0;x<8;x++) { +uint sx = t->x; +uint8 *tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3); + for(uint x = 0; x < 8; x++) { sx &= 511; if(sx < 256) { - col = *(tile_ptr + ((t->hflip) ? (7 - x) : x)); + uint col = *(tile_ptr + ((t->hflip == false) ? x : (7 - x))); if(col) { col += t->pal; oam_line_pal[sx] = col; @@ -152,8 +142,9 @@ void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 regs.oam_itemcount = 0; regs.oam_tilecount = 0; memset(oam_line_pri, OAM_PRI_NONE, 256); - memset(oam_itemlist, 0xff, 32); + for(int s = 0; s < 34; s++)oam_tilelist[s].tile = 0xffff; + for(int s = 0; s < 128; s++) { spr = &sprite_list[(s + regs.oam_firstsprite) & 127]; if(is_sprite_on_scanline() == false)continue; @@ -161,8 +152,6 @@ void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 oam_itemlist[regs.oam_itemcount - 1] = (s + regs.oam_firstsprite) & 127; } - for(int s = 0; s < 34; s++)oam_tilelist[s].tile = 0xffff; - for(int s = 31; s >= 0; s--) { if(oam_itemlist[s] == 0xff)continue; spr = &sprite_list[oam_itemlist[s]]; @@ -213,17 +202,11 @@ bool bgsub_enabled = regs.bgsub_enabled[OAM]; uint8 *wt_main = window[OAM].main; uint8 *wt_sub = window[OAM].sub; -int pri; +int pri_tbl[4] = { pri0_pos, pri1_pos, pri2_pos, pri3_pos }; for(int x = 0; x < 256; x++) { if(oam_line_pri[x] == OAM_PRI_NONE)continue; - switch(oam_line_pri[x]) { - case 0: pri = pri0_pos; break; - case 1: pri = pri1_pos; break; - case 2: pri = pri2_pos; break; - case 3: pri = pri3_pos; break; - } - + int pri = pri_tbl[oam_line_pri[x]]; if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); } if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); } } diff --git a/src/sdl/Makefile b/src/sdl/Makefile index 0afba2ea..c49a9f84 100644 --- a/src/sdl/Makefile +++ b/src/sdl/Makefile @@ -4,14 +4,14 @@ CFLAGS = -O3 -fomit-frame-pointer -ffast-math CXXFLAGS = $(CFLAGS) -fno-rtti OBJS = sdlmain.o \ libstring.o libconfig.o libbpf.o \ - reader.o cart.o cheat.o \ + reader.o cart.o \ memory.o bmemory.o \ cpu.o bcpu.o \ apu.o bapu.o \ bdsp.o \ ppu.o bppu.o \ snes.o \ - srtc.o sdd1.o c4.o dsp2.o obc1.o \ + srtc.o sdd1.o c4.o \ adler32.o compress.o crc32.o deflate.o gzio.o inffast.o \ inflate.o inftrees.o ioapi.o trees.o unzip.o zip.o zutil.o \ jma.o jcrc32.o lzmadec.o 7zlzma.o iiostrm.o inbyte.o lzma.o winout.o @@ -89,9 +89,6 @@ reader.o: ../reader/*.cpp ../reader/*.h cart.o: ../cart/*.cpp ../cart/*.h $(CXX) $(CXXFLAGS) -c ../cart/cart.cpp -cheat.o: ../cheat/*.cpp ../cheat/*.h - $(CXX) $(CXXFLAGS) -c ../cheat/cheat.cpp - ############ ### snes ### ############ @@ -110,12 +107,6 @@ sdd1.o: ../chip/sdd1/*.cpp ../chip/sdd1/*.h c4.o: ../chip/c4/*.cpp ../chip/c4/*.h $(CXX) $(CXXFLAGS) -c ../chip/c4/c4.cpp -dsp2.o: ../chip/dsp2/*.cpp ../chip/dsp2/*.h - $(CXX) $(CXXFLAGS) -c ../chip/dsp2/dsp2.cpp - -obc1.o: ../chip/obc1/*.cpp ../chip/obc1/*.h - $(CXX) $(CXXFLAGS) -c ../chip/obc1/obc1.cpp - ############ ### zlib ### ############ diff --git a/src/sdl/Makefile.win32 b/src/sdl/Makefile.win32 index c230f138..f25aff99 100644 --- a/src/sdl/Makefile.win32 +++ b/src/sdl/Makefile.win32 @@ -1,5 +1,5 @@ CC = cl -CFLAGS = /nologo /O2 /EHsc /wd4996 +CFLAGS = /nologo /O2 /EHsc OBJS = sdlmain.obj \ libstring.obj libconfig.obj libbpf.obj \ reader.obj cart.obj \ diff --git a/src/sdl/bsnes_sdl.cfg b/src/sdl/bsnes_sdl.cfg new file mode 100644 index 00000000..cc1ac3db --- /dev/null +++ b/src/sdl/bsnes_sdl.cfg @@ -0,0 +1,98 @@ +# Default path to look for ROM files in ("" = use default directory) +# (default = "") +fs.rom_path = "" + +# Default path for all save RAM files ("" = use current directory) +# (default = "") +fs.sram_path = "" + +# Extension to be used for all save RAM files +# (default = "srm") +fs.sram_ext = "srm" + +# Applies contrast adjust filter to video output when enabled +# Works by lowering the brightness of darker colors, +# while leaving brighter colors alone; thus reducing saturation +# (default = true) +snes.video_color_curve = true + +# Selects color adjustment filter for video output +# 0 = Normal (no filter, rgb555) +# 1 = Grayscale mode (l5) +# 2 = VGA mode (rgb332) +# 3 = Genesis mode (rgb333) +# (default = 0) +snes.video_color_adjust_mode = 0 + +# Mutes SNES audio output when enabled +# (default = false) +snes.mute = true + +# Enable fullscreen mode at startup +# (default = false) +video.fullscreen = false + +# Window / Fullscreen width +# (default = 320) +video.display_width = 320 + +# Window / Fullscreen height +# (default = 240) +video.display_height = 240 + +# SNES video output width +# (default = 256) +video.output_width = 256 + +# SNES video output height +# (default = 223) +video.output_height = 223 + +# Joypad1 up +# (default = 0x111) +input.joypad1.up = 0x111 + +# Joypad1 down +# (default = 0x112) +input.joypad1.down = 0x112 + +# Joypad1 left +# (default = 0x114) +input.joypad1.left = 0x114 + +# Joypad1 right +# (default = 0x113) +input.joypad1.right = 0x113 + +# Joypad1 A +# (default = 0x78) +input.joypad1.a = 0x78 + +# Joypad1 B +# (default = 0x7a) +input.joypad1.b = 0x7a + +# Joypad1 X +# (default = 0x73) +input.joypad1.x = 0x73 + +# Joypad1 Y +# (default = 0x61) +input.joypad1.y = 0x61 + +# Joypad1 L +# (default = 0x64) +input.joypad1.l = 0x64 + +# Joypad1 R +# (default = 0x63) +input.joypad1.r = 0x63 + +# Joypad1 select +# (default = 0x12f) +input.joypad1.select = 0x12f + +# Joypad1 start +# (default = 0xd) +input.joypad1.start = 0xd + diff --git a/src/sdl/sdlmain.cpp b/src/sdl/sdlmain.cpp index ff05cace..317829f9 100644 --- a/src/sdl/sdlmain.cpp +++ b/src/sdl/sdlmain.cpp @@ -122,9 +122,9 @@ SDL_Event event; atexit(SDL_Quit); set_window_info(); screen = SDL_SetVideoMode(config::video.display_width, config::video.display_height, 16, - SDL_SWSURFACE | ((config::video.fullscreen) ? SDL_FULLSCREEN : 0)); + SDL_HWSURFACE | ((config::video.fullscreen) ? SDL_FULLSCREEN : 0)); if(!screen) { alert("Failed to initialize SDL"); goto _end; } - backbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000); + backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000); if(!backbuffer) { alert("Failed to initialize SDL"); goto _end; } SDL_WM_SetCaption(BSNES_TITLE, 0); diff --git a/src/snes/snes.cpp b/src/snes/snes.cpp index 0ad3ce4a..59c9bb6e 100644 --- a/src/snes/snes.cpp +++ b/src/snes/snes.cpp @@ -6,19 +6,19 @@ #include "input/input.cpp" void SNES::run() { - if(apusync.cycles < 0) { + if(sync.counter <= 0) { r_cpu->run(); - apusync.cycles += apusync.apu_multbl[r_cpu->cycles_executed()]; + uint32 clocks = r_cpu->clocks_executed(); + sync.counter += sync.apu_multbl[clocks]; } else { r_apu->run(); - uint32 cycles = r_apu->cycles_executed(); - apusync.dsp += cycles; - apusync.cycles -= apusync.cpu_multbl[cycles]; - + uint32 clocks = r_apu->clocks_executed(); + sync.counter -= sync.cpu_multbl[clocks]; //1024000(SPC700) / 32000(DSP) = 32spc/dsp ticks //24576000(Sound clock crystal) / 32000(DSP) = 768crystal/dsp ticks - while(apusync.dsp >= 768) { - apusync.dsp -= 768; + sync.dsp_counter += clocks; + while(sync.dsp_counter >= 768) { + sync.dsp_counter -= 768; audio_update(r_dsp->run()); } } @@ -35,12 +35,14 @@ void SNES::init() { srtc = new SRTC(); sdd1 = new SDD1(); c4 = new C4(); + dsp1 = new DSP1(); dsp2 = new DSP2(); obc1 = new OBC1(); srtc->init(); sdd1->init(); c4->init(); + dsp1->init(); dsp2->init(); obc1->init(); @@ -62,6 +64,7 @@ void SNES::power() { if(cartridge.cart.srtc)srtc->power(); if(cartridge.cart.sdd1)sdd1->power(); if(cartridge.cart.c4) c4->power(); + if(cartridge.cart.dsp1)dsp1->power(); if(cartridge.cart.dsp2)dsp2->power(); if(cartridge.cart.obc1)obc1->power(); @@ -69,15 +72,14 @@ void SNES::power() { for(int i = 0x2100; i <= 0x213f; i++)r_mem->set_mmio_mapper(i, r_ppu); for(int i = 0x2140; i <= 0x217f; i++)r_mem->set_mmio_mapper(i, r_cpu); for(int i = 0x2180; i <= 0x2183; i++)r_mem->set_mmio_mapper(i, r_cpu); -//input - r_mem->set_mmio_mapper(0x4016, r_cpu); - r_mem->set_mmio_mapper(0x4017, r_cpu); + for(int i = 0x4016; i <= 0x4017; i++)r_mem->set_mmio_mapper(i, r_cpu); for(int i = 0x4200; i <= 0x421f; i++)r_mem->set_mmio_mapper(i, r_cpu); for(int i = 0x4300; i <= 0x437f; i++)r_mem->set_mmio_mapper(i, r_cpu); if(cartridge.cart.srtc)srtc->enable(); if(cartridge.cart.sdd1)sdd1->enable(); if(cartridge.cart.c4) c4->enable(); + if(cartridge.cart.dsp1)dsp1->enable(); if(cartridge.cart.dsp2)dsp2->enable(); if(cartridge.cart.obc1)obc1->enable(); @@ -85,7 +87,8 @@ void SNES::power() { } void SNES::reset() { - apusync.cycles = -apusync.cpu_multbl[32]; + sync.counter = -sync.cpu_multbl[32]; + sync.dsp_counter = 0; r_cpu->reset(); r_apu->reset(); @@ -96,6 +99,7 @@ void SNES::reset() { if(cartridge.cart.srtc)srtc->reset(); if(cartridge.cart.sdd1)sdd1->reset(); if(cartridge.cart.c4) c4->reset(); + if(cartridge.cart.dsp1)dsp1->reset(); if(cartridge.cart.dsp2)dsp2->reset(); if(cartridge.cart.obc1)obc1->reset(); @@ -137,17 +141,13 @@ uint8 SNES::region() { return snes_region; } **************/ void SNES::update_timing() { - apusync.cycles = 0; - if(snes_region == NTSC) { - apusync.cpu_freq = 21477272 >> 3; - } else if(snes_region == PAL) { - apusync.cpu_freq = 21281370 >> 3; - } - apusync.apu_freq = 24576000 >> 3; + sync.counter = 0; + sync.cpu_freq = (snes_region == NTSC) ? 21477272 : 21281370; + sync.apu_freq = 24576000; - for(int i = 0; i < 1024; i++) { - apusync.cpu_multbl[i] = i * apusync.cpu_freq; - apusync.apu_multbl[i] = i * apusync.apu_freq; + for(int64 i = 0; i < 1024; i++) { + sync.cpu_multbl[i] = i * sync.cpu_freq; + sync.apu_multbl[i] = i * sync.apu_freq; } } diff --git a/src/snes/snes.h b/src/snes/snes.h index 2cb8b9b2..9124e003 100644 --- a/src/snes/snes.h +++ b/src/snes/snes.h @@ -2,20 +2,17 @@ class VideoFilter; class SNES { protected: -bool is_debugger_enabled; +bool is_debugger_enabled; +uint8 snes_region; -uint8 snes_region; - -//APU synchronization +//CPU<>APU synchronization struct { - int32 cpu_freq, apu_freq; - int32 cpu_multbl[1024], apu_multbl[1024]; - int32 cycles; + int64 counter, dsp_counter; + int64 cpu_freq, apu_freq; + int64 cpu_multbl[1024], apu_multbl[1024]; +} sync; - int32 dsp; -} apusync; - -void update_timing(); + void update_timing(); public: enum { NTSC = 0, PAL = 1 }; @@ -23,6 +20,7 @@ enum { NTSC = 0, PAL = 1 }; //system functions virtual inline void run(); virtual inline void runtoframe(); + virtual void init(); virtual void term(); virtual void power(); @@ -32,8 +30,8 @@ enum { NTSC = 0, PAL = 1 }; virtual void scanline(); //PAL/NTSC - uint8 region(); - void set_region(uint8 new_region); + uint8 region(); + void set_region(uint8 new_region); #include "video/video.h" #include "audio/audio.h" diff --git a/src/snes/video/filter_ntsc.cpp b/src/snes/video/filter_ntsc.cpp index c94a0f42..d38edd5b 100644 --- a/src/snes/video/filter_ntsc.cpp +++ b/src/snes/video/filter_ntsc.cpp @@ -5,7 +5,7 @@ NtscVideoFilter::NtscVideoFilter() { ntsc = 0; //to do: defer initialization? - adjust(0, 0, 0, 0, 0, bool(config::snes.ntsc_merge_fields), 0); //snes->color_lookup_table); + adjust(0, 0, 0, 0, 0, bool(config::snes.ntsc_merge_fields), 0); } NtscVideoFilter::~NtscVideoFilter() { @@ -50,13 +50,12 @@ int const out_height = height; result_width = out_width; result_height = out_height; burst ^= burst_toggle; - pitch >>= 1; if(!scanline_widths) { if(width == 256) { - snes_ntsc_blit(ntsc, data, pitch, burst, out_width, out_height, output, output_pitch); + snes_ntsc_blit(ntsc, data, (pitch >> 1), burst, out_width, out_height, output, output_pitch); } else { - snes_ntsc_blit_hires(ntsc, data, pitch, burst, out_width, out_height, output, output_pitch); + snes_ntsc_blit_hires(ntsc, data, (pitch >> 1), burst, out_width, out_height, output, output_pitch); } } else { //blit multiple scanlines of same width, rather than one at a time @@ -66,14 +65,14 @@ int const out_height = height; while(1) { if(run_width != scanline_widths[line] || line >= out_height) { - uint16 const *in = (uint16*)((char*)data + pitch * run_start); - uint16 *out = (uint16*)((char*)output + output_pitch * run_start); + uint16 const *in = (uint16*)((uint8*)data + pitch * run_start); + uint16 *out = (uint16*)((uint8*)output + output_pitch * run_start); int height = line - run_start; int line_burst = (burst + run_start) % 3; if(run_width == 256) { - snes_ntsc_blit(ntsc, in, pitch, line_burst, out_width, height, out, output_pitch); + snes_ntsc_blit(ntsc, in, (pitch >> 1), line_burst, out_width, height, out, output_pitch); } else { - snes_ntsc_blit_hires(ntsc, in, pitch, line_burst, out_width, height, out, output_pitch); + snes_ntsc_blit_hires(ntsc, in, (pitch >> 1), line_burst, out_width, height, out, output_pitch); } if(line >= out_height)break; run_width = scanline_widths[line]; diff --git a/src/snes/video/filter_ntsc_core.cpp b/src/snes/video/filter_ntsc_core.cpp index 4ac5a6e5..9466b225 100644 --- a/src/snes/video/filter_ntsc_core.cpp +++ b/src/snes/video/filter_ntsc_core.cpp @@ -1,4 +1,3 @@ - /* snes_ntsc 0.2.1. http://www.slack.net/~ant/ */ /* compilable in C or C++; just change the file extension */ diff --git a/src/snes/video/filter_ntsc_core.h b/src/snes/video/filter_ntsc_core.h index df1418fe..fa6ad8a7 100644 --- a/src/snes/video/filter_ntsc_core.h +++ b/src/snes/video/filter_ntsc_core.h @@ -1,4 +1,3 @@ - /* SNES NTSC composite video to RGB emulator/blitter */ /* snes_ntsc 0.2.1 */ diff --git a/src/snes/video/video_colortable.cpp b/src/snes/video/video_colortable.cpp index b330a050..fcf4acbf 100644 --- a/src/snes/video/video_colortable.cpp +++ b/src/snes/video/video_colortable.cpp @@ -10,19 +10,19 @@ double lmin, lmax; lmin = 0.0 - double(int32(config::snes.contrast)); lmax = 255.0 + double(int32(config::snes.contrast)); int32 result = int32(lmin + double(input) * ((lmax - lmin) / 256.0)); - input = bound_range(result, 0, 255); + input = minmax<0, 255>(result); } void SNES::brightness_adjust(int32 &input) { int32 result; result = input + int32(config::snes.brightness); - input = bound_range(result, 0, 255); + input = minmax<0, 255>(result); } void SNES::gamma_adjust(int32 &input) { int32 result; result = int32(pow((double(input + 1) / 256.0), double(config::snes.gamma) / 100.0) * 256.0); - input = bound_range(result, 0, 255); + input = minmax<0, 255>(result); } void SNES::update_color_lookup_table() { @@ -55,14 +55,14 @@ uint32 col; r = int32(double(l) * (1.0 + 0.300)); g = int32(double(l) * (1.0 - 0.055)); b = int32(double(l) * (1.0 - 0.225)); - r = bound_range(r, 0, 255); - g = bound_range(g, 0, 255); - b = bound_range(b, 0, 255); + r = minmax<0, 255>(r); + g = minmax<0, 255>(g); + b = minmax<0, 255>(b); } if(bool(config::snes.grayscale) == true) { l = int32(double(r) * kr + double(g) * kg + double(b) * kb); - l = bound_range(l, 0, 255); + l = minmax<0, 255>(l); r = g = b = l; } diff --git a/src/win/Makefile b/src/win/Makefile index 653d3e0e..c4e56da1 100644 --- a/src/win/Makefile +++ b/src/win/Makefile @@ -1,16 +1,21 @@ CC = cl -CFLAGS = /nologo /O2 /arch:SSE2 /wd4996 -#CFLAGS = /nologo /O2 /GL /EHsc /wd4996 +AS = nasm +CFLAGS = /nologo /O2 /arch:SSE2 +#CFLAGS = /nologo /O2 /GL /arch:SSE2 +#CFLAGS = /nologo /O2 /GL /EHsc +COMPILE = $(CC) $(CFLAGS) /c +ASSEMBLE = $(AS) -f win32 + OBJS = main.obj \ - libstring.obj libconfig.obj libbpf.obj \ + libco.obj libstring.obj libconfig.obj libbpf.obj \ reader.obj cart.obj cheat.obj \ memory.obj bmemory.obj \ - cpu.obj bcpu.obj \ - apu.obj bapu.obj \ + cpu.obj scpu.obj bcpu.obj \ + apu.obj sapu.obj bapu.obj \ bdsp.obj \ ppu.obj bppu.obj \ snes.obj \ - srtc.obj sdd1.obj c4.obj dsp2.obj obc1.obj + srtc.obj sdd1.obj c4.obj dsp1.obj dsp2.obj obc1.obj # adler32.obj compress.obj crc32.obj deflate.obj gzio.obj inffast.obj \ # inflate.obj inftrees.obj ioapi.obj trees.obj unzip.obj zip.obj zutil.obj \ # jma.obj jcrc32.obj lzmadec.obj 7zlzma.obj iiostrm.obj inbyte.obj lzma.obj winout.obj @@ -35,104 +40,118 @@ clean: ### win32-specific ### ###################### main.obj: *.cpp *.h video/* audio/* input/* settings/* debugger/* ../config/* - $(CC) $(CFLAGS) /c main.cpp + $(COMPILE) main.cpp ################# ### libraries ### ################# +libco.obj: ../lib/* + $(ASSEMBLE) -o libco.obj ../lib/libco_x86.asm + libstring.obj: ../lib/*.cpp ../lib/*.h - $(CC) $(CFLAGS) /c ../lib/libstring.cpp + $(COMPILE) ../lib/libstring.cpp + libconfig.obj: ../lib/*.cpp ../lib/*.h - $(CC) $(CFLAGS) /c ../lib/libconfig.cpp + $(COMPILE) ../lib/libconfig.cpp + libbpf.obj: ../lib/*.cpp ../lib/*.h - $(CC) $(CFLAGS) /c ../lib/libbpf.cpp + $(COMPILE) ../lib/libbpf.cpp ############## ### memory ### ############## memory.obj: ../memory/memory.cpp ../memory/memory.h - $(CC) $(CFLAGS) /c ../memory/memory.cpp + $(COMPILE) ../memory/memory.cpp bmemory.obj: ../memory/bmemory/* - $(CC) $(CFLAGS) /c ../memory/bmemory/bmemory.cpp + $(COMPILE) ../memory/bmemory/bmemory.cpp ########### ### cpu ### ########### -cpu.obj: ../cpu/*.cpp ../cpu/*.h - $(CC) $(CFLAGS) /c ../cpu/cpu.cpp +cpu.obj: ../cpu/* + $(COMPILE) ../cpu/cpu.cpp + +scpu.obj: ../cpu/scpu/* ../cpu/scpu/core/* ../cpu/scpu/dma/* ../cpu/scpu/memory/* ../cpu/scpu/mmio/* ../cpu/scpu/timing/* + $(COMPILE) ../cpu/scpu/scpu.cpp bcpu.obj: ../cpu/bcpu/* - $(CC) $(CFLAGS) /c ../cpu/bcpu/bcpu.cpp + $(COMPILE) ../cpu/bcpu/bcpu.cpp ########### ### apu ### ########### apu.obj: ../apu/* - $(CC) $(CFLAGS) /c ../apu/apu.cpp + $(COMPILE) ../apu/apu.cpp + +sapu.obj: ../apu/sapu/* ../apu/sapu/core/* ../apu/sapu/memory/* ../apu/sapu/timing/* + $(COMPILE) ../apu/sapu/sapu.cpp bapu.obj: ../apu/bapu/* - $(CC) $(CFLAGS) /c ../apu/bapu/bapu.cpp + $(COMPILE) ../apu/bapu/bapu.cpp ########### ### dsp ### ########### bdsp.obj: ../dsp/bdsp/* - $(CC) $(CFLAGS) /c ../dsp/bdsp/bdsp.cpp + $(COMPILE) ../dsp/bdsp/bdsp.cpp ########### ### ppu ### ########### ppu.obj: ../ppu/*.cpp ../ppu/*.h - $(CC) $(CFLAGS) /c ../ppu/ppu.cpp + $(COMPILE) ../ppu/ppu.cpp bppu.obj: ../ppu/bppu/* - $(CC) $(CFLAGS) /c ../ppu/bppu/bppu.cpp + $(COMPILE) ../ppu/bppu/bppu.cpp ################# ### utilities ### ################# reader.obj: ../reader/*.cpp ../reader/*.h - $(CC) $(CFLAGS) /c ../reader/reader.cpp + $(COMPILE) ../reader/reader.cpp cart.obj: ../cart/*.cpp ../cart/*.h - $(CC) $(CFLAGS) /c ../cart/cart.cpp + $(COMPILE) ../cart/cart.cpp cheat.obj: ../cheat/*.cpp ../cheat/*.h - $(CC) $(CFLAGS) /c ../cheat/cheat.cpp + $(COMPILE) ../cheat/cheat.cpp ############ ### snes ### ############ snes.obj: ../snes/* ../snes/video/* ../snes/audio/* ../snes/input/* - $(CC) $(CFLAGS) /c ../snes/snes.cpp + $(COMPILE) ../snes/snes.cpp ##################### ### special chips ### ##################### -srtc.obj: ../chip/srtc/*.cpp ../chip/srtc/*.h - $(CC) $(CFLAGS) /c ../chip/srtc/srtc.cpp +srtc.obj: ../chip/srtc/* + $(COMPILE) ../chip/srtc/srtc.cpp -sdd1.obj: ../chip/sdd1/*.cpp ../chip/sdd1/*.h - $(CC) $(CFLAGS) /c ../chip/sdd1/sdd1.cpp +sdd1.obj: ../chip/sdd1/* + $(COMPILE) ../chip/sdd1/sdd1.cpp -c4.obj: ../chip/c4/*.cpp ../chip/c4/*.h - $(CC) $(CFLAGS) /c ../chip/c4/c4.cpp +c4.obj: ../chip/c4/* + $(COMPILE) ../chip/c4/c4.cpp -dsp2.obj: ../chip/dsp2/*.cpp ../chip/dsp2/*.h - $(CC) $(CFLAGS) /c ../chip/dsp2/dsp2.cpp +dsp1.obj: ../chip/dsp1/* + $(COMPILE) ../chip/dsp1/dsp1.cpp -obc1.obj: ../chip/obc1/*.cpp ../chip/obc1/*.h - $(CC) $(CFLAGS) /c ../chip/obc1/obc1.cpp +dsp2.obj: ../chip/dsp2/* + $(COMPILE) ../chip/dsp2/dsp2.cpp + +obc1.obj: ../chip/obc1/* + $(COMPILE) ../chip/obc1/obc1.cpp ############ ### zlib ### ############ adler32.obj: ../reader/zlib/*.c ../reader/zlib/*.h - $(CC) $(CFLAGS) /c ../reader/zlib/*.c + $(COMPILE) ../reader/zlib/*.c ########### ### jma ### ########### jma.obj: ../reader/jma/*.cpp ../reader/jma/*.h - $(CC) $(CFLAGS) /c ../reader/jma/*.cpp + $(COMPILE) ../reader/jma/*.cpp diff --git a/src/win/audio/dsound.cpp b/src/win/audio/dsound.cpp index 8d22be23..9af01646 100644 --- a/src/win/audio/dsound.cpp +++ b/src/win/audio/dsound.cpp @@ -4,7 +4,7 @@ void AudioDS::run(uint32 sample) { if(data.buffer_pos >= data.samples_per_frame) { uint32 pos, size; void *buffer; - if((bool)config::system.regulate_speed == true) { + if(bool(config::system.regulate_speed) == true) { do { dsb_b->GetCurrentPosition(&pos, 0); data.read_buffer = pos / data.buffer_size; diff --git a/src/win/bsnes.cpp b/src/win/bsnes.cpp index 2dc63305..f776eeb5 100644 --- a/src/win/bsnes.cpp +++ b/src/win/bsnes.cpp @@ -49,6 +49,14 @@ void bSNES::run() { } void bSNES::video_run() { +//temporary code to try and fix input buffer stalls +static int sync_counter = 0; + if(++sync_counter >= 30) { + Sleep(1); + sync_counter = 0; + } +//remove above code after testing + if(r_ppu->status.frames_updated) { char s[512], t[512]; r_ppu->status.frames_updated = false; diff --git a/src/win/config.cpp b/src/win/config.cpp index dda4a5e9..57aefb4b 100644 --- a/src/win/config.cpp +++ b/src/win/config.cpp @@ -13,26 +13,18 @@ Setting System::speed_fastest (&config_file, "system.speed_fastest", "Fastest s struct Video { static Setting renderer; - static Setting profile; - static Setting profile_windowed_default, profile_fullscreen_default; - static Setting profile_0, profile_1, profile_2, profile_3, profile_4; - static Setting profile_5, profile_6, profile_7, profile_8, profile_9; + static Setting profile, fullscreen; + static Setting profile_0, profile_1, profile_2, profile_3; + static Setting profile_4, profile_5, profile_6, profile_7; static Setting use_vram, triple_buffering; static Setting pscanline_intensity, iscanline_intensity; - - struct Filter { - static Setting software, hardware; - } filter; } video; Setting Video::renderer(&config_file, "video.renderer", "Video renderer\n" "\"dd\" (DirectDraw7 -- faster, less features)\n" "\"d3d\" (Direct3D9 -- slower, more features)", "d3d"); -Setting Video::profile(0, "video.profile", "", 2, Setting::DEC); -Setting Video::profile_windowed_default(&config_file, "video.profile_windowed_default", - "Windowed profile to select for Alt+Enter", 2, Setting::DEC); -Setting Video::profile_fullscreen_default(&config_file, "video.profile_fullscreen_default", - "Fullscreen profile to select for Alt+Enter", 9, Setting::DEC); +Setting Video::profile(&config_file, "video.profile", "", 2, Setting::DEC); +Setting Video::fullscreen(0, "video.fullscreen", "", false, Setting::TRUE_FALSE); /* software_filter * hardware_filter @@ -49,22 +41,19 @@ Setting Video::profile_fullscreen_default(&config_file, "video.profile_fullscree * refresh_rate * triple_buffering */ -Setting Video::profile_0(&config_file, "video.profile_0", "Video profile 0 configuration\n" +Setting Video::profile_0(&config_file, "video.profile_0", "Video profile 0-7 configuration\n" "Please use bsnes GUI configuration editor to modify video profile settings\n" "Format: software_filter;hardware_filter;video_standard;multiplier-1;correct_aspect_ratio;\n" - " enable_scanlines;manual_render_size;render_width;render_height;fullscreen;\n" + " enable_scanlines;manual_render_size;render_width;render_height;\n" " resolution_width;resolution_height;refresh_rate;triple_buffering" - "", "0;0;0;0;false;false;false;256;224;false;320;240;0;false"); -Setting Video::profile_1(&config_file, "video.profile_1", "", "0;0;0;1;false;false;false;512;448;false;640;480;0;false"); -Setting Video::profile_2(&config_file, "video.profile_2", "", "0;1;0;1;true;false;false;597;448;false;640;480;0;false"); -Setting Video::profile_3(&config_file, "video.profile_3", "", "0;1;0;2;true;false;false;896;672;false;1024;768;0;false"); -Setting Video::profile_4(&config_file, "video.profile_4", "", "0;1;0;3;true;false;false;1195;896;false;1280;960;0;false"); - -Setting Video::profile_5(&config_file, "video.profile_5", "", "0;0;0;0;false;false;false;256;224;true;320;240;0;false"); -Setting Video::profile_6(&config_file, "video.profile_6", "", "0;0;0;1;false;false;false;512;448;true;640;480;0;false"); -Setting Video::profile_7(&config_file, "video.profile_7", "", "0;1;0;1;true;false;false;597;448;true;640;480;0;false"); -Setting Video::profile_8(&config_file, "video.profile_8", "", "0;1;0;2;true;false;false;896;672;true;1024;768;0;false"); -Setting Video::profile_9(&config_file, "video.profile_9", "", "0;1;0;3;true;false;false;1195;896;true;1280;960;0;false"); + "", "0;0;0;0;false;false;false;256;224;0;0;0;false"); +Setting Video::profile_1(&config_file, "video.profile_1", "", "0;0;0;1;false;false;false;512;448;0;0;0;false"); +Setting Video::profile_2(&config_file, "video.profile_2", "", "0;1;0;1;true;false;false;597;448;0;0;0;false"); +Setting Video::profile_3(&config_file, "video.profile_3", "", "0;1;0;2;true;false;false;896;672;0;0;0;false"); +Setting Video::profile_4(&config_file, "video.profile_4", "", "0;1;0;3;true;false;false;1195;896;0;0;0;false"); +Setting Video::profile_5(&config_file, "video.profile_5", "", "0;0;0;0;false;false;false;256;224;0;0;0;false"); +Setting Video::profile_6(&config_file, "video.profile_6", "", "0;0;0;0;false;false;false;256;224;0;0;0;false"); +Setting Video::profile_7(&config_file, "video.profile_7", "", "0;0;0;0;false;false;false;256;224;0;0;0;false"); Setting Video::use_vram(&config_file, "video.use_vram", "Use Video RAM instead of System RAM", true, Setting::TRUE_FALSE); Setting Video::triple_buffering(&config_file, "video.triple_buffering", "Use triple buffering", false, Setting::TRUE_FALSE); @@ -74,14 +63,6 @@ Setting Video::pscanline_intensity(&config_file, "video.pscanline_intensity", Setting Video::iscanline_intensity(&config_file, "video.iscanline_intensity", "Interlace scanline intensity", 50, Setting::DEC); -Setting Video::Filter::software(&config_file, "video.filter.software", "Software video filter\n" - "0 = Direct\n" - "1 = Scale2x\n", 0, Setting::DEC); - -Setting Video::Filter::hardware(&config_file, "video.filter.hardware", "Hardware video filter\n" - "0 = Pixel\n" - "1 = Bilinear", 1, Setting::DEC); - struct Input { static Setting axis_resistance; struct Joypad1 { diff --git a/src/win/debugger/ui_debugger.cpp b/src/win/debugger/ui_debugger.cpp index 56e30d52..3cd94565 100644 --- a/src/win/debugger/ui_debugger.cpp +++ b/src/win/debugger/ui_debugger.cpp @@ -15,6 +15,24 @@ bool DebugWindow::Event(EventInfo &info) { } else if(bsnes->get_state() == bSNES::STOP) { bsnes->set_state(bSNES::RUN); } + } else if(info.control == &ConsoleMsgDebug) { + output.debug ^= 1; + ConsoleMsgDebug.Check(output.debug); + } else if(info.control == &ConsoleMsgCPU) { + output.cpu ^= 1; + ConsoleMsgCPU.Check(output.cpu); + } else if(info.control == &ConsoleMsgAPU) { + output.apu ^= 1; + ConsoleMsgAPU.Check(output.apu); + } else if(info.control == &ConsoleTrace) { + output.trace ^= 1; + ConsoleTrace.Check(output.trace); + if(output.trace == true) { + output.fp = fopen("trace.log", "wb"); + } else { + fclose(output.fp); + output.fp = 0; + } } } break; @@ -36,9 +54,30 @@ char t[250 * 132]; Console.SetSelection(0, -1); //scroll cursor to bottom of window } -void DebugWindow::Print(const char *str) { +void DebugWindow::Print(uint source, const char *str) { if(!hwnd)return; + switch(source) { + case source::none: + break; + case source::debug: + if(output.debug == false)return; + break; + case source::cpu: + if(output.cpu == false)return; + break; + case source::apu: + if(output.apu == false)return; + break; + } + + if(output.trace == true) { + fprintf(output.fp, "%s\r\n", str); + + //only debug messages are printed to console while tracing is enabled + if(source != source::none && source != source::debug)return; + } + for(uint i = 0; i < buffer.count - 1; i++) { strcpy(buffer.line[i], buffer.line[i + 1]); } @@ -125,7 +164,33 @@ int x = 5, y = 5; APUDisable.Create(this, "visible|left", x + 165, y + 35, 80, 20, " Disable"); y += 66; + ConsoleGroup.Create(this, "visible", x, y, 250, 70, "Console output"); + ConsoleMsgDebug.Create(this, "visible", x + 5, y + 15, 80, 15, "Debug"); + ConsoleMsgCPU.Create(this, "visible", x + 85, y + 15, 80, 15, "CPU"); + ConsoleMsgAPU.Create(this, "visible", x + 165, y + 15, 80, 15, "APU"); + ConsoleTrace.Create(this, "visible", x + 5, y + 35, 240, 15, "Enable trace logging"); + ConsoleTraceMask.Create(this, "visible|disabled", x + 5, y + 50, 240, 15, "Mask duplicate instructions"); + ConsoleMsgDebug.Check(output.debug); + ConsoleMsgCPU.Check(output.cpu); + ConsoleMsgAPU.Check(output.apu); + ConsoleTrace.Check(output.trace); + ConsoleTraceMask.Check(output.trace_mask); + buffer.count = uint(config::debugger.console_lines); buffer.count = (buffer.count < 20) ? 20 : (buffer.count > 250) ? 250 : buffer.count; Clear(); } + +DebugWindow::DebugWindow() { + output.debug = true; + output.cpu = true; + output.apu = true; + + output.fp = 0; + output.trace = false; + output.trace_mask = false; +} + +DebugWindow::~DebugWindow() { + if(output.fp)fclose(output.fp); +} diff --git a/src/win/debugger/ui_debugger.h b/src/win/debugger/ui_debugger.h index 1cf852f3..ec348e51 100644 --- a/src/win/debugger/ui_debugger.h +++ b/src/win/debugger/ui_debugger.h @@ -21,20 +21,39 @@ Button APUSkip; Editbox APUTraceNum; Button APUTrace; Button APUDisable; +Groupbox ConsoleGroup; +Checkbox ConsoleMsgDebug; +Checkbox ConsoleMsgCPU; +Checkbox ConsoleMsgAPU; +Checkbox ConsoleTrace; +Checkbox ConsoleTraceMask; struct { uint count; char line[250][128]; } buffer; +struct { + bool debug; + bool cpu; + bool apu; + + FILE *fp; + bool trace; + bool trace_mask; +} output; + bool Event(EventInfo &info); void Update(); - void Print(const char *str); + void Print(uint source, const char *str); void Clear(); void SetState(uint state); void Show(); void Setup(); + + DebugWindow(); + ~DebugWindow(); } wDebug; diff --git a/src/win/event.cpp b/src/win/event.cpp index 42679dda..67390cfc 100644 --- a/src/win/event.cpp +++ b/src/win/event.cpp @@ -24,7 +24,7 @@ void capture_screenshot() { } void set_video_profile(uint profile) { - if(profile > 9)profile = 0; + if(profile > 7)profile = 0; config::video.profile = profile; uiVideo->update_video_profile(); @@ -37,16 +37,16 @@ void set_video_profile(uint profile) { wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_5, profile == 5); wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_6, profile == 6); wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_7, profile == 7); - wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_8, profile == 8); - wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_9, profile == 9); } void toggle_fullscreen() { - if(uiVideo->active_profile_is_fullscreen() == false) { - set_video_profile(config::video.profile_fullscreen_default); - } else { - set_video_profile(config::video.profile_windowed_default); + config::video.fullscreen.toggle(); + if(bool(config::video.fullscreen) == true) { + wSettings.Hide(); + wAbout.Hide(); + debugger.deactivate(); } + event::set_video_profile(config::video.profile); } void load_rom() { diff --git a/src/win/main.cpp b/src/win/main.cpp index 49238639..c1907460 100644 --- a/src/win/main.cpp +++ b/src/win/main.cpp @@ -21,9 +21,22 @@ va_list args; vsprintf(str, s, args); va_end(args); #ifdef DEBUGGER - wDebug.Print(str); + wDebug.Print(source::none, str); #else - fprintf(stdout, "%s\r\n", str); + fprintf(stdout, "[%3d] %s\r\n", source::none, str); +#endif +} + +void dprintf(uint source, char *s, ...) { +char str[4096]; +va_list args; + va_start(args, s); + vsprintf(str, s, args); + va_end(args); +#ifdef DEBUGGER + wDebug.Print(source, str); +#else + fprintf(stdout, "[%3d] %s\r\n", source, str); #endif } diff --git a/src/win/settings/ui_videosettings.cpp b/src/win/settings/ui_videosettings.cpp index 49a8db2d..284ac758 100644 --- a/src/win/settings/ui_videosettings.cpp +++ b/src/win/settings/ui_videosettings.cpp @@ -3,11 +3,7 @@ bool VideoSettingsWindow::Event(EventInfo &info) { case EVENT_CHANGED: case EVENT_CLICKED: { - if(info.control == &WinProfile) { - config::video.profile_windowed_default = WinProfile.GetSelection(); - } else if(info.control == &FullProfile) { - config::video.profile_fullscreen_default = FullProfile.GetSelection(); - } else if(info.control == &VideoProfile) { + if(info.control == &VideoProfile) { LoadSettings(VideoProfile.GetSelection()); } else if(info.control == &ApplySettings) { SaveSettings(VideoProfile.GetSelection()); @@ -34,7 +30,6 @@ VideoSettings *v = &video_settings[profile]; ManualRenderSize.Check(v->manual_render_size); RenderWidth.SetText("%d", v->render_width); RenderHeight.SetText("%d", v->render_height); - Fullscreen.Check(v->fullscreen); FullResWidth.SetText("%d", v->resolution_width); FullResHeight.SetText("%d", v->resolution_height); FullResHz.SetText("%d", v->refresh_rate); @@ -55,7 +50,6 @@ char t[64 + 1]; v->render_width = strdec(t); RenderHeight.GetText(t, 64); v->render_height = strdec(t); - v->fullscreen = Fullscreen.Checked(); FullResWidth.GetText(t, 64); v->resolution_width = strdec(t); FullResHeight.GetText(t, 64); @@ -74,8 +68,6 @@ char t[64 + 1]; } void VideoSettingsWindow::Show() { - WinProfile.SetSelection(config::video.profile_windowed_default); - FullProfile.SetSelection(config::video.profile_fullscreen_default); VideoProfile.SetSelection(config::video.profile); LoadSettings(config::video.profile); Window::Show(); @@ -86,25 +78,14 @@ void VideoSettingsWindow::Setup() { Header.SetFont(global::font_header); int x = 15, y = 30; - WinProfileLabel.Create(this, "visible", x, y + 3, 135, 15, "Default windowed profile:"); - WinProfile.Create(this, "visible", x + 135, y, 90, 200, - "Profile 0|Profile 1|Profile 2|Profile 3|Profile 4|" - "Profile 5|Profile 6|Profile 7|Profile 8|Profile 9"); - - FullProfileLabel.Create(this, "visible", x + 235, y + 3, 135, 15, "Default fullscreen profile:"); - FullProfile.Create(this, "visible", x + 370, y, 90, 200, - "Profile 0|Profile 1|Profile 2|Profile 3|Profile 4|" - "Profile 5|Profile 6|Profile 7|Profile 8|Profile 9"); - y += 25; - VideoProfileLabel.Create(this, "visible", x, y + 3, 135, 15, "Video profile to configure:"); VideoProfile.Create(this, "visible", x + 135, y, 90, 200, - "Profile 0|Profile 1|Profile 2|Profile 3|Profile 4|" - "Profile 5|Profile 6|Profile 7|Profile 8|Profile 9"); + "Profile 1|Profile 2|Profile 3|Profile 4|" + "Profile 5|Profile 6|Profile 7|Profile 8"); y += 25; - Separator1.Create(this, "visible|sunken", x, y + 5, 460, 3); - y += 15; + Separator1.Create(this, "visible|sunken", x, y + 1, 460, 3); + y += 9; SoftwareFilterLabel.Create(this, "visible", x, y + 3, 85, 15, "Software filter:"); SoftwareFilter.Create(this, "visible", x + 85, y, 140, 200, @@ -134,13 +115,10 @@ int x = 15, y = 30; RenderWidth.Create(this, "visible|edge", x + 90, y, 50, 20); RenderHeightLabel.Create(this, "visible", x + 150, y + 3, 90, 15, "Render height:"); RenderHeight.Create(this, "visible|edge", x + 240, y, 50, 20); - y += 22; + y += 25; - Separator2.Create(this, "visible|sunken", x, y + 5, 460, 3); - y += 15; - - Fullscreen.Create(this, "visible|auto", x, y, 460, 15, "Fullscreen (hit Esc or F11 to exit)"); - y += 15; + Separator1.Create(this, "visible|sunken", x, y, 460, 3); + y += 8; FullResWidthLabel.Create(this, "visible", x, y + 3, 90, 15, "Resolution width:"); FullResWidth.Create(this, "visible|edge", x + 90, y, 50, 20); @@ -157,7 +135,7 @@ int x = 15, y = 30; SelectProfile.Create(this, "visible", x + 125, y, 120, 25, "Set as active profile"); y += 25; - for(int i = 0; i < 10; i++) { + for(int i = 0; i < 8; i++) { load_video_settings(i); } } diff --git a/src/win/settings/ui_videosettings.h b/src/win/settings/ui_videosettings.h index 64348de0..bb47a951 100644 --- a/src/win/settings/ui_videosettings.h +++ b/src/win/settings/ui_videosettings.h @@ -1,10 +1,6 @@ class VideoSettingsWindow : public Window { public: Label Header; -Label WinProfileLabel; -Combobox WinProfile; -Label FullProfileLabel; -Combobox FullProfile; Label VideoProfileLabel; Combobox VideoProfile; Label Separator1; @@ -24,7 +20,6 @@ Editbox RenderWidth; Label RenderHeightLabel; Editbox RenderHeight; Label Separator2; -Checkbox Fullscreen; Label FullResWidthLabel; Editbox FullResWidth; Label FullResHeightLabel; diff --git a/src/win/ui.h b/src/win/ui.h index 16762c44..6fdec92a 100644 --- a/src/win/ui.h +++ b/src/win/ui.h @@ -26,12 +26,9 @@ MENU_SETTINGS, MENU_SETTINGS_VIDEOPROFILE_2, MENU_SETTINGS_VIDEOPROFILE_3, MENU_SETTINGS_VIDEOPROFILE_4, - //--- MENU_SETTINGS_VIDEOPROFILE_5, MENU_SETTINGS_VIDEOPROFILE_6, MENU_SETTINGS_VIDEOPROFILE_7, - MENU_SETTINGS_VIDEOPROFILE_8, - MENU_SETTINGS_VIDEOPROFILE_9, MENU_SETTINGS_FRAMESKIP, MENU_SETTINGS_FRAMESKIP_0, //--- diff --git a/src/win/ui_main.cpp b/src/win/ui_main.cpp index 19108a7d..ca355bef 100644 --- a/src/win/ui_main.cpp +++ b/src/win/ui_main.cpp @@ -47,44 +47,37 @@ bool MainWindow::Event(EventInfo &info) { uint key = info.control_id; bool ctrl = uiInput->keydown(keymap->lctrl) || uiInput->keydown(keymap->rctrl); if(key == keymap->esc) { - if(uiVideo->settings.fullscreen == false) { + if(bool(config::video.fullscreen) == false) { ShowMenu(!MenuVisible()); Center(); } else { - event::set_video_profile(config::video.profile_windowed_default); + config::video.fullscreen = false; + event::set_video_profile(config::video.profile); } } else if(key == keymap->f11) { - if(uiVideo->settings.fullscreen == false) { - event::set_video_profile(config::video.profile_fullscreen_default); - } else { - event::set_video_profile(config::video.profile_windowed_default); - } + event::toggle_fullscreen(); } else if(key == keymap->f12) { if(bsnes->get_state() == bSNES::RUN) { bsnes->set_state(bSNES::STOP); } else if(bsnes->get_state() == bSNES::STOP) { bsnes->set_state(bSNES::RUN); } - } else if(key == keymap->numpad_0 && ctrl) { + } else if(key == keymap->num_1 && ctrl) { event::set_video_profile(0); - } else if(key == keymap->numpad_1 && ctrl) { + } else if(key == keymap->num_2 && ctrl) { event::set_video_profile(1); - } else if(key == keymap->numpad_2 && ctrl) { + } else if(key == keymap->num_3 && ctrl) { event::set_video_profile(2); - } else if(key == keymap->numpad_3 && ctrl) { + } else if(key == keymap->num_4 && ctrl) { event::set_video_profile(3); - } else if(key == keymap->numpad_4 && ctrl) { + } else if(key == keymap->num_5 && ctrl) { event::set_video_profile(4); - } else if(key == keymap->numpad_5 && ctrl) { + } else if(key == keymap->num_6 && ctrl) { event::set_video_profile(5); - } else if(key == keymap->numpad_6 && ctrl) { + } else if(key == keymap->num_7 && ctrl) { event::set_video_profile(6); - } else if(key == keymap->numpad_7 && ctrl) { + } else if(key == keymap->num_8 && ctrl) { event::set_video_profile(7); - } else if(key == keymap->numpad_8 && ctrl) { - event::set_video_profile(8); - } else if(key == keymap->numpad_9 && ctrl) { - event::set_video_profile(9); } else if((key == keymap->minus && !ctrl) || key == keymap->numpad_minus) { if(frameskip > 0)SetFrameskip(frameskip - 1); } else if((key == keymap->plus && !ctrl) || key == keymap->numpad_plus) { @@ -156,9 +149,7 @@ bool MainWindow::Event(EventInfo &info) { case MENU_SETTINGS_VIDEOPROFILE_4: case MENU_SETTINGS_VIDEOPROFILE_5: case MENU_SETTINGS_VIDEOPROFILE_6: - case MENU_SETTINGS_VIDEOPROFILE_7: - case MENU_SETTINGS_VIDEOPROFILE_8: - case MENU_SETTINGS_VIDEOPROFILE_9: { + case MENU_SETTINGS_VIDEOPROFILE_7: { event::set_video_profile(info.control_id - MENU_SETTINGS_VIDEOPROFILE_0); } break; @@ -258,16 +249,14 @@ char t[128]; AddMenuGroup("&Settings"); AddMenuGroup("&Video Profile"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_0, "Profile &0"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_1, "Profile &1"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_2, "Profile &2"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_3, "Profile &3"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_4, "Profile &4"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_5, "Profile &5"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_6, "Profile &6"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_7, "Profile &7"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_8, "Profile &8"); - AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_9, "Profile &9"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_0, "Profile &1"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_1, "Profile &2"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_2, "Profile &3"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_3, "Profile &4"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_4, "Profile &5"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_5, "Profile &6"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_6, "Profile &7"); + AddMenuItem(MENU_SETTINGS_VIDEOPROFILE_7, "Profile &8"); EndMenuGroup(); AddMenuGroup("&Frameskip"); @@ -325,7 +314,7 @@ char t[128]; CheckMenuItem(MENU_SETTINGS_MUTE, config::snes.mute); CheckMenuItem(MENU_SETTINGS_SPEED_REGULATION_ENABLE, config::system.regulate_speed); - event::set_video_profile(config::video.profile_windowed_default); + event::set_video_profile(config::video.profile); SetFrameskip(0); SetRegulationSpeed(2); diff --git a/src/win/video/d3d.cpp b/src/win/video/d3d.cpp index b5a0f8ab..f0c55607 100644 --- a/src/win/video/d3d.cpp +++ b/src/win/video/d3d.cpp @@ -14,37 +14,39 @@ HRESULT hr; } memset(&presentation, 0, sizeof(presentation)); - presentation.Flags = 0; - if(settings.triple_buffering == false) { - presentation.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + presentation.Flags = D3DPRESENTFLAG_VIDEO; + presentation.SwapEffect = (settings.triple_buffering == true) ? + D3DSWAPEFFECT_FLIP : D3DSWAPEFFECT_DISCARD; + presentation.hDeviceWindow = wMain.hwnd; + presentation.BackBufferCount = (settings.triple_buffering == true) ? 2 : 1; + presentation.MultiSampleType = D3DMULTISAMPLE_NONE; + presentation.MultiSampleQuality = 0; + presentation.EnableAutoDepthStencil = false; + presentation.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentation.PresentationInterval = (settings.triple_buffering == true) ? + D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + presentation.FullScreen_RefreshRateInHz = settings.refresh_rate; + + if(bool(config::video.fullscreen) == false) { + presentation.Windowed = true; + presentation.BackBufferFormat = D3DFMT_UNKNOWN; + presentation.BackBufferWidth = 0; + presentation.BackBufferHeight = 0; + } else { + presentation.Windowed = false; + presentation.BackBufferFormat = D3DFMT_R5G6B5; + presentation.BackBufferWidth = settings.resolution_width; + presentation.BackBufferHeight = settings.resolution_height; } - presentation.Flags |= D3DPRESENTFLAG_VIDEO; - presentation.Windowed = (settings.fullscreen == false); - presentation.SwapEffect = (settings.triple_buffering == true) ? - D3DSWAPEFFECT_FLIP : D3DSWAPEFFECT_DISCARD; - presentation.hDeviceWindow = wMain.hwnd; - presentation.BackBufferFormat = (settings.fullscreen) ? D3DFMT_X8R8G8B8 : D3DFMT_UNKNOWN; - presentation.BackBufferWidth = (settings.fullscreen) ? settings.resolution_width : 0; - presentation.BackBufferHeight = (settings.fullscreen) ? settings.resolution_height : 0; - presentation.BackBufferCount = (settings.triple_buffering == true) ? 2 : 1; - presentation.MultiSampleType = D3DMULTISAMPLE_NONE; - presentation.MultiSampleQuality = 0; - presentation.EnableAutoDepthStencil = false; - presentation.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentation.PresentationInterval = (settings.triple_buffering == true) ? - D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; - presentation.FullScreen_RefreshRateInHz = (settings.fullscreen == true) ? settings.refresh_rate : D3DPRESENT_RATE_DEFAULT; hr = lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wMain.hwnd, - D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentation, &device); + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device); if(hr != D3D_OK) { alert("Failed to create Direct3D9 device"); return false; } -/***** - * detect device capabilities - *****/ +//detect device capabilities device->GetDeviceCaps(&d3dcaps); if(d3dcaps.MaxTextureWidth < 1024 || d3dcaps.MaxTextureWidth < 1024) { alert("Error: Direct3D renderer requires that the video card supports textures up to 1024x1024.\n" @@ -52,8 +54,8 @@ HRESULT hr; "", d3dcaps.MaxTextureWidth, d3dcaps.MaxTextureHeight); return false; } - caps.dynamic = !!(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES); - caps.addresswrap = !!(d3dcaps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP); + caps.dynamic = bool(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES); + caps.addresswrap = bool(d3dcaps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP); caps.stretchrect = (d3dcaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) && (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT) && (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) && @@ -74,8 +76,7 @@ HRESULT hr; flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; } -//this is required to allow window menu to be visible in fullscreen mode - device->SetDialogBoxMode(settings.triple_buffering == false); + device->SetDialogBoxMode(false); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); diff --git a/src/win/video/ddraw.cpp b/src/win/video/ddraw.cpp index 94178560..bb860163 100644 --- a/src/win/video/ddraw.cpp +++ b/src/win/video/ddraw.cpp @@ -1,5 +1,3 @@ -#include "ddraw_present.cpp" - bool VideoDD::update_video_profile() { term(); @@ -10,7 +8,7 @@ bool VideoDD::update_video_profile() { lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7); SafeRelease(lpdd); - if(settings.fullscreen) { + if(bool(config::video.fullscreen) == true) { lpdd7->SetCooperativeLevel(wMain.hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); lpdd7->SetDisplayMode(settings.resolution_width, settings.resolution_height, 16, settings.refresh_rate, 0); } else { @@ -105,13 +103,78 @@ DDBLTFX fx; backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); surface->Blt (0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); - if(settings.fullscreen == true) { + if(bool(config::video.fullscreen) == true) { screen->Flip(0, DDFLIP_WAIT); backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); screen->Flip(0, DDFLIP_WAIT); } } +//create screen and backbuffer surfaces +void VideoDD::create_presentation() { + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + + if(bool(config::video.fullscreen) == true) { + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.dwBackBufferCount = (settings.triple_buffering == true) ? 2 : 1; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; + lpdd7->CreateSurface(&ddsd, &screen, 0); + + memset(&ddscaps, 0, sizeof(DDSCAPS2)); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + screen->GetAttachedSurface(&ddscaps, &backbuffer); + } else { + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + lpdd7->CreateSurface(&ddsd, &screen, 0); + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if(bool(config::video.use_vram) == true) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + } else { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + + ddsd.dwWidth = settings.render_width; + ddsd.dwHeight = settings.render_height; + lpdd7->CreateSurface(&ddsd, &backbuffer, 0); + } +} + +void VideoDD::redraw() { +HRESULT hr; +RECT rd, rs; + snes->get_video_info(&vi); + SetRect(&rs, 0, 0, vi.width, vi.height); + + if(bool(config::video.fullscreen) == true) { + SetRect(&rd, settings.rx, settings.ry, settings.rx + settings.rw, settings.ry + settings.rh); + backbuffer->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); + hr = screen->Flip(0, DDFLIP_WAIT); + } else { + POINT p = { 0, 0 }; + ClientToScreen(wMain.hwnd, &p); + GetClientRect(wMain.hwnd, &rd); + OffsetRect(&rd, p.x, p.y); + + hr = screen->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); + } + + if(hr == DDERR_SURFACELOST) { + screen->Restore(); + backbuffer->Restore(); + surface->Restore(); + } +} + +void VideoDD::update() { + redraw(); +} + void VideoDD::init() {} void VideoDD::term() { diff --git a/src/win/video/ddraw_present.cpp b/src/win/video/ddraw_present.cpp deleted file mode 100644 index eda7bb3a..00000000 --- a/src/win/video/ddraw_present.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//create screen and backbuffer surfaces -void VideoDD::create_presentation() { - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - - if(settings.fullscreen == true) { - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - ddsd.dwBackBufferCount = 2; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; - lpdd7->CreateSurface(&ddsd, &screen, 0); - - memset(&ddscaps, 0, sizeof(DDSCAPS2)); - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; - screen->GetAttachedSurface(&ddscaps, &backbuffer); - } else { - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - lpdd7->CreateSurface(&ddsd, &screen, 0); - - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - if(bool(config::video.use_vram) == true) { - ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; - } else { - ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - } - - ddsd.dwWidth = settings.render_width; - ddsd.dwHeight = settings.render_height; - lpdd7->CreateSurface(&ddsd, &backbuffer, 0); - } -} - -void VideoDD::redraw() { -HRESULT hr; -RECT rd, rs; - snes->get_video_info(&vi); - SetRect(&rs, 0, 0, vi.width, vi.height); - - if(settings.fullscreen == true) { - SetRect(&rd, settings.rx, settings.ry, settings.rx + settings.rw, settings.ry + settings.rh); - backbuffer->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); - hr = screen->Flip(0, DDFLIP_WAIT); - } else { - POINT p = { 0, 0 }; - ClientToScreen(wMain.hwnd, &p); - GetClientRect(wMain.hwnd, &rd); - OffsetRect(&rd, p.x, p.y); - - hr = screen->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); - } - - if(hr == DDERR_SURFACELOST) { - screen->Restore(); - backbuffer->Restore(); - surface->Restore(); - } -} - -void VideoDD::update() { - redraw(); -} diff --git a/src/win/video/video.cpp b/src/win/video/video.cpp index 3f4f7b73..55cf11a2 100644 --- a/src/win/video/video.cpp +++ b/src/win/video/video.cpp @@ -1,6 +1,6 @@ void load_video_settings(uint profile) { string line, part; - if(profile > 9)profile = 0; + if(profile > 7)profile = 0; switch(profile) { case 0: strcpy(line, config::video.profile_0.sget()); break; @@ -11,8 +11,6 @@ string line, part; case 5: strcpy(line, config::video.profile_5.sget()); break; case 6: strcpy(line, config::video.profile_6.sget()); break; case 7: strcpy(line, config::video.profile_7.sget()); break; - case 8: strcpy(line, config::video.profile_8.sget()); break; - case 9: strcpy(line, config::video.profile_9.sget()); break; } split(part, ";", line); @@ -27,17 +25,19 @@ int i = 0; v->manual_render_size = strmatch(part[i++], "true"); v->render_width = strdec(part[i++]); v->render_height = strdec(part[i++]); - v->fullscreen = strmatch(part[i++], "true"); v->resolution_width = strdec(part[i++]); v->resolution_height = strdec(part[i++]); v->refresh_rate = strdec(part[i++]); v->triple_buffering = strmatch(part[i++], "true"); + + if(v->render_width < 256)v->render_width = 256; + if(v->render_height < 224)v->render_height = 224; } void save_video_settings(uint profile) { string line; char part[64]; - if(profile > 9)profile = 0; + if(profile > 7)profile = 0; VideoSettings *v = &video_settings[profile]; strcpy(line, ""); @@ -50,7 +50,6 @@ VideoSettings *v = &video_settings[profile]; sprintf(part, "%s", v->manual_render_size ? "true" : "false"); strcat(line, part); strcat(line, ";"); sprintf(part, "%d", v->render_width); strcat(line, part); strcat(line, ";"); sprintf(part, "%d", v->render_height); strcat(line, part); strcat(line, ";"); - sprintf(part, "%s", v->fullscreen ? "true" : "false"); strcat(line, part); strcat(line, ";"); sprintf(part, "%d", v->resolution_width); strcat(line, part); strcat(line, ";"); sprintf(part, "%d", v->resolution_height); strcat(line, part); strcat(line, ";"); sprintf(part, "%d", v->refresh_rate); strcat(line, part); strcat(line, ";"); @@ -65,14 +64,12 @@ VideoSettings *v = &video_settings[profile]; case 5: config::video.profile_5.sset(strptr(line)); break; case 6: config::video.profile_6.sset(strptr(line)); break; case 7: config::video.profile_7.sset(strptr(line)); break; - case 8: config::video.profile_8.sset(strptr(line)); break; - case 9: config::video.profile_9.sset(strptr(line)); break; } } void Video::update_video_settings() { uint profile = uint(config::video.profile); - if(profile > 9)profile = 0; + if(profile > 7)profile = 0; load_video_settings(profile); VideoSettings *v = &video_settings[profile]; @@ -94,13 +91,12 @@ VideoSettings *v = &video_settings[profile]; } settings.hardware_filter = v->hardware_filter; - settings.fullscreen = v->fullscreen; settings.triple_buffering = v->triple_buffering; settings.enable_scanlines = v->enable_scanlines; - if(settings.fullscreen == true) { - settings.resolution_width = v->resolution_width; - settings.resolution_height = v->resolution_height; + if(bool(config::video.fullscreen) == true) { + settings.resolution_width = (v->resolution_width) ? v->resolution_width : GetScreenWidth(); + settings.resolution_height = (v->resolution_height) ? v->resolution_height : GetScreenHeight(); settings.refresh_rate = v->refresh_rate; } else { settings.resolution_width = settings.render_width; @@ -119,7 +115,7 @@ VideoSettings *v = &video_settings[profile]; void Video::update_window() { string t; - if(settings.fullscreen == true) { + if(bool(config::video.fullscreen) == true) { strcpy(t, "topmost|popup"); if(wMain.Visible())strcat(t, "|visible"); wMain.HideMenu(); diff --git a/src/win/video/video.h b/src/win/video/video.h index 405837ee..6a127ea5 100644 --- a/src/win/video/video.h +++ b/src/win/video/video.h @@ -13,12 +13,11 @@ struct VideoSettings { bool manual_render_size; uint render_width; uint render_height; - bool fullscreen; uint resolution_width; uint resolution_height; uint refresh_rate; bool triple_buffering; -} video_settings[10]; +} video_settings[8]; void load_video_settings(uint profile); void save_video_settings(uint profile); @@ -32,7 +31,6 @@ struct { uint render_height; uint hardware_filter; - bool fullscreen; bool triple_buffering; bool enable_scanlines; @@ -47,7 +45,6 @@ struct { } settings; void update_video_settings(); void update_window(); - bool active_profile_is_fullscreen() { return settings.fullscreen; } virtual uint16 *lock(uint32 &pitch) = 0; virtual void unlock() = 0;

@3$EzmOPGO);0c(dFUJLZ1OI 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%0A8If0QMIEQ)>Zq)H_bCE+&&(0GNrZMy6GX6af47 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